diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..fba95be3d --- /dev/null +++ b/.env.example @@ -0,0 +1,35 @@ +# ========================== +# Docker Images +# ========================== +POSTGRES_IMAGE=postgres:18 +BACKEND_IMAGE=bmv_server +FRONTEND_IMAGE=bmv_frontend + +# ========================== +# Container Names +# ========================== +POSTGRES_CONTAINER_NAME=postgres_bmv +BACKEND_CONTAINER_NAME=bmv_backend +FRONTEND_CONTAINER_NAME=bmv_frontend + +# ========================== +# PostgreSQL +# ========================== +DATABASE_URL="postgresql://postgres:123456@localhost:5432/bmv_dev" +# ========================== +# Backend +# ========================== +BACKEND_PORT=3000 +BASE_URL=http://localhost:3000 +NODE_ENV=production +JWT_SECRET=change_me_to_a_long_random_secret +RAZORPAY_KEY_ID='razor_pay_id' +RAZORPAY_SECRET='razor_pay_secret' + +# ========================== +# Frontend +# ========================== +FRONTEND_PORT=5173 + +# Uploads +UPLOAD_DIR=/app/uploads diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..2eea525d8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/backend/.dockerignore b/backend/.dockerignore new file mode 100644 index 000000000..cac5b2ba3 --- /dev/null +++ b/backend/.dockerignore @@ -0,0 +1,5 @@ +node_modules +dist +*.log +*.md +.git \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 000000000..3761a0194 --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,61 @@ +# compiled output +/dist +/node_modules +/build + +# Logs +logs +*.log +npm-debug.log* +pnpm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +# Tests +/coverage +/.nyc_output + +# IDEs and editors +/.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# IDE - VSCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# temp directory +.temp +.tmp + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +/src/infra/database/prisma/generated/prisma +some.txt +REST +uploads \ No newline at end of file diff --git a/backend/.prettierrc b/backend/.prettierrc new file mode 100644 index 000000000..a20502b7f --- /dev/null +++ b/backend/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} diff --git a/backend/BookMyVenue.pdf b/backend/BookMyVenue.pdf new file mode 100644 index 000000000..d7f6359d8 Binary files /dev/null and b/backend/BookMyVenue.pdf differ diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 000000000..6b3af6d64 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,22 @@ +FROM node:22-alpine + +# Set the working directory inside the container +WORKDIR /usr/src/app + +# Copy package.json and package-lock.json to the working directory +COPY package*.json ./ + +# Install the application dependencies +RUN npm install + +# Copy the rest of the application files +COPY . . + +# Build the NestJS application +RUN npm run build + +# Expose the application port +EXPOSE 3000 + +# Command to run the application +CMD ["node", "dist/src/main.js"] \ No newline at end of file diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 000000000..8f0f65f7e --- /dev/null +++ b/backend/README.md @@ -0,0 +1,98 @@ +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Discord +Backers on Open Collective +Sponsors on Open Collective + Donate us + Support us + Follow us on Twitter +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Project setup + +```bash +$ npm install +``` + +## Compile and run the project + +```bash +# development +$ npm run start + +# watch mode +$ npm run start:dev + +# production mode +$ npm run start:prod +``` + +## Run tests + +```bash +# unit tests +$ npm run test + +# e2e tests +$ npm run test:e2e + +# test coverage +$ npm run test:cov +``` + +## Deployment + +When you're ready to deploy your NestJS application to production, there are some key steps you can take to ensure it runs as efficiently as possible. Check out the [deployment documentation](https://docs.nestjs.com/deployment) for more information. + +If you are looking for a cloud-based platform to deploy your NestJS application, check out [Mau](https://mau.nestjs.com), our official platform for deploying NestJS applications on AWS. Mau makes deployment straightforward and fast, requiring just a few simple steps: + +```bash +$ npm install -g @nestjs/mau +$ mau deploy +``` + +With Mau, you can deploy your application in just a few clicks, allowing you to focus on building features rather than managing infrastructure. + +## Resources + +Check out a few resources that may come in handy when working with NestJS: + +- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework. +- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy). +- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/). +- Deploy your application to AWS with the help of [NestJS Mau](https://mau.nestjs.com) in just a few clicks. +- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com). +- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com). +- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs). +- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com). + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myƛliwiec](https://twitter.com/kammysliwiec) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE). diff --git a/backend/eslint.config.mjs b/backend/eslint.config.mjs new file mode 100644 index 000000000..dcfe62d8c --- /dev/null +++ b/backend/eslint.config.mjs @@ -0,0 +1,108 @@ +// @ts-check + +import eslint from '@eslint/js'; +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'; +import globals from 'globals'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + { + ignores: [ + 'dist', + 'coverage', + 'generated', + 'node_modules', + 'eslint.config.mjs', + ], + }, + + eslint.configs.recommended, + + ...tseslint.configs.recommendedTypeChecked, + + eslintPluginPrettierRecommended, + + { + languageOptions: { + globals: { + ...globals.node, + ...globals.jest, + }, + + sourceType: 'module', + + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + + rules: { + /* + * Typescript + */ + '@typescript-eslint/no-explicit-any': 'warn', + + '@typescript-eslint/no-floating-promises': 'error', + + '@typescript-eslint/no-misused-promises': 'error', + + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], + + '@typescript-eslint/consistent-type-imports': [ + 'error', + { + prefer: 'type-imports', + fixStyle: 'inline-type-imports', + }, + ], + + '@typescript-eslint/consistent-type-definitions': [ + 'error', + 'interface', + ], + + '@typescript-eslint/no-unnecessary-condition': 'error', + + '@typescript-eslint/no-confusing-void-expression': 'error', + + '@typescript-eslint/await-thenable': 'error', + + '@typescript-eslint/require-await': 'error', + + /* + * General + */ + 'eqeqeq': [ + 'error', + 'always', + ], + + 'curly': [ + 'error', + 'all', + ], + + 'no-console': 'error', + + 'no-debugger': 'error', + + /* + * Prettier + */ + 'prettier/prettier': [ + 'error', + { + endOfLine: 'auto', + }, + ], + }, + }, +); \ No newline at end of file diff --git a/backend/nest-cli.json b/backend/nest-cli.json new file mode 100644 index 000000000..f9aa683b1 --- /dev/null +++ b/backend/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/backend/package-lock.json b/backend/package-lock.json new file mode 100644 index 000000000..ac2621c26 --- /dev/null +++ b/backend/package-lock.json @@ -0,0 +1,12103 @@ +{ + "name": "backend", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "backend", + "version": "0.0.1", + "license": "UNLICENSED", + "dependencies": { + "@nestjs/common": "^11.0.1", + "@nestjs/core": "^11.0.1", + "@nestjs/platform-express": "^11.0.1", + "@nestjs/swagger": "^11.4.4", + "@novu/api": "^3.17.0", + "@prisma/adapter-pg": "^7.8.0", + "@prisma/client": "^7.8.0", + "argon2": "^0.44.0", + "audit": "^0.0.6", + "dotenv": "^17.4.2", + "envalid": "^8.2.0", + "fix": "^0.0.6", + "jsonwebtoken": "^9.0.3", + "razorpay": "^2.9.6", + "reflect-metadata": "^0.2.2", + "rxjs": "^7.8.1", + "zod": "^4.4.3" + }, + "devDependencies": { + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "^9.18.0", + "@nestjs/cli": "^11.0.0", + "@nestjs/schematics": "^11.0.0", + "@nestjs/testing": "^11.0.1", + "@types/express": "^5.0.0", + "@types/jest": "^30.0.0", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.1.0", + "@types/node": "^24.0.0", + "@types/supertest": "^7.0.0", + "eslint": "^9.18.0", + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.2", + "globals": "^17.0.0", + "jest": "^30.0.0", + "prettier": "^3.4.2", + "prisma": "^7.8.0", + "source-map-support": "^0.5.21", + "supertest": "^7.0.0", + "ts-jest": "^29.2.5", + "ts-loader": "^9.5.2", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "tsx": "^4.22.4", + "typescript": "^5.7.3", + "typescript-eslint": "^8.20.0" + } + }, + "node_modules/@angular-devkit/core": { + "version": "19.2.24", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.24.tgz", + "integrity": "sha512-Kd49warf6U/EyWe5BszF/eebN3zQ3bk7tgfEljAw8q/rX95UUtriJubWvp6pgzHfzBA4jwq8f+QiNZB8eBEXPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.18.0", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.4", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/core/node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/core/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@angular-devkit/core/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "19.2.24", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.24.tgz", + "integrity": "sha512-lnw+ZM1Io+cJAkReC0NPDjqObL8NtKzKIkdgEEKC8CUmkhurYhedbicN8Y8NYHgG1uLd2GozW3+/QqPRZaN+Lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.24", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli": { + "version": "19.2.24", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-19.2.24.tgz", + "integrity": "sha512-bsStZQG67J1HBqTmWxtIcobvgrn32L4UOdL7hGyOru5VxDWPNA8pRnDYavT3hnJeBkJYPoQIw8u7Dm0ecoQprw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.24", + "@angular-devkit/schematics": "19.2.24", + "@inquirer/prompts": "7.3.2", + "ansi-colors": "4.1.3", + "symbol-observable": "4.0.0", + "yargs-parser": "21.1.1" + }, + "bin": { + "schematics": "bin/schematics.js" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/@inquirer/prompts": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.3.2.tgz", + "integrity": "sha512-G1ytyOoHh5BphmEBxSwALin3n1KGNYB6yImbICcRQdzXfOGbuJ9Jske/Of5Sebk339NSGGNfUshnzK8YWkTPsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.1.2", + "@inquirer/confirm": "^5.1.6", + "@inquirer/editor": "^4.2.7", + "@inquirer/expand": "^4.0.9", + "@inquirer/input": "^4.1.6", + "@inquirer/number": "^3.0.9", + "@inquirer/password": "^4.0.9", + "@inquirer/rawlist": "^4.0.9", + "@inquirer/search": "^3.0.9", + "@inquirer/select": "^4.0.9" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/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/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/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/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@borewit/text-codec": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", + "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@electric-sql/pglite": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.4.1.tgz", + "integrity": "sha512-mZ9NzzUSYPOCnxHH1oAHPRzoMFJHY472raDKwXl/+6oPbpdJ7g8LsCN4FSaIIfkiCKHhb3iF/Zqo3NYxaIhU7Q==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@electric-sql/pglite-socket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.1.1.tgz", + "integrity": "sha512-p2hoXw3Z3LQHwTeikdZNsFBOvXGqKY2hk51BBw+8NKND8eoH+8LFOtW9Z8CQKmTJ2qqGYu82ipqiyFZOTTXNfw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "pglite-server": "dist/scripts/server.js" + }, + "peerDependencies": { + "@electric-sql/pglite": "0.4.1" + } + }, + "node_modules/@electric-sql/pglite-tools": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.3.1.tgz", + "integrity": "sha512-C+T3oivmy9bpQvSxVqXA1UDY8cB9Eb9vZHL9zxWwEUfDixbXv4G3r2LjoTdR33LD8aomR3O9ZXEO3XEwr/cUCA==", + "devOptional": true, + "license": "Apache-2.0", + "peerDependencies": { + "@electric-sql/pglite": "0.4.1" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "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/eslint-utils/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-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "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.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "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.1", + "minimatch": "^3.1.5", + "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/eslintrc/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/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "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.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@hono/node-server": { + "version": "1.19.11", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.11.tgz", + "integrity": "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.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/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", + "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.23", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", + "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/external-editor": "^1.0.3", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", + "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", + "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", + "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", + "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", + "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.3.2", + "@inquirer/confirm": "^5.1.21", + "@inquirer/editor": "^4.2.23", + "@inquirer/expand": "^4.0.23", + "@inquirer/input": "^4.3.1", + "@inquirer/number": "^3.0.23", + "@inquirer/password": "^4.0.23", + "@inquirer/rawlist": "^4.1.11", + "@inquirer/search": "^3.2.2", + "@inquirer/select": "^4.4.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", + "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", + "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", + "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "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/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/@isaacs/cliui/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/@isaacs/cliui/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/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/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/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.4.1.tgz", + "integrity": "sha512-v3bhyxUh9Hgmo5p6hAOXe14/R3ZxZDOsvHleh4B07z3m/x4/ngPUXEm9XwK4sF4u+f+P2ORb0Ge+MgpaqRMVDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.4.1", + "jest-util": "30.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core": { + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.4.2.tgz", + "integrity": "sha512-TZJA6cPJUFxoWhxaLo8t0VX/MZX2wPWr0uIDvLSHIvN4gu9h02vSzqI2kBADG1ExqQlC+cY09xKMSreivvrChQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.4.1", + "@jest/pattern": "30.4.0", + "@jest/reporters": "30.4.1", + "@jest/test-result": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.4.1", + "jest-config": "30.4.2", + "jest-haste-map": "30.4.1", + "jest-message-util": "30.4.1", + "jest-regex-util": "30.4.0", + "jest-resolve": "30.4.1", + "jest-resolve-dependencies": "30.4.2", + "jest-runner": "30.4.2", + "jest-runtime": "30.4.2", + "jest-snapshot": "30.4.1", + "jest-util": "30.4.1", + "jest-validate": "30.4.1", + "jest-watcher": "30.4.1", + "pretty-format": "30.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.4.0.tgz", + "integrity": "sha512-zOpzlfUs45l6u7jm39qr87JCHUDsaeCtvL+kQe/Vn9jSnRB4/5IPXISm0h9I1vZW/o00Kn4UTJ2MOlhnUGwv3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.4.1.tgz", + "integrity": "sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "jest-mock": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.4.1.tgz", + "integrity": "sha512-ginrj6TMgh2GshLUGCjO94Ptx9HhdZA/I6A9iUfyeLKFtdAjnKzHDgzgP9HYQgbxM1lbXScQ2eUBz2lGeVDPWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.4.1", + "jest-snapshot": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.4.1.tgz", + "integrity": "sha512-ZBn5CglH8fBsQsvs4VWNzD4aWfUYks+IdOOQU3MEK71ol/BcVm+P+rtb1KpiFBpSWSCE27uOahyyf1vfqOVbcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.4.1.tgz", + "integrity": "sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@sinonjs/fake-timers": "^15.4.0", + "@types/node": "*", + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-util": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.4.1.tgz", + "integrity": "sha512-ZbuY4cmXC8DkxYjfvT2DbcHWL2T6vmsMhXCDcmTB2T0y0gaezBI77ufq5ZAIdcRkYZ7NEQEDg1xFeKbxUJ5v5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.4.1", + "@jest/expect": "30.4.1", + "@jest/types": "30.4.1", + "jest-mock": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.4.0.tgz", + "integrity": "sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.4.1.tgz", + "integrity": "sha512-/SnkPCzEQpUaBH81kjdEdDdo2WZl5hxw+BmLDGWjRkm8o7XlhjwsU36cqwe5PGBE5WYpBvDzRSdXx9rbGuJtNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.4.1", + "@jest/test-result": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.5.0", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.4.1", + "jest-util": "30.4.1", + "jest-worker": "30.4.1", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/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/@jest/reporters/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/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/@jest/schemas": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz", + "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.4.1.tgz", + "integrity": "sha512-ObY4ljvQ95mt6iwKtVLetR/4yXiAgl3H4nJxhztr0MTjrN97TwDYrnCp/kF60Ec9HdhkWTHSu+Hg05aXfngpOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.4.1.tgz", + "integrity": "sha512-/ZG7pgEiOmmWkN9TplKbOu4id2N5lh7FHwRwlkgBVAzGdRH+OkkQ8wX/kIxg4zmd3ZQvAL1RwL2yWsvNYYECTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.4.1", + "@jest/types": "30.4.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.4.1.tgz", + "integrity": "sha512-PeYE+4td5rKjoRPxztObrXU+H8hsjZfxKMXOcmrr34JerSyB/ROOxbbicz8B7A5j9R9VayDnVPvBmedqCsFCdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.4.1", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.4.1.tgz", + "integrity": "sha512-Wz0LyktlTvRefoymh+n64hQ84KNXsRGcwdoZ8CSa0Ea+fgYcHZlnk+hDP7v2MS7il2bQ5uTEIxf4/NNfhMN4KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.4.1", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.4.1", + "jest-regex-util": "30.4.0", + "jest-util": "30.4.1", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/types": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.4.1.tgz", + "integrity": "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.4.0", + "@jest/schemas": "30.4.1", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "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/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@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/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "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/@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@microsoft/tsdoc": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz", + "integrity": "sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==", + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@nestjs/cli": { + "version": "11.0.21", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-11.0.21.tgz", + "integrity": "sha512-F8mV0Sj/zVEouzR3NxBuJy08YHTUOmC5Xdcx3qIIaJWzrm8Vw86CHkhkaPBJ5ewRMHPDCShPmhsfwhpCcjts3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.24", + "@angular-devkit/schematics": "19.2.24", + "@angular-devkit/schematics-cli": "19.2.24", + "@inquirer/prompts": "7.10.1", + "@nestjs/schematics": "^11.0.1", + "ansis": "4.2.0", + "chokidar": "4.0.3", + "cli-table3": "0.6.5", + "commander": "4.1.1", + "fork-ts-checker-webpack-plugin": "9.1.0", + "glob": "13.0.6", + "node-emoji": "1.11.0", + "ora": "5.4.1", + "tsconfig-paths": "4.2.0", + "tsconfig-paths-webpack-plugin": "4.2.0", + "typescript": "5.9.3", + "webpack": "5.106.0", + "webpack-node-externals": "3.0.0" + }, + "bin": { + "nest": "bin/nest.js" + }, + "engines": { + "node": ">= 20.11" + }, + "peerDependencies": { + "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 || ^0.8.0", + "@swc/core": "^1.3.62" + }, + "peerDependenciesMeta": { + "@swc/cli": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nestjs/cli/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@nestjs/cli/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@nestjs/cli/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/@nestjs/cli/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nestjs/cli/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@nestjs/cli/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nestjs/cli/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nestjs/cli/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@nestjs/cli/node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@nestjs/cli/node_modules/webpack": { + "version": "5.106.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.0.tgz", + "integrity": "sha512-Pkx5joZ9RrdgO5LBkyX1L2ZAJeK/Taz3vqZ9CbcP0wS5LEMx5QkKsEwLl29QJfihZ+DKRBFldzy1O30pJ1MDpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.20.0", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.3.1", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.17", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.4" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/@nestjs/common": { + "version": "11.1.24", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.24.tgz", + "integrity": "sha512-9zHxaDDM+oXW9As6UsP5yYB+UqczBmpeSCIFWdPEtEukMnZhxODG1BBjaUcdBB8Sc1uzojSJSJlp3yFp853t1g==", + "license": "MIT", + "dependencies": { + "file-type": "21.3.4", + "iterare": "1.2.1", + "load-esm": "1.0.3", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": ">=0.4.1", + "class-validator": ">=0.13.2", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/core": { + "version": "11.1.27", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.27.tgz", + "integrity": "sha512-K6DX7hcqmZdeXkv7tsPakKBRCgqL19a4mtbX4FluY0hWtFdtPKp6lbe+lb8gWPfvLdbOWr/CPScn7BSjBX+Ecg==", + "license": "MIT", + "dependencies": { + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "8.4.2", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "engines": { + "node": ">= 20" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0", + "@nestjs/websockets": "^11.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "node_modules/@nestjs/mapped-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.1.1.tgz", + "integrity": "sha512-SCCoMEJ6jdeI5h/N+KCVF1+pmg/hmEkNA5nHTS8Gvww7T/LCl4o1gFLinw2iQ60w7slFkszHcGLKGdazVI4F8A==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0 || ^0.15.0", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/platform-express": { + "version": "11.1.27", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.1.27.tgz", + "integrity": "sha512-0ZFhz6H6EdGh4xQVbUNwjoAwBuz73P7FvUAl67h9CTdMqQlJDaQYJApBv8pKfVZ1fGjMCbl0m9DcC6pXaZPWSQ==", + "license": "MIT", + "dependencies": { + "cors": "2.8.6", + "express": "5.2.1", + "multer": "2.1.1", + "path-to-regexp": "8.4.2", + "tslib": "2.8.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0" + } + }, + "node_modules/@nestjs/schematics": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-11.1.0.tgz", + "integrity": "sha512-lVxGZ46tcdItFMoXr6vyKWlnOsm1SZm/GUqAEDvy2RL4Q4O+3bkziAhrO7Y8JLssFUUvNFEGqAizI52WAxhjDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.24", + "@angular-devkit/schematics": "19.2.24", + "comment-json": "5.0.0", + "jsonc-parser": "3.3.1", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "prettier": "^3.0.0", + "typescript": ">=4.8.2" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/@nestjs/swagger": { + "version": "11.4.4", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.4.4.tgz", + "integrity": "sha512-VaIo1ruV2G7b+f2zPzkBSUNy9a/WQ9sg8TLKhWlrTfg4O6U10M/PA7Xi6XMXadOVhwOqoesijba8jH3i/3adrA==", + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "0.16.0", + "@nestjs/mapped-types": "2.1.1", + "js-yaml": "4.1.1", + "lodash": "4.18.1", + "path-to-regexp": "8.4.2", + "swagger-ui-dist": "5.32.6" + }, + "peerDependencies": { + "@fastify/static": "^8.0.0 || ^9.0.0", + "@nestjs/common": "^11.0.1", + "@nestjs/core": "^11.0.1", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/testing": { + "version": "11.1.27", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.27.tgz", + "integrity": "sha512-I35po13UHZZeGenLWJ3QYwh77RsLau5RcFKWBZ4waVHeARpwjtC7v7n7lGh98swLQdGmZgTnbvKaZ0B5dsUIKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + } + } + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@novu/api": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@novu/api/-/api-3.17.0.tgz", + "integrity": "sha512-94a81yA+Dv3wzHiQqBp/0sp3haJoMHaPtXcOhhRqyTvT/y/prOOf8jX/P/GyFaAIi+nV3gIjvcYLdcreeO+dQA==", + "dependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@phc/format": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", + "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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/@pkgr/core": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@prisma/adapter-pg": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/adapter-pg/-/adapter-pg-7.8.0.tgz", + "integrity": "sha512-ygb3UkerK3v8MDpXVgCISdRNDozpxh6+JVJgiIGbSr5KBgz10LLf5ejUskPGoXlsIjxsOu6nuy1JVQr2EKGSlg==", + "license": "Apache-2.0", + "dependencies": { + "@prisma/driver-adapter-utils": "7.8.0", + "@types/pg": "^8.16.0", + "pg": "^8.16.3", + "postgres-array": "3.0.4" + } + }, + "node_modules/@prisma/client": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-7.8.0.tgz", + "integrity": "sha512-HFp3Dawv/3sU3JtlPha90IB+48lS7zHiH4LKZPjmcE8YH5P9DOXGPvo8dqOtO7MqLDd1p2hOWMcFlRT1DMblHw==", + "license": "Apache-2.0", + "dependencies": { + "@prisma/client-runtime-utils": "7.8.0" + }, + "engines": { + "node": "^20.19 || ^22.12 || >=24.0" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/client-runtime-utils": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.8.0.tgz", + "integrity": "sha512-5NQZztQ0oY/ADFkmd9gPuweH5A1/CCY8YQPorLLO0Mu6a87mY5gsnDkzmFmIHs9NFaLnZojzgddFVN4RpKYrdw==", + "license": "Apache-2.0" + }, + "node_modules/@prisma/config": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.8.0.tgz", + "integrity": "sha512-HFESzd9rx2ZQxlK+TL7tu1HPvCqrHiL6LCxYykI2c34mvaUuIVVl3lYuicJD/MNnzgPnyeBEMlK4WTomJCV5jw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.3.4", + "deepmerge-ts": "7.1.5", + "effect": "3.20.0", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.8.0.tgz", + "integrity": "sha512-p+QZReysDUqXC+mk17q9a+Y/qzh4c2KYliDK30buYUyfrGeTGSyfmc0AIrJRhZJrLHhRiJa9Au/J72h3C+szvA==", + "license": "Apache-2.0" + }, + "node_modules/@prisma/dev": { + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/@prisma/dev/-/dev-0.24.3.tgz", + "integrity": "sha512-ffHlQuKXZiaDt9Go0OnCTdJZrHxK0k7omJKNV86/VjpsXu5EIHZLK0T7JSWgvNlJwh56kW9JFu9v0qJciFzepg==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "@electric-sql/pglite": "0.4.1", + "@electric-sql/pglite-socket": "0.1.1", + "@electric-sql/pglite-tools": "0.3.1", + "@hono/node-server": "1.19.11", + "@prisma/get-platform": "7.2.0", + "@prisma/query-plan-executor": "7.2.0", + "@prisma/streams-local": "0.1.2", + "foreground-child": "3.3.1", + "get-port-please": "3.2.0", + "hono": "^4.12.8", + "http-status-codes": "2.3.0", + "pathe": "2.0.3", + "proper-lockfile": "4.1.2", + "remeda": "2.33.4", + "std-env": "3.10.0", + "valibot": "1.2.0", + "zeptomatch": "2.1.0" + } + }, + "node_modules/@prisma/driver-adapter-utils": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/driver-adapter-utils/-/driver-adapter-utils-7.8.0.tgz", + "integrity": "sha512-/Q13o0ZT0rjc1Xk0Q9KhZYwuq2EW/vSbWUBKfgEKkaCuB/Sg6bqnjmTZqC5cD4d6y1vfFAEwBRzfzoSMIVJ55A==", + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "7.8.0" + } + }, + "node_modules/@prisma/engines": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-7.8.0.tgz", + "integrity": "sha512-jx3rCnNNrt5uzbkKlegtQ2GZHxSlihMCzutgT/BP6UIDF1r9tDI39hV/0T/cHZgzJ3ELbuQPXlVZy+Y1n0pcgw==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "7.8.0", + "@prisma/engines-version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a", + "@prisma/fetch-engine": "7.8.0", + "@prisma/get-platform": "7.8.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a.tgz", + "integrity": "sha512-fJPQxCkLgA5EayWaW8eArgCvjJ+N+Kz3VyeNKMEeYiQC4alNkxRKFVAGxv/ZUzuJISKqdw+zGeDbS6mn6RCPOA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines/node_modules/@prisma/get-platform": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.8.0.tgz", + "integrity": "sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "7.8.0" + } + }, + "node_modules/@prisma/fetch-engine": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.8.0.tgz", + "integrity": "sha512-gwB0Euiz/DDRyxFRpLXYlK3RfaZUj1c5dAYMuhZYfApg7arknJlcb9bIsOHDppJmbqYaVA+yBIiFMDBfprsNPQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "7.8.0", + "@prisma/engines-version": "7.8.0-6.3c6e192761c0362d496ed980de936e2f3cebcd3a", + "@prisma/get-platform": "7.8.0" + } + }, + "node_modules/@prisma/fetch-engine/node_modules/@prisma/get-platform": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.8.0.tgz", + "integrity": "sha512-WlxgRGnolL8VH2EmkH1R/DkKNr/mVdS3G2h42IZFFZ3eUrH9OT6t73kIOSlkkrv50wG123Iq8d96ufv5LlZktw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "7.8.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.2.0.tgz", + "integrity": "sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "7.2.0" + } + }, + "node_modules/@prisma/get-platform/node_modules/@prisma/debug": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.2.0.tgz", + "integrity": "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/query-plan-executor": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-7.2.0.tgz", + "integrity": "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/streams-local": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@prisma/streams-local/-/streams-local-0.1.2.tgz", + "integrity": "sha512-l49yTxKKF2odFxaAXTmwmkBKL3+bVQ1tFOooGifu4xkdb9NMNLxHj27XAhTylWZod8I+ISGM5erU1xcl/oBCtg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "ajv": "^8.12.0", + "better-result": "^2.7.0", + "env-paths": "^3.0.0", + "proper-lockfile": "^4.1.2" + }, + "engines": { + "bun": ">=1.3.6", + "node": ">=22.0.0" + } + }, + "node_modules/@prisma/streams-local/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@prisma/streams-local/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@prisma/studio-core": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.27.3.tgz", + "integrity": "sha512-AADjNFPdsrglxHQVTmHFqv6DuKQZ5WY4p5/gVFY017twvNrSwpLJ9lqUbYYxEu2W7nbvVxTZA8deJ8LseNALsw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@radix-ui/react-toggle": "1.1.10", + "chart.js": "4.5.1" + }, + "engines": { + "node": "^20.19 || ^22.12 || >=24.0", + "pnpm": "8" + }, + "peerDependencies": { + "@types/react": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz", + "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.49", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.49.tgz", + "integrity": "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.4.0.tgz", + "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@tokenizer/inflate": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", + "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "token-types": "^6.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", + "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookiejar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.5.tgz", + "integrity": "sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "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/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/methods": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/methods/-/methods-1.1.4.tgz", + "integrity": "sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/multer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.1.0.tgz", + "integrity": "sha512-zYZb0+nJhOHtPpGDb3vqPjwpdeGlGC157VpkqNQL+UU2qwoacoQ7MpsAmUptI/0Oa127X32JzWDqQVEXp2RcIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "24.12.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.4.tgz", + "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/pg": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.20.0.tgz", + "integrity": "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.15", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", + "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/superagent": { + "version": "8.1.10", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.10.tgz", + "integrity": "sha512-nbt4IWXABhW0jGmmpRzCFNlbmwCTzZ2gTUsNIr+X+ItdqPms+PAJZbWsNzpS2USqXjcoNLQcO6nXo60zcPQiIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cookiejar": "^2.1.5", + "@types/methods": "^1.1.4", + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/supertest": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-7.2.0.tgz", + "integrity": "sha512-uh2Lv57xvggst6lCqNdFAmDSvoMG7M/HDtX4iUCquxQ5EGPtaPM5PL5Hmi7LCvOG8db7YaCPNJEeoI8s/WzIQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/methods": "^1.1.4", + "@types/superagent": "^8.1.0" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.0.tgz", + "integrity": "sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/type-utils": "8.60.0", + "@typescript-eslint/utils": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.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.60.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.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.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.0.tgz", + "integrity": "sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", + "debug": "^4.4.3" + }, + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.0.tgz", + "integrity": "sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.60.0", + "@typescript-eslint/types": "^8.60.0", + "debug": "^4.4.3" + }, + "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.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.0.tgz", + "integrity": "sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0" + }, + "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.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.0.tgz", + "integrity": "sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ==", + "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.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.0.tgz", + "integrity": "sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/utils": "8.60.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.0.tgz", + "integrity": "sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA==", + "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.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.0.tgz", + "integrity": "sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.60.0", + "@typescript-eslint/tsconfig-utils": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/visitor-keys": "8.60.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.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.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.0.tgz", + "integrity": "sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.60.0", + "@typescript-eslint/types": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.0.tgz", + "integrity": "sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.60.0", + "eslint-visitor-keys": "^5.0.0" + }, + "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": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.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/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "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/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "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/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argon2": { + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.44.0.tgz", + "integrity": "sha512-zHPGN3S55sihSQo0dBbK0A5qpi2R31z7HZDZnry3ifOyj8bZZnpZND2gpmhnRGO1V/d555RwBqIK5W4Mrmv3ig==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@phc/format": "^1.0.0", + "cross-env": "^10.0.0", + "node-addon-api": "^8.5.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">=16.17.0" + } + }, + "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==", + "license": "Python-2.0" + }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/audit": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/audit/-/audit-0.0.6.tgz", + "integrity": "sha512-xgv3Y3RIYE00N2/xk10VLlwFd1kjc7FRaX1vC8+CsOfDRe53a06vOSkp91BOSNijZfddYum47a1Fvju/2+JPcw==", + "engines": { + "node": ">= 0.5.0" + } + }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/babel-jest": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.4.1.tgz", + "integrity": "sha512-fATAbM8piYxkiXQp3RBXmZHxZVNJZAVXXfyeyCN2Tida3+qJ8ea9UxhiJ2y4fLO90ZImKt6k9FlcH2+rLkJGhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "30.4.1", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.1", + "babel-preset-jest": "30.4.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz", + "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", + "dev": true, + "license": "BSD-3-Clause", + "workspaces": [ + "test/babel-8" + ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.4.0.tgz", + "integrity": "sha512-9EdtWM/sSfXLOGLwSn+GS6pIXyBnL07/8gyJlwFXjWy4DxMOyItqyUT29d4lQiS380EZwYlX7/At4PgBS+m2aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.4.0.tgz", + "integrity": "sha512-lBY4jxsNmCnSiu7kquw8ZC9F4+XLMOKypT3RnNHPvU2Kpd4W0xaPuLr5ZkRyOsvLYAY4yaW1ZwTW4xB7NIiZzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.4.0", + "babel-preset-current-node-syntax": "^1.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0 || ^8.0.0-beta.1" + } + }, + "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/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/baseline-browser-mapping": { + "version": "2.10.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz", + "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/better-result": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/better-result/-/better-result-2.9.2.tgz", + "integrity": "sha512-WIFoBPCdnTOdk9inkE1ZRvCZ4P0CpSkAiLlchC65N7n9DcjZ3NhqkBOlafzpOVnO8ixyi37kicmSJ3ENhPZl7Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "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.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "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.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "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/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.3.4.tgz", + "integrity": "sha512-cM0ApFQSBXuourJejzwv/AuPRvAxordTyParRVcHjjtXirtkzM0uK2L9TTn9s0cXZbG7E55jCivRQzoxYmRAlA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "confbox": "^0.2.4", + "defu": "^6.1.6", + "dotenv": "^17.3.1", + "exsolve": "^1.0.8", + "giget": "^3.2.0", + "jiti": "^2.6.1", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^2.1.0", + "pkg-types": "^2.3.0", + "rc9": "^3.0.1" + }, + "peerDependencies": { + "magicast": "*" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/c12/node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "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==", + "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==", + "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": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "dev": true, + "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==", + "dev": true, + "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/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/chart.js": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", + "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "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==", + "dev": true, + "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/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/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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/comment-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-5.0.0.tgz", + "integrity": "sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/confbox": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "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/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-env": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", + "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT", + "peer": true + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "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/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "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==", + "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/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/effect": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.20.0.tgz", + "integrity": "sha512-qMLfDJscrNG8p/aw+IkT9W7fgj50Z4wG5bLBy0Txsxz8iUHjDIkOgO3SV0WZfnQbNG2VJYb0b+rDLMrhM4+Krw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.364", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.364.tgz", + "integrity": "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "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/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/envalid": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/envalid/-/envalid-8.2.0.tgz", + "integrity": "sha512-CkPvea95dwMYE1wnKX5mQXkOpiMs9O+ncv8NqZy+gW7FuzpUp06KTdUHb18xFG8CqQHmfmRqGLF5DuGaBWNrSw==", + "license": "MIT", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "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==", + "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/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "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.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "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.5", + "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-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.6.tgz", + "integrity": "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.13" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "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": "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/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "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/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.4.1.tgz", + "integrity": "sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.4.1", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.4.1", + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-util": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fast-check/node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "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==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "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/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "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/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/file-type": { + "version": "21.3.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.4.tgz", + "integrity": "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==", + "license": "MIT", + "dependencies": { + "@tokenizer/inflate": "^0.4.1", + "strtok3": "^10.3.4", + "token-types": "^6.1.1", + "uint8array-extras": "^1.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "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/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "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/fix": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/fix/-/fix-0.0.6.tgz", + "integrity": "sha512-UQ+8m0GnIakgpY+92a9y+pYoX3Y6eaW7WNTkPolQ7r58Fjzq7NhyRLMrZ6J6U1u4y7H7APugjRmZ+i6CAn4+Dg==", + "dependencies": { + "pipe": "0.0.2", + "underscore": "1.1.6", + "underscore.string": "1.1.4" + }, + "engines": { + "node": ">=0.4.8" + } + }, + "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.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "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==", + "devOptional": 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/fork-ts-checker-webpack-plugin": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz", + "integrity": "sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^4.0.1", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=14.21.3" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/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/form-data/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/formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz", + "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==", + "dev": true, + "license": "Unlicense" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "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==", + "dev": true, + "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==", + "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-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-port-please": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz", + "integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==", + "devOptional": true, + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/giget": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-3.2.0.tgz", + "integrity": "sha512-GvHTWcykIR/fP8cj8dMpuMMkvaeJfPvYnhq0oW+chSeIr+ldX21ifU2Ms6KBoyKZQZmVaUAAhQ2EZ68KJF8a7A==", + "devOptional": true, + "license": "MIT", + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "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-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", + "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "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==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/grammex": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/grammex/-/grammex-3.1.12.tgz", + "integrity": "sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/graphmatch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.1.tgz", + "integrity": "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "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==", + "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.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hono": { + "version": "4.12.26", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.26.tgz", + "integrity": "sha512-uyZtpnYxM9CmQ7QsQknM4zN8EftNqhON1qYeIKM0Se67CCEe2c44xyGURwB0axX2fBDu1dqHrHAc1hmNT8ITkw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-status-codes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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": "BSD-3-Clause" + }, + "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/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "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/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "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-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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "license": "ISC", + "engines": { + "node": ">=6" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.4.2.tgz", + "integrity": "sha512-Yi1jqNC/Oq0N4hBgNH/YvBpP1P57QqundgytzYqy3yqAa7NZPNjSoi4SGbRAXDMdBzNE6xBCi5U7RgfrvMEUVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.4.2", + "@jest/types": "30.4.1", + "import-local": "^3.2.0", + "jest-cli": "30.4.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.4.1.tgz", + "integrity": "sha512-IuctmYrxi21iOSOaIXpJWalHyPAsVv0GeBHKDn8C1CA4W5htHn7INL+wdnL4Bo0+olEndvAFkmb++tIQJG+vvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.4.1", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus": { + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.4.2.tgz", + "integrity": "sha512-rvHH7VlY6LgbJXJTQ87GW62g1FntOtbhh0zT+v04kC+pgL6aBKyYINXxWukCpj3dcIBMw5/XUbtDS9dU9JTXeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.4.1", + "@jest/expect": "30.4.1", + "@jest/test-result": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.4.1", + "jest-matcher-utils": "30.4.1", + "jest-message-util": "30.4.1", + "jest-runtime": "30.4.2", + "jest-snapshot": "30.4.1", + "jest-util": "30.4.1", + "p-limit": "^3.1.0", + "pretty-format": "30.4.1", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-cli": { + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.4.2.tgz", + "integrity": "sha512-jfA2ocvVHMXS2QijrJ0d31ektP+d/W0T5RpcTX2Pq+3sVqHlsXVCM2+FmwpL+bdY8OfHpIg9xMxLF17Zg0U49Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "30.4.2", + "@jest/test-result": "30.4.1", + "@jest/types": "30.4.1", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.4.2", + "jest-util": "30.4.1", + "jest-validate": "30.4.1", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.4.2.tgz", + "integrity": "sha512-rNHAShJQqQwFNoL0hbf3BphSBOWnpOUAKvidLS/AjNVLPfoj5mSf4jQMfW3cYOs6hXeZC7nF7mDHaBnbxELOzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.1.0", + "@jest/pattern": "30.4.0", + "@jest/test-sequencer": "30.4.1", + "@jest/types": "30.4.1", + "babel-jest": "30.4.1", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.5.0", + "graceful-fs": "^4.2.11", + "jest-circus": "30.4.2", + "jest-docblock": "30.4.0", + "jest-environment-node": "30.4.1", + "jest-regex-util": "30.4.0", + "jest-resolve": "30.4.1", + "jest-runner": "30.4.2", + "jest-util": "30.4.1", + "jest-validate": "30.4.1", + "parse-json": "^5.2.0", + "pretty-format": "30.4.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/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/jest-config/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/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/jest-diff": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.4.1.tgz", + "integrity": "sha512-CRpFK0RtLriVDGcPPAnR6HMVI8bSR2jnUIgralhauzYQZIb4RH9AtEInTuQr65LmmGggGcRT6HIASxwqsVsmlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.4.0", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.4.0.tgz", + "integrity": "sha512-ZPMabUZCx5MpbZ2eBYSvZ0J8fvo3dR9oM+eeUpb3aKNQFuS2tu3Duw1TNlMoP8k3WQgKGJuhcMFvwcVuq6T7oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.4.1.tgz", + "integrity": "sha512-/8MJbH6fuj48TstjrMf+u/pd06Qezz5xOXvZA6442heNOWr8bdeoGZX2d9fCn028CoMgYmroH9//zky5GfyYmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.4.1", + "chalk": "^4.1.2", + "jest-util": "30.4.1", + "pretty-format": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.4.1.tgz", + "integrity": "sha512-4FZYVOk85hz2AyT6BbarKy9u37g6DbrDyCdFhsnDdXqyrueYQvB+0zO4f/kqLCRD0BsPRXPMNJeQwihKZV8naw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.4.1", + "@jest/fake-timers": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "jest-mock": "30.4.1", + "jest-util": "30.4.1", + "jest-validate": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.4.1.tgz", + "integrity": "sha512-rFrcONd8jeFsyw+Z9CrScJgglRf2+NFmNam8dKu7n+SoHqNYT47mn0DdEcVUZJpvh7Iz6/si7f7yUH7GJHVgnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.4.0", + "jest-util": "30.4.1", + "jest-worker": "30.4.1", + "picomatch": "^4.0.3", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "node_modules/jest-leak-detector": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.4.1.tgz", + "integrity": "sha512-IpmyiioeHxiWDhesHnUFmOxcTzwCwKpgACgWajtAP+nYQXiY7DakTxB6Bx9JFiRMljr0AX1PvnQdaU1KFoz6NQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "pretty-format": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.4.1.tgz", + "integrity": "sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.4.1", + "pretty-format": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.4.1.tgz", + "integrity": "sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.4.1", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-util": "30.4.1", + "picomatch": "^4.0.3", + "pretty-format": "30.4.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-mock": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.4.1.tgz", + "integrity": "sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@types/node": "*", + "jest-util": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.4.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.4.0.tgz", + "integrity": "sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.4.1.tgz", + "integrity": "sha512-Zry8Yq/yJcNAZ7dJ5F2heic8AheXvbFZ7XI5V+h28nrYZ7Qoyy4dItq8OodjnYD270mvX+ZudmrNV9cysqhW5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.4.1", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.4.1", + "jest-validate": "30.4.1", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.4.2.tgz", + "integrity": "sha512-gDiVh1I+GxYzz9oXlyw+1wv6VOYX1WYxMOfjsA3iGKePV2oxmbHhwxfkALxNxYy1ciw6APWwkW2zZONwP97aEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "30.4.0", + "jest-snapshot": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner": { + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.4.2.tgz", + "integrity": "sha512-2dw0PslVYXxffXGpLo+Ejad+KcI1Qkjn7f4X4619gf21oCUmL+SPfjqIa/losUem3yEOvfNZe/F1HWUcNpODcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.4.1", + "@jest/environment": "30.4.1", + "@jest/test-result": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.4.0", + "jest-environment-node": "30.4.1", + "jest-haste-map": "30.4.1", + "jest-leak-detector": "30.4.1", + "jest-message-util": "30.4.1", + "jest-resolve": "30.4.1", + "jest-runtime": "30.4.2", + "jest-util": "30.4.1", + "jest-watcher": "30.4.1", + "jest-worker": "30.4.1", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "30.4.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.4.2.tgz", + "integrity": "sha512-3/5e8iPz2k/VLqlr8DgTftYyLUv8Su3FkCAO2/Od81UsUTpSxOrS6O5x5KkoQwyUjmpYyDJKeyAvg2T2nvpNkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.4.1", + "@jest/fake-timers": "30.4.1", + "@jest/globals": "30.4.1", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.5.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.4.1", + "jest-message-util": "30.4.1", + "jest-mock": "30.4.1", + "jest-regex-util": "30.4.0", + "jest-resolve": "30.4.1", + "jest-snapshot": "30.4.1", + "jest-util": "30.4.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/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/jest-runtime/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/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/jest-snapshot": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.4.1.tgz", + "integrity": "sha512-tEOkkfOMppUyeiHwjZswOQ3lcnoTnws/q5FnGIaeIh/jmoU0ZlgMYRR8sTlTj+nNGCoJ0RDq6SfxGxCsyMTPmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.4.1", + "@jest/get-type": "30.1.0", + "@jest/snapshot-utils": "30.4.1", + "@jest/transform": "30.4.1", + "@jest/types": "30.4.1", + "babel-preset-current-node-syntax": "^1.2.0", + "chalk": "^4.1.2", + "expect": "30.4.1", + "graceful-fs": "^4.2.11", + "jest-diff": "30.4.1", + "jest-matcher-utils": "30.4.1", + "jest-message-util": "30.4.1", + "jest-util": "30.4.1", + "pretty-format": "30.4.1", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz", + "integrity": "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.4.1", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.4.1.tgz", + "integrity": "sha512-PDWi4SOwLnwqNDfHZjOcsEFyZ4fc/2W2gVL3DEoyqnB6jCQMLRtfBong8s6omIw3lI0HWOus12xfnFmQtjW3fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0", + "@jest/types": "30.4.1", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.4.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.4.1.tgz", + "integrity": "sha512-/l9UonmvCwjHH7d2h3iAwIloLc1H0S8mJZ/LNK3i86hqwPAz8otUJjP9MfYtz9Tt77Su5FD2xGjZn8d31IZHlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.4.1", + "@jest/types": "30.4.1", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.4.1", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.4.1.tgz", + "integrity": "sha512-SHynN/q/QD++iNyvMdy+WMmbCGk8jIsNcRxycXbWubSOhvo6T+j2afcfUSl+3hYsiBebOTo0cT7c2H7CXugu1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.4.1", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "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-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "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": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "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/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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/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/load-esm": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/load-esm/-/load-esm-1.0.3.tgz", + "integrity": "sha512-v5xlu8eHD1+6r8EHTg6hfmO97LN8ugKtiXcy5e6oN72iD2r6u0RPfLl6fxM+7Wnh2ZRq15o0russMst44WauPA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + }, + { + "type": "buymeacoffee", + "url": "https://buymeacoffee.com/borewit" + } + ], + "license": "MIT", + "engines": { + "node": ">=13.2.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "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.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "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/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru.min": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", + "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", + "devOptional": true, + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "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/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "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.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "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/multer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz", + "integrity": "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">= 10.16.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/multer/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multer/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/multer/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/multer/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/mysql2": { + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.15.3.tgz", + "integrity": "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.7.0", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", + "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "lru.min": "^1.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "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": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.9.0.tgz", + "integrity": "sha512-ekZMeaaIzSQTSpr7X2X3iJM7lTzgnx8ahAG9pJfT/7+14mlEM8ZYQ9cgCDvSSRbReFK0oHli3WrZdCiRsgAT9Q==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz", + "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "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/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "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/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "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-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pg": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.21.0.tgz", + "integrity": "sha512-AUP1EYJuHraQGsVoCQVIcM7TEJVGtDzxWtGFZd8rds9d+CCXlU5Js1rYgfLNvxy9iJrpHjGrRjoi/3BT9fRyiA==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.13.0", + "pg-pool": "^3.14.0", + "pg-protocol": "^1.14.0", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.4.0" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.4.0.tgz", + "integrity": "sha512-Vo7z/6rrQYxpNRylp4Tlob2elzbh+N/MOQbxFVWCxS7oEx6jF53GTJFxK2WWpKuBRkmiin4Mt+xofFDjx09R0A==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.13.0.tgz", + "integrity": "sha512-EMnU9E2fSULdsbErBbMaXJvFeD9B4+nPcM3f+4lsiCR0BHLPrLVjv3DbyM2hgQQviKJaTWIRRTjKjWlHg3p2ig==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.14.0.tgz", + "integrity": "sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.14.0.tgz", + "integrity": "sha512-n5taZ1kO3s9ngDTVxsEznOqCyToTgz0FLuPq0B33COy5pPpuWJpY3/2oRBVETuOgzdqRXfWpM9HIhp2LBBT1BA==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pg-types/node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pipe": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/pipe/-/pipe-0.0.2.tgz", + "integrity": "sha512-67s0/X7rv2PX1sl64FQqC0qQuSpd1tv8Wh6c+U1lprj6Q7NxDYulCxZTbVbDvc/HSpZLYh7Oo821xReXSCZikQ==", + "engines": { + "node": ">=0.4.8" + } + }, + "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/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.1.tgz", + "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.4", + "exsolve": "^1.0.8", + "pathe": "^2.0.3" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", + "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", + "devOptional": true, + "license": "Unlicense", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, + "node_modules/postgres-array": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.4.tgz", + "integrity": "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "30.4.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", + "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.4.1", + "ansi-styles": "^5.2.0", + "react-is-18": "npm:react-is@^18.3.1", + "react-is-19": "npm:react-is@^19.2.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prisma": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-7.8.0.tgz", + "integrity": "sha512-yfN4yrw7HV9kEJhoy1+jgah0jafEIQsf7uWouSsM8MvJtlubsk+kM7AIBWZ8+GJl74Yj3c+nbYqBkMOxtsZ3Lw==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/config": "7.8.0", + "@prisma/dev": "0.24.3", + "@prisma/engines": "7.8.0", + "@prisma/studio-core": "0.27.3", + "mysql2": "3.15.3", + "postgres": "3.4.7" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": "^20.19 || ^22.12 || >=24.0" + }, + "peerDependencies": { + "better-sqlite3": ">=9.0.0", + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/proper-lockfile/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/razorpay": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/razorpay/-/razorpay-2.9.6.tgz", + "integrity": "sha512-zsHAQzd6e1Cc6BNoCNZQaf65ElL6O6yw0wulxmoG5VQDr363fZC90Mp1V5EktVzG45yPyNomNXWlf4cQ3622gQ==", + "license": "MIT", + "dependencies": { + "axios": "^1.6.8" + } + }, + "node_modules/rc9": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-3.0.1.tgz", + "integrity": "sha512-gMDyleLWVE+i6Sgtc0QbbY6pEKqYs97NGi6isHQPqYlLemPoO8dxQ3uGi0f4NiP98c+jMW6cG1Kx9dDwfvqARQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.6", + "destr": "^2.0.5" + } + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "devOptional": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/react-is-18": { + "name": "react-is", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-is-19": { + "name": "react-is", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.6.tgz", + "integrity": "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw==", + "dev": true, + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, + "node_modules/remeda": { + "version": "2.33.4", + "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz", + "integrity": "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==", + "devOptional": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/remeda" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "devOptional": true, + "license": "MIT", + "peer": true + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", + "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==", + "devOptional": true + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "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.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "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==", + "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==", + "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==", + "devOptional": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "devOptional": true, + "license": "MIT" + }, + "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_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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/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/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-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": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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/strtok3": { + "version": "10.3.5", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz", + "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/superagent": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz", + "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.5", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.14.1" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supertest": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz", + "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cookie-signature": "^1.2.2", + "methods": "^1.1.2", + "superagent": "^10.3.0" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.32.6", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.32.6.tgz", + "integrity": "sha512-75ttZNaYCLoFPnozPZcTUU6mS3wKT8l7WLjU5zJSHFeJa23i5vtnze6IiCl4jDMPeQTXVXIgovq4M11NNfQvSA==", + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/synckit": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.3.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser": { + "version": "5.48.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.48.0.tgz", + "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "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/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-types": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", + "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", + "license": "MIT", + "dependencies": { + "@borewit/text-codec": "^0.2.1", + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-jest": { + "version": "29.4.11", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", + "integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.9", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.8.0", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <7" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ts-loader": { + "version": "9.5.7", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.7.tgz", + "integrity": "sha512-/ZNrKgA3K3PtpMYOC71EeMWIloGw3IYEa5/t1cyz2r5/PyUwTXGzYJvcD3kfUvmhlfpz1rhV8B2O6IVTQ0avsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", + "tsconfig-paths": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tsconfig-paths/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/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/tsx": { + "version": "4.22.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.4.tgz", + "integrity": "sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "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/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", + "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", + "license": "MIT", + "dependencies": { + "content-type": "^2.0.0", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/type-is/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.60.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.0.tgz", + "integrity": "sha512-9f65qWLZdAW9m1JaxBDUHcqRUfL8bkxxXL7XxEfI+F09q56PkBvIfCjLF3yInsDM/BBmwkqmCQdCZe/RYlIWEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.60.0", + "@typescript-eslint/parser": "8.60.0", + "@typescript-eslint/typescript-estree": "8.60.0", + "@typescript-eslint/utils": "8.60.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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "license": "MIT", + "dependencies": { + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/underscore": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.6.tgz", + "integrity": "sha512-aqSzrO92Cjmeo8G7F49+ZHWBo3IJpjpsUZZaqfOHJGN61flbpLxQw/sP91p4kf/2+nkFrG6AG2WHlJh6RCf+/g==", + "engines": { + "node": "*" + } + }, + "node_modules/underscore.string": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-1.1.4.tgz", + "integrity": "sha512-WsF8NWzIbTvxUaSOpSLq+AiO0tzweXdWQZ4w9Op8S/1BT9Fh7hCS7bfrF17vZu9kJg3pcqO+8WXfQSr1ah0f2g==", + "dependencies": { + "underscore": "1.1.6" + }, + "engines": { + "node": "*" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "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/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/valibot": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz", + "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==", + "devOptional": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">=5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "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/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webpack": { + "version": "5.107.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.107.2.tgz", + "integrity": "sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.22.0", + "es-module-lexer": "^2.1.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "loader-runner": "^4.3.2", + "mime-db": "^1.54.0", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.5.0", + "watchpack": "^2.5.1", + "webpack-sources": "^3.5.0" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-sources": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.5.0.tgz", + "integrity": "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "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/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "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==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zeptomatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/zeptomatch/-/zeptomatch-2.1.0.tgz", + "integrity": "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "grammex": "^3.1.11", + "graphmatch": "^1.1.0" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 000000000..993cc44e2 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,91 @@ +{ + "name": "backend", + "version": "0.0.1", + "description": "", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/src/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "test": "jest", + "test:watch": "jest --watch", + "test:cov": "jest --coverage", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:e2e": "jest --config ./test/jest-e2e.json", + "db:seed": "tsx prisma/seed.ts" + }, + "prisma": { + "seed": "tsx prisma/seed.ts" + }, + "dependencies": { + "@nestjs/common": "^11.0.1", + "@nestjs/core": "^11.0.1", + "@nestjs/platform-express": "^11.0.1", + "@nestjs/swagger": "^11.4.4", + "@novu/api": "^3.17.0", + "@prisma/adapter-pg": "^7.8.0", + "@prisma/client": "^7.8.0", + "argon2": "^0.44.0", + "audit": "^0.0.6", + "dotenv": "^17.4.2", + "envalid": "^8.2.0", + "fix": "^0.0.6", + "jsonwebtoken": "^9.0.3", + "razorpay": "^2.9.6", + "reflect-metadata": "^0.2.2", + "rxjs": "^7.8.1", + "zod": "^4.4.3" + }, + "devDependencies": { + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "^9.18.0", + "@nestjs/cli": "^11.0.0", + "@nestjs/schematics": "^11.0.0", + "@nestjs/testing": "^11.0.1", + "@types/express": "^5.0.0", + "@types/jest": "^30.0.0", + "@types/jsonwebtoken": "^9.0.10", + "@types/multer": "^2.1.0", + "@types/node": "^24.0.0", + "@types/supertest": "^7.0.0", + "eslint": "^9.18.0", + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.2", + "globals": "^17.0.0", + "jest": "^30.0.0", + "prettier": "^3.4.2", + "prisma": "^7.8.0", + "source-map-support": "^0.5.21", + "supertest": "^7.0.0", + "ts-jest": "^29.2.5", + "ts-loader": "^9.5.2", + "ts-node": "^10.9.2", + "tsconfig-paths": "^4.2.0", + "tsx": "^4.22.4", + "typescript": "^5.7.3", + "typescript-eslint": "^8.20.0" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" + } +} diff --git a/backend/payment.html b/backend/payment.html new file mode 100644 index 000000000..0c2d58a42 --- /dev/null +++ b/backend/payment.html @@ -0,0 +1,130 @@ + + + + + + BookMyVenue Razorpay Test + + + + + + + + +

Book My Venue

+ + + +

Verify Payload

+ +

+
+    
+
+
+
+
\ No newline at end of file
diff --git a/backend/prisma.config.ts b/backend/prisma.config.ts
new file mode 100644
index 000000000..831a20fa8
--- /dev/null
+++ b/backend/prisma.config.ts
@@ -0,0 +1,14 @@
+// This file was generated by Prisma, and assumes you have installed the following:
+// npm install --save-dev prisma dotenv
+import "dotenv/config";
+import { defineConfig } from "prisma/config";
+
+export default defineConfig({
+  schema: "prisma/schema.prisma",
+  migrations: {
+    path: "prisma/migrations",
+  },
+  datasource: {
+    url: process.env["DATABASE_URL"],
+  },
+});
diff --git a/backend/prisma/migrations/20260531140957_init/migration.sql b/backend/prisma/migrations/20260531140957_init/migration.sql
new file mode 100644
index 000000000..f64e6db18
--- /dev/null
+++ b/backend/prisma/migrations/20260531140957_init/migration.sql
@@ -0,0 +1,345 @@
+-- CreateEnum
+CREATE TYPE "role" AS ENUM ('ADMIN', 'VENUE_OWNER', 'USER');
+
+-- CreateEnum
+CREATE TYPE "user_status" AS ENUM ('ACTIVE', 'BLOCKED', 'DELETED');
+
+-- CreateEnum
+CREATE TYPE "venue_status" AS ENUM ('PENDING', 'APPROVED', 'REJECTED', 'SUSPENDED');
+
+-- CreateEnum
+CREATE TYPE "payment_status" AS ENUM ('PENDING', 'PAID', 'FAILED', 'REFUNDED');
+
+-- CreateEnum
+CREATE TYPE "refund_status" AS ENUM ('PENDING', 'COMPLETED', 'REJECTED');
+
+-- CreateTable
+CREATE TABLE "users" (
+    "id" UUID NOT NULL,
+    "email" VARCHAR(255) NOT NULL,
+    "password" VARCHAR(255),
+    "first_name" VARCHAR(100) NOT NULL,
+    "last_name" VARCHAR(100),
+    "phone" VARCHAR(20),
+    "google_id" VARCHAR(255),
+    "role" "role" NOT NULL,
+    "status" "user_status" NOT NULL DEFAULT 'ACTIVE',
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updated_at" TIMESTAMPTZ NOT NULL,
+    "deleted_at" TIMESTAMPTZ,
+
+    CONSTRAINT "users_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "amenities" (
+    "id" UUID NOT NULL,
+    "name" VARCHAR(100) NOT NULL,
+
+    CONSTRAINT "amenities_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "venues" (
+    "id" UUID NOT NULL,
+    "owner_id" UUID NOT NULL,
+    "title" VARCHAR(200) NOT NULL,
+    "description" TEXT NOT NULL,
+    "venue_type" VARCHAR(50) NOT NULL,
+    "address_line_1" VARCHAR(255) NOT NULL,
+    "city" VARCHAR(100) NOT NULL,
+    "state" VARCHAR(100) NOT NULL,
+    "country" VARCHAR(100) NOT NULL,
+    "postal_code" VARCHAR(20) NOT NULL,
+    "latitude" DECIMAL(10,8),
+    "longitude" DECIMAL(11,8),
+    "capacity" INTEGER NOT NULL,
+    "price_per_day" DECIMAL(12,2) NOT NULL,
+    "status" "venue_status" NOT NULL DEFAULT 'PENDING',
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updated_at" TIMESTAMPTZ NOT NULL,
+    "deleted_at" TIMESTAMPTZ,
+
+    CONSTRAINT "venues_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "venue_images" (
+    "id" UUID NOT NULL,
+    "venue_id" UUID NOT NULL,
+    "image_url" VARCHAR(500) NOT NULL,
+    "sort_order" INTEGER NOT NULL DEFAULT 0,
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "venue_images_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "venue_amenities" (
+    "venue_id" UUID NOT NULL,
+    "amenity_id" UUID NOT NULL,
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "venue_amenities_pkey" PRIMARY KEY ("venue_id","amenity_id")
+);
+
+-- CreateTable
+CREATE TABLE "bookings" (
+    "id" UUID NOT NULL,
+    "user_id" UUID NOT NULL,
+    "venue_id" UUID NOT NULL,
+    "booking_start" TIMESTAMPTZ NOT NULL,
+    "booking_end" TIMESTAMPTZ NOT NULL,
+    "guests_count" INTEGER NOT NULL,
+    "total_amount" DECIMAL(12,2) NOT NULL,
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    "updated_at" TIMESTAMPTZ NOT NULL,
+
+    CONSTRAINT "bookings_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "payments" (
+    "id" UUID NOT NULL,
+    "booking_id" UUID NOT NULL,
+    "provider" VARCHAR(50) NOT NULL,
+    "provider_payment_id" VARCHAR(255),
+    "amount" DECIMAL(12,2) NOT NULL,
+    "status" "payment_status" NOT NULL DEFAULT 'PENDING',
+    "paid_at" TIMESTAMPTZ,
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "payments_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "refunds" (
+    "id" UUID NOT NULL,
+    "payment_id" UUID NOT NULL,
+    "amount" DECIMAL(12,2) NOT NULL,
+    "reason" TEXT,
+    "status" "refund_status" NOT NULL DEFAULT 'PENDING',
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "refunds_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "reviews" (
+    "id" UUID NOT NULL,
+    "venue_id" UUID NOT NULL,
+    "user_id" UUID NOT NULL,
+    "rating" SMALLINT NOT NULL,
+    "comment" TEXT,
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "reviews_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "audit_logs" (
+    "id" UUID NOT NULL,
+    "user_id" UUID NOT NULL,
+    "action" VARCHAR(100) NOT NULL,
+    "entity_type" VARCHAR(100) NOT NULL,
+    "entity_id" UUID NOT NULL,
+    "metadata" JSONB,
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "audit_logs_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "refresh_tokens" (
+    "id" UUID NOT NULL,
+    "user_id" UUID NOT NULL,
+    "token_hash" VARCHAR(255) NOT NULL,
+    "expires_at" TIMESTAMPTZ NOT NULL,
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "refresh_tokens_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "saved_venues" (
+    "id" UUID NOT NULL,
+    "user_id" UUID NOT NULL,
+    "venue_id" UUID NOT NULL,
+    "created_at" TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
+
+    CONSTRAINT "saved_venues_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "users_google_id_key" ON "users"("google_id");
+
+-- CreateIndex
+CREATE INDEX "users_role_idx" ON "users"("role");
+
+-- CreateIndex
+CREATE INDEX "users_status_idx" ON "users"("status");
+
+-- CreateIndex
+CREATE INDEX "users_created_at_idx" ON "users"("created_at");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "amenities_name_key" ON "amenities"("name");
+
+-- CreateIndex
+CREATE INDEX "venues_owner_id_idx" ON "venues"("owner_id");
+
+-- CreateIndex
+CREATE INDEX "venues_status_idx" ON "venues"("status");
+
+-- CreateIndex
+CREATE INDEX "venues_city_idx" ON "venues"("city");
+
+-- CreateIndex
+CREATE INDEX "venues_state_idx" ON "venues"("state");
+
+-- CreateIndex
+CREATE INDEX "venues_venue_type_idx" ON "venues"("venue_type");
+
+-- CreateIndex
+CREATE INDEX "venues_capacity_idx" ON "venues"("capacity");
+
+-- CreateIndex
+CREATE INDEX "venues_price_per_day_idx" ON "venues"("price_per_day");
+
+-- CreateIndex
+CREATE INDEX "venues_city_venue_type_idx" ON "venues"("city", "venue_type");
+
+-- CreateIndex
+CREATE INDEX "venues_city_status_idx" ON "venues"("city", "status");
+
+-- CreateIndex
+CREATE INDEX "venues_owner_id_status_idx" ON "venues"("owner_id", "status");
+
+-- CreateIndex
+CREATE INDEX "venues_created_at_idx" ON "venues"("created_at");
+
+-- CreateIndex
+CREATE INDEX "venue_images_venue_id_idx" ON "venue_images"("venue_id");
+
+-- CreateIndex
+CREATE INDEX "venue_images_venue_id_sort_order_idx" ON "venue_images"("venue_id", "sort_order");
+
+-- CreateIndex
+CREATE INDEX "venue_amenities_venue_id_idx" ON "venue_amenities"("venue_id");
+
+-- CreateIndex
+CREATE INDEX "venue_amenities_amenity_id_idx" ON "venue_amenities"("amenity_id");
+
+-- CreateIndex
+CREATE INDEX "bookings_user_id_idx" ON "bookings"("user_id");
+
+-- CreateIndex
+CREATE INDEX "bookings_venue_id_idx" ON "bookings"("venue_id");
+
+-- CreateIndex
+CREATE INDEX "bookings_booking_start_idx" ON "bookings"("booking_start");
+
+-- CreateIndex
+CREATE INDEX "bookings_booking_end_idx" ON "bookings"("booking_end");
+
+-- CreateIndex
+CREATE INDEX "bookings_venue_id_booking_start_booking_end_idx" ON "bookings"("venue_id", "booking_start", "booking_end");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "payments_booking_id_key" ON "payments"("booking_id");
+
+-- CreateIndex
+CREATE INDEX "payments_status_idx" ON "payments"("status");
+
+-- CreateIndex
+CREATE INDEX "payments_provider_idx" ON "payments"("provider");
+
+-- CreateIndex
+CREATE INDEX "payments_paid_at_idx" ON "payments"("paid_at");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "refunds_payment_id_key" ON "refunds"("payment_id");
+
+-- CreateIndex
+CREATE INDEX "refunds_status_idx" ON "refunds"("status");
+
+-- CreateIndex
+CREATE INDEX "reviews_venue_id_idx" ON "reviews"("venue_id");
+
+-- CreateIndex
+CREATE INDEX "reviews_user_id_idx" ON "reviews"("user_id");
+
+-- CreateIndex
+CREATE INDEX "reviews_rating_idx" ON "reviews"("rating");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "reviews_venue_id_user_id_key" ON "reviews"("venue_id", "user_id");
+
+-- CreateIndex
+CREATE INDEX "audit_logs_user_id_idx" ON "audit_logs"("user_id");
+
+-- CreateIndex
+CREATE INDEX "audit_logs_entity_type_idx" ON "audit_logs"("entity_type");
+
+-- CreateIndex
+CREATE INDEX "audit_logs_entity_id_idx" ON "audit_logs"("entity_id");
+
+-- CreateIndex
+CREATE INDEX "audit_logs_created_at_idx" ON "audit_logs"("created_at");
+
+-- CreateIndex
+CREATE INDEX "refresh_tokens_user_id_idx" ON "refresh_tokens"("user_id");
+
+-- CreateIndex
+CREATE INDEX "refresh_tokens_expires_at_idx" ON "refresh_tokens"("expires_at");
+
+-- CreateIndex
+CREATE INDEX "saved_venues_user_id_idx" ON "saved_venues"("user_id");
+
+-- CreateIndex
+CREATE INDEX "saved_venues_venue_id_idx" ON "saved_venues"("venue_id");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "saved_venues_user_id_venue_id_key" ON "saved_venues"("user_id", "venue_id");
+
+-- AddForeignKey
+ALTER TABLE "venues" ADD CONSTRAINT "venues_owner_id_fkey" FOREIGN KEY ("owner_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "venue_images" ADD CONSTRAINT "venue_images_venue_id_fkey" FOREIGN KEY ("venue_id") REFERENCES "venues"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "venue_amenities" ADD CONSTRAINT "venue_amenities_venue_id_fkey" FOREIGN KEY ("venue_id") REFERENCES "venues"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "venue_amenities" ADD CONSTRAINT "venue_amenities_amenity_id_fkey" FOREIGN KEY ("amenity_id") REFERENCES "amenities"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "bookings" ADD CONSTRAINT "bookings_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "bookings" ADD CONSTRAINT "bookings_venue_id_fkey" FOREIGN KEY ("venue_id") REFERENCES "venues"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "payments" ADD CONSTRAINT "payments_booking_id_fkey" FOREIGN KEY ("booking_id") REFERENCES "bookings"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "refunds" ADD CONSTRAINT "refunds_payment_id_fkey" FOREIGN KEY ("payment_id") REFERENCES "payments"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "reviews" ADD CONSTRAINT "reviews_venue_id_fkey" FOREIGN KEY ("venue_id") REFERENCES "venues"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "reviews" ADD CONSTRAINT "reviews_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "refresh_tokens" ADD CONSTRAINT "refresh_tokens_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "saved_venues" ADD CONSTRAINT "saved_venues_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "saved_venues" ADD CONSTRAINT "saved_venues_venue_id_fkey" FOREIGN KEY ("venue_id") REFERENCES "venues"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/backend/prisma/migrations/20260620193151_removed_unwanted_table/migration.sql b/backend/prisma/migrations/20260620193151_removed_unwanted_table/migration.sql
new file mode 100644
index 000000000..c38978626
--- /dev/null
+++ b/backend/prisma/migrations/20260620193151_removed_unwanted_table/migration.sql
@@ -0,0 +1,38 @@
+/*
+  Warnings:
+
+  - You are about to drop the `audit_logs` table. If the table is not empty, all the data it contains will be lost.
+  - You are about to drop the `refunds` table. If the table is not empty, all the data it contains will be lost.
+  - You are about to drop the `reviews` table. If the table is not empty, all the data it contains will be lost.
+  - You are about to drop the `saved_venues` table. If the table is not empty, all the data it contains will be lost.
+
+*/
+-- DropForeignKey
+ALTER TABLE "refunds" DROP CONSTRAINT "refunds_payment_id_fkey";
+
+-- DropForeignKey
+ALTER TABLE "reviews" DROP CONSTRAINT "reviews_user_id_fkey";
+
+-- DropForeignKey
+ALTER TABLE "reviews" DROP CONSTRAINT "reviews_venue_id_fkey";
+
+-- DropForeignKey
+ALTER TABLE "saved_venues" DROP CONSTRAINT "saved_venues_user_id_fkey";
+
+-- DropForeignKey
+ALTER TABLE "saved_venues" DROP CONSTRAINT "saved_venues_venue_id_fkey";
+
+-- DropTable
+DROP TABLE "audit_logs";
+
+-- DropTable
+DROP TABLE "refunds";
+
+-- DropTable
+DROP TABLE "reviews";
+
+-- DropTable
+DROP TABLE "saved_venues";
+
+-- DropEnum
+DROP TYPE "refund_status";
diff --git a/backend/prisma/migrations/20260621032748_remove_table_amenities/migration.sql b/backend/prisma/migrations/20260621032748_remove_table_amenities/migration.sql
new file mode 100644
index 000000000..a0b5d0f0e
--- /dev/null
+++ b/backend/prisma/migrations/20260621032748_remove_table_amenities/migration.sql
@@ -0,0 +1,18 @@
+/*
+  Warnings:
+
+  - You are about to drop the `amenities` table. If the table is not empty, all the data it contains will be lost.
+  - You are about to drop the `venue_amenities` table. If the table is not empty, all the data it contains will be lost.
+
+*/
+-- DropForeignKey
+ALTER TABLE "venue_amenities" DROP CONSTRAINT "venue_amenities_amenity_id_fkey";
+
+-- DropForeignKey
+ALTER TABLE "venue_amenities" DROP CONSTRAINT "venue_amenities_venue_id_fkey";
+
+-- DropTable
+DROP TABLE "amenities";
+
+-- DropTable
+DROP TABLE "venue_amenities";
diff --git a/backend/prisma/migrations/20260621032843_add_column_amenities/migration.sql b/backend/prisma/migrations/20260621032843_add_column_amenities/migration.sql
new file mode 100644
index 000000000..cbc96fd87
--- /dev/null
+++ b/backend/prisma/migrations/20260621032843_add_column_amenities/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "venues" ADD COLUMN     "amenities" TEXT[] DEFAULT ARRAY[]::TEXT[];
diff --git a/backend/prisma/migrations/20260626154120_add_column_status_to_booking/migration.sql b/backend/prisma/migrations/20260626154120_add_column_status_to_booking/migration.sql
new file mode 100644
index 000000000..b2764d01a
--- /dev/null
+++ b/backend/prisma/migrations/20260626154120_add_column_status_to_booking/migration.sql
@@ -0,0 +1,25 @@
+/*
+  Warnings:
+
+  - The values [PENDING] on the enum `payment_status` will be removed. If these variants are still used in the database, this will fail.
+
+*/
+-- CreateEnum
+CREATE TYPE "booking_status" AS ENUM ('BOOKED', 'CANCELLED');
+
+-- AlterEnum
+BEGIN;
+CREATE TYPE "payment_status_new" AS ENUM ('INITIATED', 'PAID', 'FAILED', 'REFUNDED');
+ALTER TABLE "public"."payments" ALTER COLUMN "status" DROP DEFAULT;
+ALTER TABLE "payments" ALTER COLUMN "status" TYPE "payment_status_new" USING ("status"::text::"payment_status_new");
+ALTER TYPE "payment_status" RENAME TO "payment_status_old";
+ALTER TYPE "payment_status_new" RENAME TO "payment_status";
+DROP TYPE "public"."payment_status_old";
+ALTER TABLE "payments" ALTER COLUMN "status" SET DEFAULT 'INITIATED';
+COMMIT;
+
+-- AlterTable
+ALTER TABLE "bookings" ADD COLUMN     "status" "booking_status" NOT NULL DEFAULT 'BOOKED';
+
+-- AlterTable
+ALTER TABLE "payments" ALTER COLUMN "status" SET DEFAULT 'INITIATED';
diff --git a/backend/prisma/migrations/20260626160138_add_column_payment_status_to_booking/migration.sql b/backend/prisma/migrations/20260626160138_add_column_payment_status_to_booking/migration.sql
new file mode 100644
index 000000000..570f45e44
--- /dev/null
+++ b/backend/prisma/migrations/20260626160138_add_column_payment_status_to_booking/migration.sql
@@ -0,0 +1,5 @@
+-- AlterEnum
+ALTER TYPE "payment_status" ADD VALUE 'PENDING';
+
+-- AlterTable
+ALTER TABLE "bookings" ADD COLUMN     "payment_status" "payment_status" NOT NULL DEFAULT 'PENDING';
diff --git a/backend/prisma/migrations/20260629140011_add_column_updated_to_payment/migration.sql b/backend/prisma/migrations/20260629140011_add_column_updated_to_payment/migration.sql
new file mode 100644
index 000000000..79431f860
--- /dev/null
+++ b/backend/prisma/migrations/20260629140011_add_column_updated_to_payment/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "payments" ADD COLUMN     "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
diff --git a/backend/prisma/migrations/20260629164040_update_table_payment/migration.sql b/backend/prisma/migrations/20260629164040_update_table_payment/migration.sql
new file mode 100644
index 000000000..89b6807f9
--- /dev/null
+++ b/backend/prisma/migrations/20260629164040_update_table_payment/migration.sql
@@ -0,0 +1,4 @@
+-- AlterTable
+ALTER TABLE "payments" ADD COLUMN     "currency" VARCHAR(20) NOT NULL DEFAULT 'INR',
+ADD COLUMN     "failure_reason" VARCHAR(100),
+ADD COLUMN     "provider_order_id" VARCHAR(255);
diff --git a/backend/prisma/migrations/migration_lock.toml b/backend/prisma/migrations/migration_lock.toml
new file mode 100644
index 000000000..044d57cdb
--- /dev/null
+++ b/backend/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (e.g., Git)
+provider = "postgresql"
diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma
new file mode 100644
index 000000000..d6a7b4f53
--- /dev/null
+++ b/backend/prisma/schema.prisma
@@ -0,0 +1,167 @@
+generator client {
+  provider     = "prisma-client"
+  output       = "../src/infra/database/prisma/generated/prisma"
+  moduleFormat = "cjs"
+}
+
+datasource db {
+  provider = "postgresql"
+}
+
+enum role {
+  ADMIN
+  VENUE_OWNER
+  USER
+}
+
+enum user_status {
+  ACTIVE
+  BLOCKED
+  DELETED
+}
+
+enum venue_status {
+  PENDING
+  APPROVED
+  REJECTED
+  SUSPENDED
+}
+
+enum booking_status {
+  BOOKED
+  CANCELLED
+}
+
+enum payment_status {
+  PENDING
+  INITIATED
+  PAID
+  FAILED
+  REFUNDED
+}
+
+model users {
+  id            String           @id @default(uuid()) @db.Uuid
+  email         String           @unique @db.VarChar(255)
+  password      String?          @db.VarChar(255)
+  first_name    String           @db.VarChar(100)
+  last_name     String?          @db.VarChar(100)
+  phone         String?          @db.VarChar(20)
+  google_id     String?          @unique @db.VarChar(255)
+  role          role
+  status        user_status      @default(ACTIVE)
+  created_at    DateTime         @default(now()) @db.Timestamptz
+  updated_at    DateTime         @updatedAt @db.Timestamptz
+  deleted_at    DateTime?        @db.Timestamptz
+  venues        venues[]
+  bookings      bookings[]
+  refreshTokens refresh_tokens[]
+
+  @@index([role])
+  @@index([status])
+  @@index([created_at])
+}
+
+model venues {
+  id             String         @id @default(uuid()) @db.Uuid
+  owner_id       String         @db.Uuid
+  title          String         @db.VarChar(200)
+  description    String         @db.Text
+  venue_type     String         @db.VarChar(50)
+  address_line_1 String         @db.VarChar(255)
+  city           String         @db.VarChar(100)
+  state          String         @db.VarChar(100)
+  country        String         @db.VarChar(100)
+  postal_code    String         @db.VarChar(20)
+  latitude       Decimal?       @db.Decimal(10, 8)
+  longitude      Decimal?       @db.Decimal(11, 8)
+  capacity       Int            @db.Integer
+  price_per_day  Decimal        @db.Decimal(12, 2)
+  status         venue_status   @default(PENDING)
+  created_at     DateTime       @default(now()) @db.Timestamptz
+  updated_at     DateTime       @updatedAt @db.Timestamptz
+  deleted_at     DateTime?      @db.Timestamptz
+  owner          users          @relation(fields: [owner_id], references: [id])
+  amenities      String[]       @default([])
+  images         venue_images[]
+  bookings       bookings[]
+
+  @@index([owner_id])
+  @@index([status])
+  @@index([city])
+  @@index([state])
+  @@index([venue_type])
+  @@index([capacity])
+  @@index([price_per_day])
+  @@index([city, venue_type])
+  @@index([city, status])
+  @@index([owner_id, status])
+  @@index([created_at])
+}
+
+model venue_images {
+  id         String   @id @default(uuid()) @db.Uuid
+  venue_id   String   @db.Uuid
+  image_url  String   @db.VarChar(500)
+  sort_order Int      @default(0)
+  created_at DateTime @default(now()) @db.Timestamptz
+  venue      venues   @relation(fields: [venue_id], references: [id], onDelete: Cascade)
+
+  @@index([venue_id])
+  @@index([venue_id, sort_order])
+}
+
+model bookings {
+  id             String         @id @default(uuid()) @db.Uuid
+  user_id        String         @db.Uuid
+  venue_id       String         @db.Uuid
+  booking_start  DateTime       @db.Timestamptz
+  booking_end    DateTime       @db.Timestamptz
+  guests_count   Int            @db.Integer
+  total_amount   Decimal        @db.Decimal(12, 2)
+  status         booking_status @default(BOOKED)
+  payment_status payment_status @default(PENDING)
+  created_at     DateTime       @default(now()) @db.Timestamptz
+  updated_at     DateTime       @updatedAt @db.Timestamptz
+  user           users          @relation(fields: [user_id], references: [id])
+  venue          venues         @relation(fields: [venue_id], references: [id])
+  payment        payments?
+
+  @@index([user_id])
+  @@index([venue_id])
+  @@index([booking_start])
+  @@index([booking_end])
+  @@index([venue_id, booking_start, booking_end])
+}
+
+model payments {
+  id                  String         @id @default(uuid()) @db.Uuid
+  booking_id          String         @unique @db.Uuid
+  provider            String         @db.VarChar(50)
+  provider_order_id   String?        @db.VarChar(255)
+  provider_payment_id String?        @db.VarChar(255)
+  amount              Decimal        @db.Decimal(12, 2)
+  currency            String         @default("INR") @db.VarChar(20)
+  status              payment_status @default(INITIATED)
+  failure_reason      String?        @db.VarChar(100)
+  paid_at             DateTime?      @db.Timestamptz
+  created_at          DateTime       @default(now()) @db.Timestamptz
+  updated_at          DateTime       @default(now()) @updatedAt
+  booking             bookings       @relation(fields: [booking_id], references: [id])
+
+  @@index([status])
+  @@index([provider])
+  @@index([paid_at])
+}
+
+model refresh_tokens {
+  id         String   @id @default(uuid()) @db.Uuid
+  user_id    String   @db.Uuid
+  token_hash String   @db.VarChar(255)
+  expires_at DateTime @db.Timestamptz
+  created_at DateTime @default(now()) @db.Timestamptz
+  user       users    @relation(fields: [user_id], references: [id], onDelete: Cascade)
+
+  @@index([user_id])
+  @@index([expires_at])
+}
diff --git a/backend/prisma/seed.ts b/backend/prisma/seed.ts
new file mode 100644
index 000000000..f7fe3f541
--- /dev/null
+++ b/backend/prisma/seed.ts
@@ -0,0 +1,529 @@
+import 'dotenv/config';
+import { PrismaClient } from '../src/infra/database/prisma/generated/prisma/client';
+import { PrismaPg } from '@prisma/adapter-pg';
+import * as argon from 'argon2'
+import { AMENITIES } from '../src/constants/amenities';
+
+// ──────────────────────────────────────────────────────────
+// Password hashing (mirrors CryptoPasswordHasher in the app)
+// ──────────────────────────────────────────────────────────
+function hashPassword(password: string): Promise {
+  return argon.hash(password)
+}
+
+// ──────────────────────────────────────────────────────────
+// Helpers
+// ──────────────────────────────────────────────────────────
+function daysFromNow(days: number): Date {
+  const d = new Date();
+  d.setDate(d.getDate() + days);
+  return d;
+}
+
+function daysAgo(days: number): Date {
+  return daysFromNow(-days);
+}
+
+// ──────────────────────────────────────────────────────────
+// Venue image sets
+// ──────────────────────────────────────────────────────────
+const VENUE_IMAGES: Record = {
+  grand_hall: [
+    'https://images.unsplash.com/photo-1519167758481-83f550bb49b3?w=1200',
+    'https://images.unsplash.com/photo-1464366400600-7168b8af9bc3?w=1200',
+    'https://images.unsplash.com/photo-1522413452208-996ff3f3e740?w=1200',
+  ],
+  conference: [
+    'https://images.unsplash.com/photo-1497366216548-37526070297c?w=1200',
+    'https://images.unsplash.com/photo-1560472355-536de3962603?w=1200',
+    'https://images.unsplash.com/photo-1542744173-8e7e53415bb0?w=1200',
+  ],
+  wedding: [
+    'https://images.unsplash.com/photo-1478146059778-26028b07395a?w=1200',
+    'https://images.unsplash.com/photo-1510076857177-7470076d4098?w=1200',
+    'https://images.unsplash.com/photo-1501426026826-31c667bdf23d?w=1200',
+  ],
+  rooftop: [
+    'https://images.unsplash.com/photo-1533174072545-7a4b6ad7a6c3?w=1200',
+    'https://images.unsplash.com/photo-1470229722913-7c0e2dbbafd3?w=1200',
+  ],
+  outdoor: [
+    'https://images.unsplash.com/photo-1505236858219-8359eb29e329?w=1200',
+    'https://images.unsplash.com/photo-1464366400600-7168b8af9bc3?w=1200',
+    'https://images.unsplash.com/photo-1490645935967-10de6ba17061?w=1200',
+  ],
+  banquet: [
+    'https://images.unsplash.com/photo-1555244162-803834f70033?w=1200',
+    'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=1200',
+  ],
+};
+
+// ──────────────────────────────────────────────────────────
+// Per-venue amenity selections (values must exist in AMENITIES)
+// ──────────────────────────────────────────────────────────
+const [
+  WiFi, Parking, AC, Projector, Catering, Sound,
+  Kitchen, Stage, Security, Pool, Generator,
+  Wheelchair, Valet, Bridal, Lockers, DanceFloor,
+  OpenBar, PhotoBooth, Terrace, GreenRoom,
+] = AMENITIES;
+
+const VENUE_AMENITIES = {
+  grand_hall: [WiFi, Parking, AC, Catering, Sound, Stage, Security, Generator, Valet, Bridal, DanceFloor, OpenBar],
+  conference: [WiFi, Parking, AC, Projector, Catering, Sound, Generator, Wheelchair],
+  wedding: [WiFi, Parking, AC, Catering, Sound, Kitchen, Stage, Security, Pool, Generator, Valet, Bridal, DanceFloor, OpenBar, PhotoBooth, GreenRoom],
+  elite_biz: [WiFi, Parking, AC, Projector, Catering, Sound, Wheelchair],
+  rooftop: [WiFi, AC, Sound, Security, Generator, OpenBar, Terrace],
+  tech_park: [WiFi, Parking, AC, Projector, Catering, Sound, Stage, Security, Generator, Wheelchair],
+  garden: [WiFi, Parking, Catering, Sound, Stage, Security, Generator, Terrace, PhotoBooth],
+  banquet: [WiFi, Parking, AC, Catering, Sound, Generator, DanceFloor],
+};
+
+async function main() {
+  const adapter = new PrismaPg({
+    connectionString: process.env.DATABASE_URL!,
+  });
+  const prisma = new PrismaClient({ adapter });
+
+  try {
+    console.log('đŸŒ±  Starting database seed
\n');
+
+    // ── 0. Clean existing data ─────────────────────────────────────
+    console.log('🗑   Cleaning existing data
');
+    await prisma.payments.deleteMany();
+    await prisma.bookings.deleteMany();
+    await prisma.venue_images.deleteMany();
+    await prisma.venues.deleteMany();
+    await prisma.refresh_tokens.deleteMany();
+    await prisma.users.deleteMany();
+    console.log('✅  Cleaned.\n');
+
+    // ── 1. Users ───────────────────────────────────────────────────
+    console.log('đŸ‘€  Seeding users
');
+    const hashedPassword = await hashPassword('password123');
+    const adminId = '14d1f934-0e40-4c9a-b0cb-5922af2b3074'
+    const owenrId = '4bb43d76-6646-45e5-8a79-4aeb1ff8ec95'
+    const userId = 'e3780270-8f0d-4eb1-86e6-0139ca7ab8ed'
+
+    const admin = await prisma.users.create({
+      data: {
+        id: adminId,
+        email: 'admin@bmv.com',
+        password: hashedPassword,
+        first_name: 'Super',
+        last_name: 'Admin',
+        phone: '+91-9000000000',
+        role: 'ADMIN',
+        status: 'ACTIVE',
+      },
+    });
+
+    const owner1 = await prisma.users.create({
+      data: {
+        id: owenrId,
+        email: 'owner@bmv.com',
+        password: hashedPassword,
+        first_name: 'Owner',
+        last_name: 'Sharma',
+        phone: '+91-9811234567',
+        role: 'VENUE_OWNER',
+        status: 'ACTIVE',
+      },
+    });
+
+    const owner2 = await prisma.users.create({
+      data: {
+        email: 'priya.patel@bmv.com',
+        password: hashedPassword,
+        first_name: 'Priya',
+        last_name: 'Patel',
+        phone: '+91-9822345678',
+        role: 'VENUE_OWNER',
+        status: 'ACTIVE',
+      },
+    });
+
+    const owner3 = await prisma.users.create({
+      data: {
+        email: 'amit.verma@bmv.com',
+        password: hashedPassword,
+        first_name: 'Amit',
+        last_name: 'Verma',
+        phone: '+91-9833456789',
+        role: 'VENUE_OWNER',
+        status: 'ACTIVE',
+      },
+    });
+
+    const user1 = await prisma.users.create({
+      data: {
+        id: userId,
+        email: 'user@bmv.com',
+        password: hashedPassword,
+        first_name: 'John',
+        last_name: 'Doe',
+        phone: '+91-9844567890',
+        role: 'USER',
+        status: 'ACTIVE',
+      },
+    });
+
+    const user2 = await prisma.users.create({
+      data: {
+        email: 'sneha.gupta@bmv.com',
+        password: hashedPassword,
+        first_name: 'Sneha',
+        last_name: 'Gupta',
+        phone: '+91-9855678901',
+        role: 'USER',
+        status: 'ACTIVE',
+      },
+    });
+
+    const user3 = await prisma.users.create({
+      data: {
+        email: 'aryan.mehta@bmv.com',
+        password: hashedPassword,
+        first_name: 'Aryan',
+        last_name: 'Mehta',
+        phone: '+91-9866789012',
+        role: 'USER',
+        status: 'ACTIVE',
+      },
+    });
+
+    const user4 = await prisma.users.create({
+      data: {
+        email: 'deepika.nair@bmv.com',
+        password: hashedPassword,
+        first_name: 'Deepika',
+        last_name: 'Nair',
+        phone: '+91-9877890123',
+        role: 'USER',
+        status: 'ACTIVE',
+      },
+    });
+
+    const user5 = await prisma.users.create({
+      data: {
+        email: 'vikram.singh@bmv.com',
+        password: hashedPassword,
+        first_name: 'Vikram',
+        last_name: 'Singh',
+        phone: '+91-9888901234',
+        role: 'USER',
+        status: 'ACTIVE',
+      },
+    });
+
+    console.log('✅  9 users created (1 admin, 3 owners, 5 users).\n');
+
+    // ── 2. Venues (amenities stored as String[] on the venue) ──────
+    console.log('🏛   Seeding venues
');
+
+    // Owner 1 – Mumbai
+    const venue1 = await prisma.venues.create({
+      data: {
+        owner_id: owner1.id,
+        title: 'Grand Celebration Hall',
+        description:
+          'A stunning 5-star banquet hall nestled in the heart of Mumbai, ideal for grand weddings, corporate galas, and milestone celebrations. Features floor-to-ceiling windows with panoramic sea views, state-of-the-art lighting, and a dedicated bridal suite.',
+        venue_type: 'BANQUET_HALL',
+        address_line_1: '14, Marine Drive',
+        city: 'Mumbai',
+        state: 'Maharashtra',
+        country: 'India',
+        postal_code: '400001',
+        latitude: 18.9441,
+        longitude: 72.8233,
+        capacity: 500,
+        price_per_day: 120000.0,
+        status: 'APPROVED',
+        amenities: VENUE_AMENITIES.grand_hall,
+      },
+    });
+
+    const venue2 = await prisma.venues.create({
+      data: {
+        owner_id: owner1.id,
+        title: 'Seaside Conference Centre',
+        description:
+          'A modern, fully-equipped conference centre overlooking the Arabian Sea. Perfect for corporate seminars, product launches, and executive off-sites. High-speed fibre internet, modular breakout rooms, and in-house catering available.',
+        venue_type: 'CONFERENCE_HALL',
+        address_line_1: '7, Nariman Point',
+        city: 'Mumbai',
+        state: 'Maharashtra',
+        country: 'India',
+        postal_code: '400021',
+        latitude: 18.9255,
+        longitude: 72.8242,
+        capacity: 200,
+        price_per_day: 55000.0,
+        status: 'APPROVED',
+        amenities: VENUE_AMENITIES.conference,
+      },
+    });
+
+    // Owner 2 – Delhi
+    const venue3 = await prisma.venues.create({
+      data: {
+        owner_id: owner2.id,
+        title: 'Royal Garden Palace',
+        description:
+          'An opulent wedding palace spread across 3 acres in South Delhi, featuring lush manicured gardens, an ornate ballroom, and a heritage courtyard. Our in-house décor team crafts bespoke experiences for each event.',
+        venue_type: 'WEDDING_HALL',
+        address_line_1: '22, Mehrauli Road',
+        city: 'Delhi',
+        state: 'Delhi',
+        country: 'India',
+        postal_code: '110030',
+        latitude: 28.5244,
+        longitude: 77.1855,
+        capacity: 800,
+        price_per_day: 250000.0,
+        status: 'APPROVED',
+        amenities: VENUE_AMENITIES.wedding,
+      },
+    });
+
+    const venue4 = await prisma.venues.create({
+      data: {
+        owner_id: owner2.id,
+        title: 'Elite Business Hub',
+        description:
+          'Premium co-working and event space in Connaught Place offering flexible conference rooms, a large training hall, and networking lounges. Ideal for workshops, board meetings, and company town halls.',
+        venue_type: 'CONFERENCE_HALL',
+        address_line_1: 'Block A, Connaught Place',
+        city: 'Delhi',
+        state: 'Delhi',
+        country: 'India',
+        postal_code: '110001',
+        latitude: 28.6315,
+        longitude: 77.2167,
+        capacity: 150,
+        price_per_day: 38000.0,
+        status: 'APPROVED',
+        amenities: VENUE_AMENITIES.elite_biz,
+      },
+    });
+
+    const venue5 = await prisma.venues.create({
+      data: {
+        owner_id: owner2.id,
+        title: 'The Rooftop Lounge & Events',
+        description:
+          'Chic open-air rooftop venue perched 14 floors above Delhi with a breathtaking city skyline backdrop. Ideal for sunset cocktail parties, private celebrations, and intimate corporate evenings.',
+        venue_type: 'PARTY_HALL',
+        address_line_1: '45, Cyber City Tower',
+        city: 'Delhi',
+        state: 'Delhi',
+        country: 'India',
+        postal_code: '110048',
+        latitude: 28.4964,
+        longitude: 77.0912,
+        capacity: 100,
+        price_per_day: 45000.0,
+        status: 'PENDING',
+        amenities: VENUE_AMENITIES.rooftop,
+      },
+    });
+
+    // Owner 3 – Bangalore
+    const venue6 = await prisma.venues.create({
+      data: {
+        owner_id: owner3.id,
+        title: 'Tech Park Convention Centre',
+        description:
+          'A cutting-edge convention centre located in Whitefield, designed for large-scale tech conferences, hackathons, and corporate summits. Features 4K laser projection, simultaneous interpretation booths, and enterprise-grade AV infrastructure.',
+        venue_type: 'CONFERENCE_HALL',
+        address_line_1: 'ITPL Road, Whitefield',
+        city: 'Bangalore',
+        state: 'Karnataka',
+        country: 'India',
+        postal_code: '560066',
+        latitude: 12.9784,
+        longitude: 77.7477,
+        capacity: 600,
+        price_per_day: 95000.0,
+        status: 'APPROVED',
+        amenities: VENUE_AMENITIES.tech_park,
+      },
+    });
+
+    const venue7 = await prisma.venues.create({
+      data: {
+        owner_id: owner3.id,
+        title: 'Garden Grove Outdoor Events',
+        description:
+          'A serene 2-acre garden retreat in South Bangalore, perfect for open-air receptions, themed celebrations, and nature-inspired weddings. Features a covered pavilion, ambient lighting, and on-site parking for 150 vehicles.',
+        venue_type: 'GARDEN_VENUE',
+        address_line_1: '88, Bannerghatta Road',
+        city: 'Bangalore',
+        state: 'Karnataka',
+        country: 'India',
+        postal_code: '560076',
+        latitude: 12.8826,
+        longitude: 77.5970,
+        capacity: 350,
+        price_per_day: 70000.0,
+        status: 'APPROVED',
+        amenities: VENUE_AMENITIES.garden,
+      },
+    });
+
+    const venue8 = await prisma.venues.create({
+      data: {
+        owner_id: owner3.id,
+        title: 'Skyline Banquet & Events',
+        description:
+          'A modern banquet hall in Indiranagar with a contemporary design aesthetic. Accommodates up to 250 guests with flexible seating arrangements. Pending re-inspection after recent renovations.',
+        venue_type: 'BANQUET_HALL',
+        address_line_1: '12, 100 Feet Road, Indiranagar',
+        city: 'Bangalore',
+        state: 'Karnataka',
+        country: 'India',
+        postal_code: '560038',
+        latitude: 12.9784,
+        longitude: 77.6408,
+        capacity: 250,
+        price_per_day: 58000.0,
+        status: 'REJECTED',
+        amenities: VENUE_AMENITIES.banquet,
+      },
+    });
+
+    console.log('✅  8 venues created.\n');
+
+    // ── 3. Venue Images ────────────────────────────────────────────
+    console.log('đŸ–Œ   Seeding venue images
');
+
+    const imageInserts: Array<{
+      venue_id: string;
+      image_url: string;
+      sort_order: number;
+    }> = [];
+
+    const venueImageMap: Array<[string, string[]]> = [
+      [venue1.id, VENUE_IMAGES.grand_hall],
+      [venue2.id, VENUE_IMAGES.conference],
+      [venue3.id, VENUE_IMAGES.wedding],
+      [venue4.id, VENUE_IMAGES.conference],
+      [venue5.id, VENUE_IMAGES.rooftop],
+      [venue6.id, VENUE_IMAGES.conference],
+      [venue7.id, VENUE_IMAGES.outdoor],
+      [venue8.id, VENUE_IMAGES.banquet],
+    ];
+
+    for (const [venueId, urls] of venueImageMap) {
+      urls.forEach((url, idx) =>
+        imageInserts.push({ venue_id: venueId, image_url: url, sort_order: idx }),
+      );
+    }
+
+    await prisma.venue_images.createMany({ data: imageInserts });
+    console.log(`✅  ${imageInserts.length} venue images created.\n`);
+
+    // ── 4. Bookings ────────────────────────────────────────────────
+    console.log('📅  Seeding bookings
');
+
+    const booking1 = await prisma.bookings.create({
+      data: {
+        user_id: user1.id,
+        venue_id: venue1.id,
+        booking_start: daysAgo(30),
+        booking_end: daysAgo(28),
+        guests_count: 300,
+        total_amount: 240000.0,
+        created_at: daysAgo(45),
+      },
+    });
+
+    const booking2 = await prisma.bookings.create({
+      data: {
+        user_id: user2.id,
+        venue_id: venue3.id,
+        booking_start: daysAgo(60),
+        booking_end: daysAgo(59),
+        guests_count: 600,
+        total_amount: 250000.0,
+        created_at: daysAgo(75),
+      },
+    });
+
+    const booking3 = await prisma.bookings.create({
+      data: {
+        user_id: user3.id,
+        venue_id: venue6.id,
+        booking_start: daysFromNow(15),
+        booking_end: daysFromNow(16),
+        guests_count: 400,
+        total_amount: 95000.0,
+        created_at: daysAgo(5),
+      },
+    });
+
+    const booking4 = await prisma.bookings.create({
+      data: {
+        user_id: user4.id,
+        venue_id: venue7.id,
+        booking_start: daysFromNow(30),
+        booking_end: daysFromNow(31),
+        guests_count: 200,
+        total_amount: 70000.0,
+        created_at: daysAgo(2),
+      },
+    });
+
+    const booking5 = await prisma.bookings.create({
+      data: {
+        user_id: user5.id,
+        venue_id: venue2.id,
+        booking_start: daysAgo(15),
+        booking_end: daysAgo(14),
+        guests_count: 80,
+        total_amount: 55000.0,
+        created_at: daysAgo(30),
+      },
+    });
+
+    const booking6 = await prisma.bookings.create({
+      data: {
+        user_id: user1.id,
+        venue_id: venue4.id,
+        booking_start: daysFromNow(7),
+        booking_end: daysFromNow(8),
+        guests_count: 100,
+        total_amount: 38000.0,
+        created_at: new Date(),
+      },
+    });
+
+    console.log('✅  6 bookings created.\n');
+
+    // ── Summary ────────────────────────────────────────────────────
+    console.log('─'.repeat(50));
+    console.log('🎉  Seed complete! Summary:');
+    console.log(`    ‱ ${AMENITIES.length} amenities available (from constants)`);
+    console.log(`    ‱ 9 users`);
+    console.log(`        - admin@bmv.com          (password123)`);
+    console.log(`        - owner@bmv.com          (password123)`);
+    console.log(`        - priya.patel@bmv.com    (password123)`);
+    console.log(`        - amit.verma@bmv.com     (password123)`);
+    console.log(`        - user@bmv.com           (password123)`);
+    console.log(`        - sneha.gupta@bmv.com    (password123)`);
+    console.log(`        - aryan.mehta@bmv.com    (password123)`);
+    console.log(`        - deepika.nair@bmv.com   (password123)`);
+    console.log(`        - vikram.singh@bmv.com   (password123)`);
+    console.log(`    ‱ 8 venues (5 approved, 1 pending, 1 rejected)`);
+    console.log(`    ‱ ${imageInserts.length} venue images`);
+    console.log(`    ‱ 6 bookings`);
+    console.log('─'.repeat(50));
+  } finally {
+    await prisma.$disconnect();
+  }
+}
+
+main().catch((err) => {
+  console.error('❌  Seed failed:', err);
+  process.exit(1);
+});
diff --git a/backend/src/config/app.config.ts b/backend/src/config/app.config.ts
new file mode 100644
index 000000000..dd8390459
--- /dev/null
+++ b/backend/src/config/app.config.ts
@@ -0,0 +1,30 @@
+import 'dotenv/config'
+import { cleanEnv, port, str } from 'envalid'
+
+
+cleanEnv(process.env, {
+    PORT: port(),
+    BASE_URL: str(),
+    RAZORPAY_KEY_ID: str(),
+    RAZORPAY_SECRET: str(),
+    NOVU_SECRET_KEY: str(),
+    DATABASE_URL: str()
+})
+
+
+export const APP_CONFIG = {
+    BASE_URL: process.env.BASE_URL!
+}
+
+export const PAYMENT_CONFIG = {
+    RAZORPAY_KEY_ID: process.env.RAZORPAY_KEY_ID!,
+    RAZORPAY_SECRET: process.env.RAZORPAY_SECRET!,
+}
+
+export const NOTIFICATION_CONFIG = {
+    NOVU_SECRET_KEY: process.env.NOVU_SECRET_KEY!
+}
+
+export const DB_CONFIG = {
+    DATABASE_URL: process.env.DATABASE_URL!
+}
\ No newline at end of file
diff --git a/backend/src/constants/amenities.ts b/backend/src/constants/amenities.ts
new file mode 100644
index 000000000..8d2c3f51d
--- /dev/null
+++ b/backend/src/constants/amenities.ts
@@ -0,0 +1,24 @@
+export const AMENITIES = [
+  'WiFi',
+  'Parking',
+  'Air Conditioning',
+  'Projector & Screen',
+  'Catering Services',
+  'Sound System',
+  'Fully Equipped Kitchen',
+  'Stage & Podium',
+  '24/7 Security',
+  'Swimming Pool',
+  'Generator Backup',
+  'Wheelchair Access',
+  'Valet Parking',
+  'Bridal Suite',
+  'Locker Rooms',
+  'Dance Floor',
+  'Open Bar',
+  'Photo Booth Area',
+  'Outdoor Terrace',
+  'Green Room / Dressing Room',
+] as const;
+
+export type Amenity = (typeof AMENITIES)[number];
diff --git a/backend/src/constants/venue-type.ts b/backend/src/constants/venue-type.ts
new file mode 100644
index 000000000..14536e3d8
--- /dev/null
+++ b/backend/src/constants/venue-type.ts
@@ -0,0 +1,148 @@
+export const VENUE_TYPES = [
+    {
+        value: 'BANQUET_HALL',
+        label: 'Banquet Hall',
+    },
+    {
+        value: 'BIRTHDAY_PARTY_HALL',
+        label: 'Birthday Party Hall',
+    },
+    {
+        value: 'WEDDING_HALL',
+        label: 'Wedding Hall',
+    },
+    {
+        value: 'AUDITORIUM',
+        label: 'Auditorium',
+    },
+    {
+        value: 'CONVENTION_CENTER',
+        label: 'Convention Center',
+    },
+    {
+        value: 'MEETING_ROOM',
+        label: 'Meeting Room',
+    },
+    {
+        value: 'CONFERENCE_HALL',
+        label: 'Conference Hall',
+    },
+    {
+        value: 'SEMINAR_HALL',
+        label: 'Seminar Hall',
+    },
+    {
+        value: 'TRAINING_ROOM',
+        label: 'Training Room',
+    },
+    {
+        value: 'WORKSHOP_SPACE',
+        label: 'Workshop Space',
+    },
+    {
+        value: 'CO_WORKING_SPACE',
+        label: 'Co-working Space',
+    },
+    {
+        value: 'EVENT_SPACE',
+        label: 'Event Space',
+    },
+    {
+        value: 'EXHIBITION_HALL',
+        label: 'Exhibition Hall',
+    },
+    {
+        value: 'COMMUNITY_HALL',
+        label: 'Community Hall',
+    },
+    {
+        value: 'CLUB_HOUSE',
+        label: 'Club House',
+    },
+    {
+        value: 'PARTY_HALL',
+        label: 'Party Hall',
+    },
+    {
+        value: 'ROOFTOP_VENUE',
+        label: 'Rooftop Venue',
+    },
+    {
+        value: 'OPEN_GROUND',
+        label: 'Open Ground',
+    },
+    {
+        value: 'OUTDOOR_VENUE',
+        label: 'Outdoor Venue',
+    },
+    {
+        value: 'GARDEN_VENUE',
+        label: 'Garden Venue',
+    },
+    {
+        value: 'BEACH_VENUE',
+        label: 'Beach Venue',
+    },
+    {
+        value: 'RESORT',
+        label: 'Resort',
+    },
+    {
+        value: 'HOTEL',
+        label: 'Hotel',
+    },
+    {
+        value: 'HOTEL_BANQUET_HALL',
+        label: 'Hotel Banquet Hall',
+    },
+    {
+        value: 'RESTAURANT_PARTY_SPACE',
+        label: 'Restaurant Party Space',
+    },
+    {
+        value: 'CAFE_EVENT_SPACE',
+        label: 'Cafe Event Space',
+    },
+    {
+        value: 'VILLA',
+        label: 'Villa',
+    },
+    {
+        value: 'FARM_HOUSE',
+        label: 'Farm House',
+    },
+    {
+        value: 'PRIVATE_HOME',
+        label: 'Private Home',
+    },
+    {
+        value: 'SPORTS_VENUE',
+        label: 'Sports Venue',
+    },
+    {
+        value: 'TURF',
+        label: 'Turf',
+    },
+    {
+        value: 'STADIUM',
+        label: 'Stadium',
+    },
+    {
+        value: 'ART_GALLERY',
+        label: 'Art Gallery',
+    },
+    {
+        value: 'PHOTO_STUDIO',
+        label: 'Photo Studio',
+    },
+    {
+        value: 'FILM_SHOOT_LOCATION',
+        label: 'Film Shoot Location',
+    },
+    {
+        value: 'OTHER',
+        label: 'Other',
+    },
+] as const;
+
+export type VenueType = typeof VENUE_TYPES[number]['value'];
\ No newline at end of file
diff --git a/backend/src/core/application/_shared/dto/pagination.ts b/backend/src/core/application/_shared/dto/pagination.ts
new file mode 100644
index 000000000..94fddc0a8
--- /dev/null
+++ b/backend/src/core/application/_shared/dto/pagination.ts
@@ -0,0 +1,57 @@
+
+export interface PaginationFilter {
+    limit: number,
+    offset: number,
+    search?: string
+}
+
+type PaginationProps = {
+    limit: number,
+    offset: number,
+    total: number
+    data: T[]
+}
+
+export class Pagination {
+
+    public readonly page: number
+    public readonly total: number
+    public readonly offset: number
+    public readonly limit: number
+    public readonly data: T[]
+
+    constructor(readonly props: PaginationProps) {
+        this.page = (props.offset / props.limit) + 1
+        this.total = props.total
+        this.offset = props.offset
+        this.limit = props.limit
+        this.data = props.data
+    }
+
+    get totalPages(): number {
+        return Math.ceil(
+            this.total / this.limit,
+        );
+    }
+
+    get hasNext(): boolean {
+        return this.page < this.totalPages;
+    }
+
+    get hasPrevious(): boolean {
+        return this.page > 1;
+    }
+
+    toJSON() {
+        return {
+            data: this.data,
+            total: this.total,
+            page: this.page,
+            limit: this.limit,
+            offset: this.offset,
+            totalPages: this.totalPages,
+            hasNext: this.hasNext,
+            hasPrevious: this.hasPrevious,
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/core/application/_shared/logger/ILogger.ts b/backend/src/core/application/_shared/logger/ILogger.ts
new file mode 100644
index 000000000..97ae5e6af
--- /dev/null
+++ b/backend/src/core/application/_shared/logger/ILogger.ts
@@ -0,0 +1,11 @@
+export interface ILogger {
+  info(message: string, meta?: Record): void;
+
+  warn(message: string, meta?: Record): void;
+
+  error(message: string, trace?: string, meta?: Record): void;
+
+  debug(message: string, meta?: Record): void;
+
+  verbose(message: string, meta?: Record): void;
+}
diff --git a/backend/src/core/application/_shared/storage/file-storage.interface.ts b/backend/src/core/application/_shared/storage/file-storage.interface.ts
new file mode 100644
index 000000000..6f0e3146b
--- /dev/null
+++ b/backend/src/core/application/_shared/storage/file-storage.interface.ts
@@ -0,0 +1,8 @@
+export interface IFileStorage {
+    upload(
+        fileName: string,
+        buffer: Buffer,
+    ): Promise;
+
+    delete(path: string): Promise;
+}
\ No newline at end of file
diff --git a/backend/src/core/application/admin/commands/approve-venue.command.ts b/backend/src/core/application/admin/commands/approve-venue.command.ts
new file mode 100644
index 000000000..1902c0bab
--- /dev/null
+++ b/backend/src/core/application/admin/commands/approve-venue.command.ts
@@ -0,0 +1,28 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IVenueRepository } from '../../../domain/venues/repositories/venue-repository.interface';
+import { NotFoundException } from '../../../domain/_shared/exception/notfound.exception';
+import { BusinessRuleException } from '../../../domain/_shared/exception/business-rule.exception';
+
+
+@Injectable()
+export class ApproveVenueCommand {
+  constructor(
+    @Inject('IVenueRepository')
+    private readonly venueRepository: IVenueRepository,
+  ) { }
+
+  async execute(venueId: string): Promise<{ message: string }> {
+
+    const venue = await this.venueRepository.findById(venueId);
+    if (!venue) {
+      throw new NotFoundException('Venue not found');
+    }
+
+    venue.approve();
+
+    await this.venueRepository.save(venue);
+
+    return { message: 'Venue approved' }
+
+  }
+}
diff --git a/backend/src/core/application/admin/commands/create-user.command.ts b/backend/src/core/application/admin/commands/create-user.command.ts
new file mode 100644
index 000000000..d602d4eac
--- /dev/null
+++ b/backend/src/core/application/admin/commands/create-user.command.ts
@@ -0,0 +1,72 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { User, } from '../../../domain/users/entities/user.entity';
+import { type IUserRepository } from '../../../domain/users/repositories/user-repository.interface';
+import { type IPasswordHasher } from '../../users/services/password-hasher.interface';
+import { BusinessRuleException } from '../../../domain/_shared/exception/business-rule.exception';
+import * as crypto from 'crypto';
+import type { UserRole } from 'src/core/domain/_shared/enum/UserRole';
+import type { INotificationService } from 'src/core/domain/notification/notification.service.interface';
+
+export interface CreateUserDto {
+  email: string;
+  password?: string;
+  firstName: string;
+  lastName?: string;
+  phone?: string;
+  role: UserRole.USER | UserRole.VENUE_OWNER;
+}
+
+@Injectable()
+export class CreateUserCommand {
+  constructor(
+    @Inject('IUserRepository')
+    private readonly userRepository: IUserRepository,
+    @Inject('IPasswordHasher')
+    private readonly passwordHasher: IPasswordHasher,
+    @Inject('INotificationService')
+    private readonly notificationService: INotificationService
+  ) { }
+
+  async execute(dto: CreateUserDto): Promise<{ userId: string }> {
+    const existing = await this.userRepository.findByEmail(dto.email);
+    if (existing) {
+      throw new BusinessRuleException('Email is already registered');
+    }
+
+    let hashedPassword: string | undefined = undefined;
+    if (dto.password) {
+      hashedPassword = await this.passwordHasher.hash(dto.password);
+    }
+
+    const userId = crypto.randomUUID();
+    const user = User.create(userId, {
+      email: dto.email,
+      password: hashedPassword,
+      firstName: dto.firstName,
+      lastName: dto.lastName || null,
+      phone: dto.phone || null,
+      role: dto.role,
+      status: 'ACTIVE',
+    });
+
+    await this.userRepository.save(user);
+
+    await this.notificationService.createSubscriber({
+      email: user.email,
+      subscriberId: user.id,
+      firstName: user.firstName,
+      lastName: user.lastName || '',
+      phone: user.phone || ''
+    })
+
+    await this.notificationService.trigger({
+      subscriberId: user.id,
+      payload: {
+        title: 'Welcome to bmv',
+        message: `Hi ${user.firstName}, welcome to BMV. we are happy to see here`
+      }
+    })
+
+    return { userId };
+  }
+}
diff --git a/backend/src/core/application/admin/commands/reject-venue.command.ts b/backend/src/core/application/admin/commands/reject-venue.command.ts
new file mode 100644
index 000000000..f5573b9e3
--- /dev/null
+++ b/backend/src/core/application/admin/commands/reject-venue.command.ts
@@ -0,0 +1,26 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IVenueRepository } from '../../../domain/venues/repositories/venue-repository.interface';
+import { NotFoundException } from '../../../domain/_shared/exception/notfound.exception';
+
+
+@Injectable()
+export class RejectVenueCommand {
+    constructor(
+        @Inject('IVenueRepository')
+        private readonly venueRepository: IVenueRepository,
+    ) { }
+
+    async execute(venueId: string): Promise<{ message: string }> {
+
+        const venue = await this.venueRepository.findById(venueId);
+        if (!venue) {
+            throw new NotFoundException('Venue not found');
+        }
+
+        venue.reject()
+
+        await this.venueRepository.save(venue);
+
+        return { message: 'Venue rejected' }
+    }
+}
diff --git a/backend/src/core/application/admin/queries/list-venues.query.ts b/backend/src/core/application/admin/queries/list-venues.query.ts
new file mode 100644
index 000000000..32eeb1004
--- /dev/null
+++ b/backend/src/core/application/admin/queries/list-venues.query.ts
@@ -0,0 +1,58 @@
+import { Injectable, Inject } from '@nestjs/common';
+import type { IVenueRepository } from 'src/core/domain/venues/repositories/venue-repository.interface';
+import { Pagination } from '../../_shared/dto/pagination';
+
+export interface ListVenueQueryOutputDto {
+    id: string
+    ownerId: string
+    title: string
+    description: string
+    venueType: string
+    addressLine1: string
+    capacity: number
+    pricePerDay: number
+    status: string
+    createdAt: Date
+    updatedAt: Date
+}
+
+export interface ListVenueQueryInputDto {
+    offset: number
+    limit: number
+    search: string
+}
+
+@Injectable()
+export class ListVenueQuery {
+    constructor(
+        @Inject('IVenueRepository')
+        private readonly venueRepository: IVenueRepository,
+    ) { }
+
+    async execute(params: ListVenueQueryInputDto): Promise> {
+
+        const response = await this.venueRepository.findAll()
+
+        const venues = response.map(item => ({
+            id: item.id,
+            ownerId: item.ownerId,
+            capacity: item.capacity,
+            description: item.description,
+            title: item.title,
+            pricePerDay: item.pricePerDay,
+            status: item.status,
+            venueType: item.venueType,
+            addressLine1: item.address.addressLine1,
+            createdAt: item.createdAt,
+            updatedAt: item.updatedAt
+        }))
+
+        return new Pagination({
+            data: venues,
+            total: response.length,
+            offset: 0,
+            limit: params.limit
+        })
+
+    }
+}
diff --git a/backend/src/core/application/bookings/commands/cancel-booking.command.ts b/backend/src/core/application/bookings/commands/cancel-booking.command.ts
new file mode 100644
index 000000000..7b9f2c07b
--- /dev/null
+++ b/backend/src/core/application/bookings/commands/cancel-booking.command.ts
@@ -0,0 +1,37 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IBookingRepository } from '../../../domain/bookings/repositories/booking-repository.interface';
+import { NotFoundException } from '../../../domain/_shared/exception/notfound.exception';
+import { BusinessRuleException } from '../../../domain/_shared/exception/business-rule.exception';
+
+export interface CancelBookingDto {
+  bookingId: string;
+  userId: string;
+  userRole: string;
+}
+
+@Injectable()
+export class CancelBookingCommand {
+  constructor(
+    @Inject('IBookingRepository')
+    private readonly bookingRepository: IBookingRepository,
+  ) { }
+
+  async execute(dto: CancelBookingDto): Promise {
+    const booking = await this.bookingRepository.findById(dto.bookingId);
+    if (!booking) {
+      throw new NotFoundException('Booking not found');
+    }
+
+    // Authorization
+    if (booking.userId !== dto.userId && dto.userRole !== 'ADMIN') {
+      throw new BusinessRuleException('You do not have permission to cancel this booking');
+    }
+
+    // Enforce booking cancellation rules, e.g. cannot cancel past bookings
+    if (booking.dateRange.startDate < new Date()) {
+      throw new BusinessRuleException('Cannot cancel a booking that has already started');
+    }
+
+    await this.bookingRepository.delete(dto.bookingId);
+  }
+}
diff --git a/backend/src/core/application/bookings/commands/create-booking.command.ts b/backend/src/core/application/bookings/commands/create-booking.command.ts
new file mode 100644
index 000000000..3daaaec8f
--- /dev/null
+++ b/backend/src/core/application/bookings/commands/create-booking.command.ts
@@ -0,0 +1,85 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { Booking } from '../../../domain/bookings/entities/booking.entity';
+import { DateRange } from '../../../domain/bookings/value-objects/date-range.vo';
+import { type IBookingRepository } from '../../../domain/bookings/repositories/booking-repository.interface';
+import { type IVenueRepository } from '../../../domain/venues/repositories/venue-repository.interface';
+import { NotFoundException } from '../../../domain/_shared/exception/notfound.exception';
+import { BusinessRuleException } from '../../../domain/_shared/exception/business-rule.exception';
+import * as crypto from 'crypto';
+import { BookingStatus } from 'src/core/domain/bookings/enum/booking-status.enum';
+import { PaymentStatus } from 'src/core/domain/_shared/enum/PaymentStatus.enum';
+import type { INotificationService } from 'src/core/domain/notification/notification.service.interface';
+
+export interface CreateBookingDto {
+  userId: string;
+  venueId: string;
+  startDate: Date;
+  endDate: Date;
+  guestsCount: number;
+}
+
+@Injectable()
+export class CreateBookingCommand {
+  constructor(
+    @Inject('IBookingRepository')
+    private readonly bookingRepository: IBookingRepository,
+    @Inject('IVenueRepository')
+    private readonly venueRepository: IVenueRepository,
+    @Inject('INotificationService')
+    private readonly notificationService: INotificationService
+  ) { }
+
+  async execute(dto: CreateBookingDto): Promise<{ bookingId: string; totalAmount: number }> {
+    const venue = await this.venueRepository.findById(dto.venueId);
+    if (!venue) {
+      throw new NotFoundException('Venue not found');
+    }
+
+    if (venue.status !== 'APPROVED') {
+      throw new BusinessRuleException('Cannot book a venue that is not approved');
+    }
+
+    if (dto.guestsCount > venue.capacity) {
+      throw new BusinessRuleException(`Guests count exceeds venue capacity of ${venue.capacity}`);
+    }
+
+    const dateRange = DateRange.create(dto.startDate, dto.endDate);
+
+    const isAvailable = await this.bookingRepository.checkAvailability(
+      dto.venueId,
+      dateRange.startDate,
+      dateRange.endDate,
+    );
+    if (!isAvailable) {
+      throw new BusinessRuleException('Venue is already booked for the selected dates');
+    }
+
+    const bookingId = crypto.randomUUID();
+    const booking = Booking.create(bookingId, {
+      userId: dto.userId,
+      venueId: dto.venueId,
+      dateRange,
+      guestsCount: dto.guestsCount,
+      totalAmount: 0,
+      status: BookingStatus.BOOKED,
+      paymentStatus: PaymentStatus.PENDING,
+    });
+
+    booking.calculateTotalAmount(venue.pricePerDay);
+
+    await this.bookingRepository.save(booking);
+
+    await this.notificationService.trigger({
+      subscriberId: dto.userId,
+      payload: {
+        title: 'Booking confirmed',
+        message: `Your booking for ${venue.title} has been success`
+      }
+    })
+
+    return {
+      bookingId,
+      totalAmount: booking.totalAmount,
+    };
+  }
+}
diff --git a/backend/src/core/application/bookings/queries/get-booking-details.query.ts b/backend/src/core/application/bookings/queries/get-booking-details.query.ts
new file mode 100644
index 000000000..c75a9c60d
--- /dev/null
+++ b/backend/src/core/application/bookings/queries/get-booking-details.query.ts
@@ -0,0 +1,88 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IBookingRepository } from '../../../domain/bookings/repositories/booking-repository.interface';
+import { NotFoundException } from 'src/core/domain/_shared/exception/notfound.exception';
+import { UserRole } from 'src/core/domain/_shared/enum/UserRole';
+import type { BookingStatus } from 'src/core/domain/bookings/enum/booking-status.enum';
+import type { PaymentStatus } from 'src/core/domain/_shared/enum/PaymentStatus.enum';
+
+export interface BookingDetailsResponseDto {
+    id: string;
+    startDate: Date;
+    endDate: Date;
+    guestsCount: number;
+    totalAmount: number;
+    status: BookingStatus,
+    paymentStatus: PaymentStatus
+    createdAt: Date;
+    user: {
+        id: string
+        firstName: string,
+        lastName: string,
+        phone: string | null | undefined,
+        email: string
+    }
+    venue: {
+        id: string
+        title: string,
+        address: string,
+        images: string[]
+    }
+}
+
+interface BookingDetailsInputDto {
+    bookingId: string,
+    userId: string
+    role: UserRole
+}
+
+@Injectable()
+export class GetBookingDetailsQuery {
+    constructor(
+        @Inject('IBookingRepository')
+        private readonly bookingRepository: IBookingRepository,
+    ) { }
+
+    async execute({
+        bookingId,
+        role,
+        userId
+    }: BookingDetailsInputDto): Promise {
+        const booking = await this.bookingRepository.findById(bookingId);
+
+        if (!booking) throw new NotFoundException('invalid booking id, booking not found')
+
+        // booking details is only accessible by the venue owner or booking 
+        if (role === UserRole.USER && booking.userId !== userId) {
+            throw new NotFoundException('invalid booking id')
+        }
+
+        if (role === UserRole.VENUE_OWNER && booking.venue!.ownerId !== userId) {
+            throw new NotFoundException('invalid booking')
+        }
+
+
+        return {
+            id: booking.id,
+            startDate: booking.dateRange.startDate,
+            endDate: booking.dateRange.endDate,
+            guestsCount: booking.guestsCount,
+            totalAmount: booking.totalAmount,
+            status: booking.status,
+            paymentStatus: booking.paymentStatus,
+            createdAt: booking.createdAt,
+            user: {
+                id: booking.user!.id,
+                firstName: booking.user!.firstName,
+                lastName: booking.user!.lastName,
+                email: booking.user!.email,
+                phone: booking.user!.phone,
+            },
+            venue: {
+                id: booking.venue!.id,
+                title: booking.venue!.title,
+                address: '',
+                images: booking.venue!.images
+            }
+        }
+    }
+}
diff --git a/backend/src/core/application/bookings/queries/get-bookings-for-owner.query.ts b/backend/src/core/application/bookings/queries/get-bookings-for-owner.query.ts
new file mode 100644
index 000000000..e372fc10c
--- /dev/null
+++ b/backend/src/core/application/bookings/queries/get-bookings-for-owner.query.ts
@@ -0,0 +1,54 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IBookingRepository } from '../../../domain/bookings/repositories/booking-repository.interface';
+import { Pagination } from '../../_shared/dto/pagination';
+import type { BookingStatus } from 'src/core/domain/bookings/enum/booking-status.enum';
+import type { PaymentStatus } from 'src/core/domain/_shared/enum/PaymentStatus.enum';
+
+export interface BookingResponseDto {
+    id: string;
+    userId: string;
+    venueId: string;
+    startDate: Date;
+    endDate: Date;
+    guestsCount: number;
+    totalAmount: number;
+    status: BookingStatus
+    paymentStatus: PaymentStatus
+    createdAt: Date;
+}
+
+@Injectable()
+export class GetBookingsByOwnerQuery {
+    constructor(
+        @Inject('IBookingRepository')
+        private readonly bookingRepository: IBookingRepository,
+    ) { }
+
+    async execute(ownerId: string): Promise> {
+        const bookings = await this.bookingRepository.findByOwnerId(ownerId);
+
+        const docs = bookings.map((b) => ({
+            id: b.id,
+            userId: b.userId,
+            venueId: b.venueId,
+            startDate: b.dateRange.startDate,
+            endDate: b.dateRange.endDate,
+            guestsCount: b.guestsCount,
+            totalAmount: b.totalAmount,
+            status: b.status,
+            paymentStatus: b.paymentStatus,
+            createdAt: b.createdAt,
+            venue: {
+                id: b.venue!.id,
+                title: b.venue!.title,
+            }
+        }));
+
+        return new Pagination({
+            data: docs,
+            total: docs.length,
+            offset: 0,
+            limit: docs.length
+        })
+    }
+}
diff --git a/backend/src/core/application/bookings/queries/get-user-bookings.query.ts b/backend/src/core/application/bookings/queries/get-user-bookings.query.ts
new file mode 100644
index 000000000..55d49dfbf
--- /dev/null
+++ b/backend/src/core/application/bookings/queries/get-user-bookings.query.ts
@@ -0,0 +1,58 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IBookingRepository } from '../../../domain/bookings/repositories/booking-repository.interface';
+import { Pagination } from '../../_shared/dto/pagination';
+import type { BookingStatus } from 'src/core/domain/bookings/enum/booking-status.enum';
+import type { PaymentStatus } from 'src/core/domain/_shared/enum/PaymentStatus.enum';
+
+export interface BookingResponseDto {
+  id: string;
+  userId: string;
+  startDate: Date;
+  endDate: Date;
+  guestsCount: number;
+  totalAmount: number;
+  status: BookingStatus
+  paymentStatus: PaymentStatus
+  createdAt: Date;
+  venue: {
+    id: string;
+    title: string
+    images: string[]
+  }
+}
+
+@Injectable()
+export class GetUserBookingsQuery {
+  constructor(
+    @Inject('IBookingRepository')
+    private readonly bookingRepository: IBookingRepository,
+  ) { }
+
+  async execute(userId: string): Promise> {
+    const bookings = await this.bookingRepository.findByUserId(userId);
+
+    const docs = bookings.map((b) => ({
+      id: b.id,
+      userId: b.userId,
+      startDate: b.dateRange?.startDate,
+      endDate: b.dateRange?.endDate,
+      guestsCount: b.guestsCount,
+      totalAmount: b.totalAmount,
+      status: b.status,
+      paymentStatus: b.paymentStatus,
+      createdAt: b.createdAt,
+      venue: {
+        id: b.venue!.id,
+        title: b.venue!.title,
+        images: b.venue!.images
+      }
+    }));
+
+    return new Pagination({
+      data: docs,
+      total: docs.length,
+      offset: 0,
+      limit: docs.length
+    })
+  }
+}
diff --git a/backend/src/core/application/bookings/queries/get-venue-bookings.query.ts b/backend/src/core/application/bookings/queries/get-venue-bookings.query.ts
new file mode 100644
index 000000000..56b84de65
--- /dev/null
+++ b/backend/src/core/application/bookings/queries/get-venue-bookings.query.ts
@@ -0,0 +1,53 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IBookingRepository } from '../../../domain/bookings/repositories/booking-repository.interface';
+import type { IVenueRepository } from 'src/core/domain/venues/repositories/venue-repository.interface';
+import { NotFoundException } from 'src/core/domain/_shared/exception/notfound.exception';
+import { BusinessRuleException } from 'src/core/domain/_shared/exception/business-rule.exception';
+import type { BookingStatus } from 'src/core/domain/bookings/enum/booking-status.enum';
+import type { PaymentStatus } from 'src/core/domain/_shared/enum/PaymentStatus.enum';
+
+export interface BookingResponseDto {
+    id: string;
+    userId: string;
+    venueId: string;
+    startDate: Date;
+    endDate: Date;
+    guestsCount: number;
+    totalAmount: number;
+    status: BookingStatus
+    paymentStatus: PaymentStatus
+    createdAt: Date;
+}
+
+@Injectable()
+export class GetBookingsByVenueQuery {
+    constructor(
+        @Inject('IBookingRepository')
+        private readonly bookingRepository: IBookingRepository,
+        @Inject('IVenueRepository')
+        private readonly venueRepository: IVenueRepository,
+    ) { }
+
+    async execute(venueId: string, ownerId: string): Promise {
+
+        const venue = await this.venueRepository.findById(venueId)
+
+        if (!venue) throw new NotFoundException('Venue not found')
+        if (venue.ownerId !== ownerId) throw new BusinessRuleException('invalid ownership')
+
+        const bookings = await this.bookingRepository.findByVenueId(venueId);
+
+        return bookings.map((b) => ({
+            id: b.id,
+            userId: b.userId,
+            venueId: b.venueId,
+            startDate: b.dateRange.startDate,
+            endDate: b.dateRange.endDate,
+            guestsCount: b.guestsCount,
+            totalAmount: b.totalAmount,
+            status: b.status,
+            paymentStatus: b.paymentStatus,
+            createdAt: b.createdAt,
+        }));
+    }
+}
diff --git a/backend/src/core/application/dashboard/dashboard.repository.interface.ts b/backend/src/core/application/dashboard/dashboard.repository.interface.ts
new file mode 100644
index 000000000..497f606c2
--- /dev/null
+++ b/backend/src/core/application/dashboard/dashboard.repository.interface.ts
@@ -0,0 +1,35 @@
+import type { VenueStatus } from "src/core/domain/venues/entities/venue.entity";
+
+export interface AdminDashboardDto {
+    totalUsers: number;
+    totalOwners: number;
+    totalVenues: number;
+    venueStatusSummary: { status: VenueStatus, count: number }[]
+    approvalPendingVenues: {
+        id: string
+        title: string
+        addressLine1: string
+        venueType: string
+        capacity: number
+    }[]
+}
+
+export interface OwnerDashboardDto {
+    venueCount: number,
+    bookingCount: number,
+    totalRevenue: number
+    recentBookings: {
+        id: string,
+        venueName: string,
+        startDate: Date,
+        endDate: Date,
+        guestsCount: number,
+        amount: number,
+    }[]
+}
+
+export interface IDashboardRepository {
+
+    getAdminDashboard(): Promise;
+    getOwnerDashboard(ownerId: string): Promise;
+}
\ No newline at end of file
diff --git a/backend/src/core/application/dashboard/query/admin-dashboard.query.ts b/backend/src/core/application/dashboard/query/admin-dashboard.query.ts
new file mode 100644
index 000000000..f6c1b830b
--- /dev/null
+++ b/backend/src/core/application/dashboard/query/admin-dashboard.query.ts
@@ -0,0 +1,14 @@
+import { Inject } from "@nestjs/common";
+import type { IDashboardRepository } from "../dashboard.repository.interface";
+
+export class GetAdminDashboardQuery {
+
+    constructor(
+        @Inject('IDashboardRepository')
+        private readonly dashboardRepository: IDashboardRepository,
+    ) { }
+
+    async execute() {
+        return this.dashboardRepository.getAdminDashboard();
+    }
+}
\ No newline at end of file
diff --git a/backend/src/core/application/dashboard/query/owner-dashboard.query.ts b/backend/src/core/application/dashboard/query/owner-dashboard.query.ts
new file mode 100644
index 000000000..a2cfbfbd6
--- /dev/null
+++ b/backend/src/core/application/dashboard/query/owner-dashboard.query.ts
@@ -0,0 +1,14 @@
+import { Inject } from "@nestjs/common";
+import type { IDashboardRepository } from "../dashboard.repository.interface";
+
+export class GetOwnerDashboardQuery {
+
+    constructor(
+        @Inject('IDashboardRepository')
+        private readonly dashboardRepository: IDashboardRepository,
+    ) { }
+
+    async execute(ownerId: string) {
+        return this.dashboardRepository.getOwnerDashboard(ownerId);
+    }
+}
\ No newline at end of file
diff --git a/backend/src/core/application/payment/commands/initiate-payment.command.ts b/backend/src/core/application/payment/commands/initiate-payment.command.ts
new file mode 100644
index 000000000..24a5bc2f8
--- /dev/null
+++ b/backend/src/core/application/payment/commands/initiate-payment.command.ts
@@ -0,0 +1,85 @@
+import { Inject, Injectable } from '@nestjs/common';
+import { PaymentStatus } from 'src/core/domain/_shared/enum/PaymentStatus.enum';
+import { BusinessRuleException } from 'src/core/domain/_shared/exception/business-rule.exception';
+import { BookingStatus } from 'src/core/domain/bookings/enum/booking-status.enum';
+import type { IBookingRepository } from 'src/core/domain/bookings/repositories/booking-repository.interface';
+import { Payment } from 'src/core/domain/payment/entities/payment.entity';
+import type { IPaymentProvider } from 'src/core/domain/payment/payment-provider.interface';
+import type { IPaymentRepository } from 'src/core/domain/payment/repositories/payment-repository.interface';
+
+
+export interface InitiatePaymentCommand {
+    bookingId: string;
+    customerPhone: string
+}
+@Injectable()
+export class InitiatePaymentCommandHandler {
+
+    constructor(
+        @Inject('IPaymentRepository')
+        private readonly paymentRepository: IPaymentRepository,
+        @Inject('IBookingRepository')
+        private readonly bookingRepository: IBookingRepository,
+        @Inject('IPaymentProvider')
+        private readonly paymentProvider: IPaymentProvider,
+    ) { }
+
+    async execute(command: InitiatePaymentCommand, userId: string) {
+
+        const booking = await this.bookingRepository.findById(command.bookingId);
+
+        if (!booking) {
+            throw new BusinessRuleException('Booking not found');
+        }
+
+        const existingPayment = await this.paymentRepository.findByBookingId(
+            booking.id,
+        );
+
+        if (existingPayment) {
+            throw new BusinessRuleException('Payment already exists');
+        }
+
+        const payment = Payment.create(
+            crypto.randomUUID(),
+            {
+                bookingId: booking.id,
+                provider: 'RAZORPAY',
+                providerOrderId: null,
+                providerPaymentId: null,
+                amount: booking.totalAmount,
+                currency: 'INR',
+                status: PaymentStatus.INITIATED,
+                paidAt: null,
+                failureReason: null,
+            },
+        );
+
+        const response = await this.paymentProvider.createPayment({
+            paymentId: payment.id,
+            amount: payment.amount,
+            currency: payment.currency,
+            customerName: booking.user!.firstName + ' ' + booking.user!.lastName,
+            customerEmail: booking.user!.email,
+            customerPhone: booking.user!.phone || command.customerPhone,
+            description: `Booking #${booking.id}`,
+        });
+
+        payment.setProviderOrderId(
+            response.providerOrderId,
+        );
+
+        await this.paymentRepository.create(payment);
+        await this.bookingRepository.update(booking.id, {
+            paymentStatus: PaymentStatus.INITIATED
+        })
+
+        return {
+            paymentId: payment.id,
+            providerOrderId: response.providerOrderId,
+            checkoutData: response.providerData,
+        };
+
+    }
+
+}
\ No newline at end of file
diff --git a/backend/src/core/application/payment/commands/verify-payment.command.ts b/backend/src/core/application/payment/commands/verify-payment.command.ts
new file mode 100644
index 000000000..8b88be8bc
--- /dev/null
+++ b/backend/src/core/application/payment/commands/verify-payment.command.ts
@@ -0,0 +1,93 @@
+import { Inject, Injectable, InternalServerErrorException } from '@nestjs/common';
+import { PaymentStatus } from 'src/core/domain/_shared/enum/PaymentStatus.enum';
+import { BusinessRuleException } from 'src/core/domain/_shared/exception/business-rule.exception';
+import type { IBookingRepository } from 'src/core/domain/bookings/repositories/booking-repository.interface';
+import type { INotificationService } from 'src/core/domain/notification/notification.service.interface';
+import type { IPaymentProvider } from 'src/core/domain/payment/payment-provider.interface';
+import type { IPaymentRepository } from 'src/core/domain/payment/repositories/payment-repository.interface';
+
+
+export interface VerifyPaymentCommand {
+    providerOrderId: string;
+    providerPaymentId: string;
+    signature: string;
+}
+
+@Injectable()
+export class VerifyPaymentCommandHandler {
+
+    constructor(
+
+        @Inject('IPaymentRepository')
+        private readonly paymentRepository: IPaymentRepository,
+        @Inject('IBookingRepository')
+        private readonly bookingRepository: IBookingRepository,
+        @Inject('IPaymentProvider')
+        private readonly paymentProvider: IPaymentProvider,
+        @Inject('INotificationService')
+        private readonly notificationService: INotificationService
+    ) { }
+
+    async execute(command: VerifyPaymentCommand, userId) {
+
+        const payment = await this.paymentRepository.findByProviderOrderId(
+            command.providerOrderId,
+        );
+
+        if (!payment) {
+            throw new BusinessRuleException('Payment not found');
+        }
+
+        const verification = await this.paymentProvider.verifyPayment({
+            providerOrderId: command.providerOrderId,
+            providerPaymentId: command.providerPaymentId,
+            signature: command.signature,
+        });
+
+        if (!verification.success) {
+
+            payment.markFailed('Payment verification failed');
+
+            await this.paymentRepository.update(payment.id, {
+                providerPaymentId: command.providerPaymentId,
+                status: PaymentStatus.FAILED,
+                failureReason: 'payment failed'
+            });
+
+            throw new InternalServerErrorException('Payment verification failed');
+
+        }
+
+        payment.markPaid(
+            command.providerPaymentId,
+            verification.paidAt ?? new Date(),
+        );
+
+        await this.paymentRepository.update(payment.id, {
+            paidAt: new Date(),// todo need to update this date with real date from provider 
+            providerPaymentId: command.providerPaymentId,
+            status: PaymentStatus.PAID
+        });
+
+        await this.bookingRepository.update(payment.bookingId, {
+            paymentStatus: PaymentStatus.PAID
+        })
+
+        await this.notificationService.trigger({
+            subscriberId: userId,
+            payload: {
+                title: "Payment success",
+                message: `Your recent payment is success`
+            }
+        })
+
+        return {
+            paymentId: payment.id,
+            bookingId: payment.bookingId,
+            status: payment.status,
+            paidAt: payment.paidAt,
+        };
+
+    }
+
+}
\ No newline at end of file
diff --git a/backend/src/core/application/payment/queries/get-all-payments.query.ts b/backend/src/core/application/payment/queries/get-all-payments.query.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/backend/src/core/application/payment/queries/get-payment.query.ts b/backend/src/core/application/payment/queries/get-payment.query.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/backend/src/core/application/users/commands/login-user.command.ts b/backend/src/core/application/users/commands/login-user.command.ts
new file mode 100644
index 000000000..0437d4495
--- /dev/null
+++ b/backend/src/core/application/users/commands/login-user.command.ts
@@ -0,0 +1,95 @@
+import { Injectable, Inject } from '@nestjs/common';
+import * as jwt from 'jsonwebtoken';
+import { type IUserRepository } from '../../../domain/users/repositories/user-repository.interface';
+import { type IPasswordHasher } from '../services/password-hasher.interface';
+import { type ITokenService } from '../services/token.interface';
+import { type IRefreshTokenRepository } from '../services/refresh-token-repository.interface';
+import { BusinessRuleException } from '../../../domain/_shared/exception/business-rule.exception';
+import { NotFoundException } from '../../../domain/_shared/exception/notfound.exception';
+import type { UserRole } from 'src/core/domain/_shared/enum/UserRole';
+
+export interface LoginUserDto {
+  email: string;
+  password?: string;
+}
+
+export interface LoginResultDto {
+  accessToken: string;
+  refreshToken: string;
+  user: {
+    id: string;
+    email: string;
+    firstName: string;
+    lastName: string | null;
+    role: string;
+  };
+}
+
+@Injectable()
+export class LoginUserCommand {
+  constructor(
+    @Inject('IUserRepository')
+    private readonly userRepository: IUserRepository,
+    @Inject('IPasswordHasher')
+    private readonly passwordHasher: IPasswordHasher,
+    @Inject('ITokenService')
+    private readonly tokenService: ITokenService,
+    @Inject('IRefreshTokenRepository')
+    private readonly refreshTokenRepository: IRefreshTokenRepository,
+  ) { }
+
+  async execute(dto: LoginUserDto): Promise {
+    const user = await this.userRepository.findByEmail(dto.email);
+    if (!user) {
+      throw new NotFoundException('User not found');
+    }
+
+    if (user.status === 'BLOCKED') {
+      throw new BusinessRuleException('Your account has been blocked');
+    }
+    if (user.status === 'DELETED') {
+      throw new BusinessRuleException('Your account has been deleted');
+    }
+
+    // Standard credential login
+    if (dto.password) {
+      if (!user.password) {
+        throw new BusinessRuleException('Invalid credentials (please use Google login)');
+      }
+      const isMatch = await this.passwordHasher.compare(dto.password, user.password);
+      if (!isMatch) {
+        throw new BusinessRuleException('Invalid credentials');
+      }
+    } else {
+      // Social login check would be handled by another mechanism or pass through
+      throw new BusinessRuleException('Password is required');
+    }
+
+    const payload = {
+      userId: user.id,
+      email: user.email,
+      role: user.role as UserRole
+    };
+
+    const accessToken = this.tokenService.generateAccessToken(payload);
+    const refreshToken = this.tokenService.generateRefreshToken(payload);
+
+    const decoded = jwt.decode(refreshToken) as jwt.JwtPayload;
+    const expiresAt = decoded.exp
+      ? new Date(decoded.exp * 1000)
+      : new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
+    await this.refreshTokenRepository.save(user.id, refreshToken, expiresAt);
+
+    return {
+      accessToken,
+      refreshToken,
+      user: {
+        id: user.id,
+        email: user.email,
+        firstName: user.firstName,
+        lastName: user.lastName || null,
+        role: user.role,
+      },
+    };
+  }
+}
diff --git a/backend/src/core/application/users/commands/logout.command.ts b/backend/src/core/application/users/commands/logout.command.ts
new file mode 100644
index 000000000..9e67d6509
--- /dev/null
+++ b/backend/src/core/application/users/commands/logout.command.ts
@@ -0,0 +1,18 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IRefreshTokenRepository } from '../services/refresh-token-repository.interface';
+
+export interface LogoutDto {
+  userId: string;
+}
+
+@Injectable()
+export class LogoutCommand {
+  constructor(
+    @Inject('IRefreshTokenRepository')
+    private readonly refreshTokenRepository: IRefreshTokenRepository,
+  ) {}
+
+  async execute(dto: LogoutDto): Promise {
+    await this.refreshTokenRepository.deleteByUserId(dto.userId);
+  }
+}
diff --git a/backend/src/core/application/users/commands/refresh-access-token.command.ts b/backend/src/core/application/users/commands/refresh-access-token.command.ts
new file mode 100644
index 000000000..29e9b8e40
--- /dev/null
+++ b/backend/src/core/application/users/commands/refresh-access-token.command.ts
@@ -0,0 +1,55 @@
+import { Injectable, Inject } from '@nestjs/common';
+import * as jwt from 'jsonwebtoken';
+import { type ITokenService } from '../services/token.interface';
+import { type IRefreshTokenRepository } from '../services/refresh-token-repository.interface';
+import { BusinessRuleException } from '../../../domain/_shared/exception/business-rule.exception';
+
+export interface RefreshAccessTokenDto {
+  refreshToken: string;
+}
+
+export interface RefreshAccessTokenResultDto {
+  accessToken: string;
+  refreshToken: string;
+}
+
+@Injectable()
+export class RefreshAccessTokenCommand {
+  constructor(
+    @Inject('ITokenService')
+    private readonly tokenService: ITokenService,
+    @Inject('IRefreshTokenRepository')
+    private readonly refreshTokenRepository: IRefreshTokenRepository,
+  ) {}
+
+  async execute(dto: RefreshAccessTokenDto): Promise {
+    const payload = this.tokenService.verifyRefreshToken(dto.refreshToken);
+    if (!payload) {
+      throw new BusinessRuleException('Invalid or expired refresh token');
+    }
+
+    const isValid = await this.refreshTokenRepository.verify(payload.userId, dto.refreshToken);
+    if (!isValid) {
+      throw new BusinessRuleException('Invalid or expired refresh token');
+    }
+
+    const newPayload = {
+      userId: payload.userId,
+      email: payload.email,
+      role: payload.role,
+    };
+
+    const accessToken = this.tokenService.generateAccessToken(newPayload);
+    const refreshToken = this.tokenService.generateRefreshToken(newPayload);
+
+    await this.refreshTokenRepository.deleteByUserId(payload.userId);
+
+    const decoded = jwt.decode(refreshToken) as jwt.JwtPayload;
+    const expiresAt = decoded.exp
+      ? new Date(decoded.exp * 1000)
+      : new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
+    await this.refreshTokenRepository.save(payload.userId, refreshToken, expiresAt);
+
+    return { accessToken, refreshToken };
+  }
+}
diff --git a/backend/src/core/application/users/commands/register-user.command.ts b/backend/src/core/application/users/commands/register-user.command.ts
new file mode 100644
index 000000000..6030ff457
--- /dev/null
+++ b/backend/src/core/application/users/commands/register-user.command.ts
@@ -0,0 +1,52 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { User } from '../../../domain/users/entities/user.entity';
+import { type IUserRepository } from '../../../domain/users/repositories/user-repository.interface';
+import { type IPasswordHasher } from '../services/password-hasher.interface';
+import { BusinessRuleException } from '../../../domain/_shared/exception/business-rule.exception';
+import * as crypto from 'crypto';
+import type { UserRole } from 'src/core/domain/_shared/enum/UserRole';
+
+export interface RegisterUserDto {
+  email: string;
+  password?: string;
+  firstName: string;
+  lastName?: string;
+  phone?: string;
+}
+
+@Injectable()
+export class RegisterUserCommand {
+  constructor(
+    @Inject('IUserRepository')
+    private readonly userRepository: IUserRepository,
+    @Inject('IPasswordHasher')
+    private readonly passwordHasher: IPasswordHasher,
+  ) { }
+
+  async execute(dto: RegisterUserDto): Promise<{ userId: string }> {
+    const existing = await this.userRepository.findByEmail(dto.email);
+    if (existing) {
+      throw new BusinessRuleException('Email is already registered');
+    }
+
+    let hashedPassword: string | undefined = undefined;
+    if (dto.password) {
+      hashedPassword = await this.passwordHasher.hash(dto.password);
+    }
+
+    const userId = crypto.randomUUID();
+    const user = User.create(userId, {
+      email: dto.email,
+      password: hashedPassword,
+      firstName: dto.firstName,
+      lastName: dto.lastName || null,
+      phone: dto.phone || null,
+      role: 'USER',
+      status: 'ACTIVE',
+    });
+
+    await this.userRepository.save(user);
+
+    return { userId };
+  }
+}
diff --git a/backend/src/core/application/users/queries/get-user-profile.query.ts b/backend/src/core/application/users/queries/get-user-profile.query.ts
new file mode 100644
index 000000000..e4b82a9f2
--- /dev/null
+++ b/backend/src/core/application/users/queries/get-user-profile.query.ts
@@ -0,0 +1,40 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IUserRepository } from '../../../domain/users/repositories/user-repository.interface';
+import { NotFoundException } from '../../../domain/_shared/exception/notfound.exception';
+
+export interface UserProfileDto {
+  id: string;
+  email: string;
+  firstName: string;
+  lastName: string | null;
+  phone: string | null;
+  role: string;
+  status: string;
+  createdAt: Date;
+}
+
+@Injectable()
+export class GetUserProfileQuery {
+  constructor(
+    @Inject('IUserRepository')
+    private readonly userRepository: IUserRepository,
+  ) { }
+
+  async execute(userId: string): Promise {
+    const user = await this.userRepository.findById(userId);
+    if (!user) {
+      throw new NotFoundException('User not found');
+    }
+
+    return {
+      id: user.id,
+      email: user.email,
+      firstName: user.firstName,
+      lastName: user.lastName || null,
+      phone: user.phone || null,
+      role: user.role,
+      status: user.status,
+      createdAt: user.createdAt,
+    };
+  }
+}
diff --git a/backend/src/core/application/users/queries/list-users.query.ts b/backend/src/core/application/users/queries/list-users.query.ts
new file mode 100644
index 000000000..f60bf0618
--- /dev/null
+++ b/backend/src/core/application/users/queries/list-users.query.ts
@@ -0,0 +1,45 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IUserRepository } from '../../../domain/users/repositories/user-repository.interface';
+import { Pagination } from '../../_shared/dto/pagination';
+
+export interface UserListDto {
+    id: string;
+    email: string;
+    firstName: string;
+    lastName: string | null | undefined;
+    phone: string | null | undefined;
+    role: string;
+    status: string;
+    createdAt: Date;
+}
+
+@Injectable()
+export class ListUsersQuery {
+    constructor(
+        @Inject('IUserRepository')
+        private readonly userRepository: IUserRepository,
+    ) { }
+
+    async execute(): Promise> {
+        const data = await this.userRepository.findAll();
+
+        const users = data.map(user => ({
+            id: user.id,
+            email: user.email,
+            firstName: user.firstName,
+            lastName: user.lastName,
+            phone: user.phone,
+            role: user.role,
+            status: user.status,
+            createdAt: user.createdAt,
+        }))
+
+        return new Pagination({
+            data: users,
+            total: data.length,
+            offset: 0,
+            limit: data.length
+        });
+
+    }
+}
diff --git a/backend/src/core/application/users/services/password-hasher.interface.ts b/backend/src/core/application/users/services/password-hasher.interface.ts
new file mode 100644
index 000000000..a46685ee4
--- /dev/null
+++ b/backend/src/core/application/users/services/password-hasher.interface.ts
@@ -0,0 +1,4 @@
+export interface IPasswordHasher {
+  hash(password: string): Promise;
+  compare(password: string, hashed: string): Promise;
+}
diff --git a/backend/src/core/application/users/services/refresh-token-repository.interface.ts b/backend/src/core/application/users/services/refresh-token-repository.interface.ts
new file mode 100644
index 000000000..d8ce84b9b
--- /dev/null
+++ b/backend/src/core/application/users/services/refresh-token-repository.interface.ts
@@ -0,0 +1,5 @@
+export interface IRefreshTokenRepository {
+  save(userId: string, rawToken: string, expiresAt: Date): Promise;
+  verify(userId: string, rawToken: string): Promise;
+  deleteByUserId(userId: string): Promise;
+}
diff --git a/backend/src/core/application/users/services/token.interface.ts b/backend/src/core/application/users/services/token.interface.ts
new file mode 100644
index 000000000..1f05b2962
--- /dev/null
+++ b/backend/src/core/application/users/services/token.interface.ts
@@ -0,0 +1,14 @@
+import type { UserRole } from "src/core/domain/_shared/enum/UserRole";
+
+export interface TokenPayload {
+  userId: string;
+  email: string;
+  role: UserRole;
+}
+
+export interface ITokenService {
+  generateAccessToken(payload: TokenPayload): string;
+  generateRefreshToken(payload: TokenPayload): string;
+  verifyAccessToken(token: string): TokenPayload | null;
+  verifyRefreshToken(token: string): TokenPayload | null;
+}
diff --git a/backend/src/core/application/venues/commands/create-venue.command.ts b/backend/src/core/application/venues/commands/create-venue.command.ts
new file mode 100644
index 000000000..92f9ebd94
--- /dev/null
+++ b/backend/src/core/application/venues/commands/create-venue.command.ts
@@ -0,0 +1,60 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { Venue } from '../../../domain/venues/entities/venue.entity';
+import { Address } from '../../../domain/venues/value-objects/address.vo';
+import { type IVenueRepository } from '../../../domain/venues/repositories/venue-repository.interface';
+import * as crypto from 'crypto';
+
+export interface CreateVenueDto {
+  ownerId: string;
+  title: string;
+  description: string;
+  venueType: string;
+  addressLine1: string;
+  city: string;
+  state: string;
+  country: string;
+  postalCode: string;
+  latitude?: number | null;
+  longitude?: number | null;
+  capacity: number;
+  pricePerDay: number;
+  amenities: string[]
+}
+
+@Injectable()
+export class CreateVenueCommand {
+  constructor(
+    @Inject('IVenueRepository')
+    private readonly venueRepository: IVenueRepository,
+  ) { }
+
+  async execute(dto: CreateVenueDto): Promise<{ venueId: string }> {
+    const address = Address.create({
+      addressLine1: dto.addressLine1,
+      city: dto.city,
+      state: dto.state,
+      country: dto.country,
+      postalCode: dto.postalCode,
+      latitude: dto.latitude,
+      longitude: dto.longitude,
+    });
+
+    const venueId = crypto.randomUUID();
+    const venue = Venue.create(venueId, {
+      ownerId: dto.ownerId,
+      title: dto.title,
+      description: dto.description,
+      venueType: dto.venueType,
+      address,
+      capacity: dto.capacity,
+      pricePerDay: dto.pricePerDay,
+      status: 'PENDING',
+      amenities: dto.amenities,
+      images: []
+    });
+
+    await this.venueRepository.save(venue);
+
+    return { venueId };
+  }
+}
diff --git a/backend/src/core/application/venues/commands/update-venue.command.ts b/backend/src/core/application/venues/commands/update-venue.command.ts
new file mode 100644
index 000000000..70590093c
--- /dev/null
+++ b/backend/src/core/application/venues/commands/update-venue.command.ts
@@ -0,0 +1,66 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { Address } from '../../../domain/venues/value-objects/address.vo';
+import { type IVenueRepository } from '../../../domain/venues/repositories/venue-repository.interface';
+import { NotFoundException } from '../../../domain/_shared/exception/notfound.exception';
+import { BusinessRuleException } from '../../../domain/_shared/exception/business-rule.exception';
+
+export interface UpdateVenueDto {
+  venueId: string;
+  userId: string;
+  userRole: string;
+  title: string;
+  description: string;
+  venueType: string;
+  addressLine1: string;
+  city: string;
+  state: string;
+  country: string;
+  postalCode: string;
+  latitude?: number | null;
+  longitude?: number | null;
+  capacity: number;
+  pricePerDay: number;
+  amenities: string[],
+}
+
+@Injectable()
+export class UpdateVenueCommand {
+  constructor(
+    @Inject('IVenueRepository')
+    private readonly venueRepository: IVenueRepository,
+  ) { }
+
+  async execute(dto: UpdateVenueDto): Promise {
+    const venue = await this.venueRepository.findById(dto.venueId);
+    if (!venue) {
+      throw new NotFoundException('Venue not found');
+    }
+
+    // Authorization check
+    if (venue.ownerId !== dto.userId && dto.userRole !== 'ADMIN') {
+      throw new BusinessRuleException('You do not have permission to update this venue');
+    }
+
+    const address = Address.create({
+      addressLine1: dto.addressLine1,
+      city: dto.city,
+      state: dto.state,
+      country: dto.country,
+      postalCode: dto.postalCode,
+      latitude: dto.latitude,
+      longitude: dto.longitude,
+    });
+
+    venue.updateDetails(
+      dto.title,
+      dto.description,
+      dto.venueType,
+      address,
+      dto.capacity,
+      dto.pricePerDay,
+      dto.amenities
+    );
+
+    await this.venueRepository.save(venue);
+  }
+}
diff --git a/backend/src/core/application/venues/commands/upload-venue-images.command.ts b/backend/src/core/application/venues/commands/upload-venue-images.command.ts
new file mode 100644
index 000000000..a47a80f3f
--- /dev/null
+++ b/backend/src/core/application/venues/commands/upload-venue-images.command.ts
@@ -0,0 +1,62 @@
+import { Inject } from "@nestjs/common";
+import type { IVenueRepository } from "src/core/domain/venues/repositories/venue-repository.interface";
+import type { IFileStorage } from "../../_shared/storage/file-storage.interface";
+import { NotFoundException } from "src/core/domain/_shared/exception/notfound.exception";
+import type { IVenueImageRepository } from "src/core/domain/venues/repositories/venue-image-repository.interface";
+import { VenueImage } from "src/core/domain/venues/entities/venue-image.entity";
+import { BusinessRuleException } from "src/core/domain/_shared/exception/business-rule.exception";
+
+type UploadVenueImageInputDto = {
+    ownerId: string,
+    venueId: string,
+    files: {
+        fileName: string,
+        buffer: Buffer
+    }[]
+}
+
+
+export class UploadVenueImagesCommand {
+    constructor(
+        @Inject('IVenueRepository')
+        private readonly venueRepository: IVenueRepository,
+        @Inject('IVenueImageRepository')
+        private readonly venueImageRepository: IVenueImageRepository,
+        @Inject('IFileStorage')
+        private readonly fileStorage: IFileStorage,
+    ) { }
+
+    async execute(dto: UploadVenueImageInputDto): Promise<{ message: string }> {
+
+        const venue = await this.venueRepository.findById(dto.venueId);
+
+        if (!venue) {
+            throw new NotFoundException(
+                'Venue not found',
+            );
+        }
+
+        if (venue.ownerId !== dto.ownerId) throw new BusinessRuleException('invalid venue id, cannot process')
+
+        const venueImages: VenueImage[] = []
+
+        for (const file of dto.files) {
+
+            const url = await this.fileStorage.upload(
+                file.fileName,
+                file.buffer,
+            );
+            venueImages.push(VenueImage.create(crypto.randomUUID(), {
+                url,
+                venueId: dto.venueId,
+            }))
+
+        }
+
+        await this.venueImageRepository.create(venueImages);
+
+        return {
+            message: 'Venue images uploaded successfully'
+        }
+    }
+}
\ No newline at end of file
diff --git a/backend/src/core/application/venues/queries/find-my-venues.query.ts b/backend/src/core/application/venues/queries/find-my-venues.query.ts
new file mode 100644
index 000000000..158a4bed8
--- /dev/null
+++ b/backend/src/core/application/venues/queries/find-my-venues.query.ts
@@ -0,0 +1,62 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IVenueRepository } from '../../../domain/venues/repositories/venue-repository.interface';
+import { Pagination } from '../../_shared/dto/pagination';
+
+
+export interface VenueResponseDto {
+    id: string;
+    ownerId: string;
+    title: string;
+    description: string;
+    venueType: string;
+    addressLine1: string;
+    city: string;
+    state: string;
+    country: string;
+    postalCode: string;
+    latitude: number | null;
+    longitude: number | null;
+    capacity: number;
+    pricePerDay: number;
+    status: string;
+    createdAt: Date;
+}
+
+@Injectable()
+export class FindMyVenuesQuery {
+    constructor(
+        @Inject('IVenueRepository')
+        private readonly venueRepository: IVenueRepository,
+    ) { }
+
+    async execute(ownerId: string): Promise> {
+        const venues = await this.venueRepository.findAll({ ownerId });
+
+        const docs = venues.map((v) => ({
+            id: v.id,
+            ownerId: v.ownerId,
+            title: v.title,
+            description: v.description,
+            venueType: v.venueType,
+            addressLine1: v.address.addressLine1,
+            city: v.address.city,
+            state: v.address.state,
+            country: v.address.country,
+            postalCode: v.address.postalCode,
+            latitude: v.address.latitude || null,
+            longitude: v.address.longitude || null,
+            capacity: v.capacity,
+            pricePerDay: v.pricePerDay,
+            status: v.status,
+            createdAt: v.createdAt,
+            images: v.images.map(img => img.url)
+        }));
+
+        return new Pagination({
+            data: docs,
+            limit: docs.length,
+            offset: 0,
+            total: docs.length
+        })
+    }
+}
diff --git a/backend/src/core/application/venues/queries/get-venue-details.query.ts b/backend/src/core/application/venues/queries/get-venue-details.query.ts
new file mode 100644
index 000000000..a11edbf85
--- /dev/null
+++ b/backend/src/core/application/venues/queries/get-venue-details.query.ts
@@ -0,0 +1,40 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IVenueRepository } from '../../../domain/venues/repositories/venue-repository.interface';
+import { NotFoundException } from '../../../domain/_shared/exception/notfound.exception';
+import { VenueResponseDto } from './search-venues.query';
+
+@Injectable()
+export class GetVenueDetailsQuery {
+  constructor(
+    @Inject('IVenueRepository')
+    private readonly venueRepository: IVenueRepository,
+  ) { }
+
+  async execute(venueId: string): Promise {
+    const v = await this.venueRepository.findById(venueId);
+    if (!v) {
+      throw new NotFoundException('Venue not found');
+    }
+
+    return {
+      id: v.id,
+      ownerId: v.ownerId,
+      title: v.title,
+      description: v.description,
+      venueType: v.venueType,
+      addressLine1: v.address.addressLine1,
+      city: v.address.city,
+      state: v.address.state,
+      country: v.address.country,
+      postalCode: v.address.postalCode,
+      latitude: v.address.latitude || null,
+      longitude: v.address.longitude || null,
+      capacity: v.capacity,
+      pricePerDay: v.pricePerDay,
+      amenities: v.amenities,
+      images: v.images.map(img => img.url),
+      status: v.status,
+      createdAt: v.createdAt,
+    };
+  }
+}
diff --git a/backend/src/core/application/venues/queries/search-venues.query.ts b/backend/src/core/application/venues/queries/search-venues.query.ts
new file mode 100644
index 000000000..b59ae5310
--- /dev/null
+++ b/backend/src/core/application/venues/queries/search-venues.query.ts
@@ -0,0 +1,76 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { type IVenueRepository } from '../../../domain/venues/repositories/venue-repository.interface';
+import { Pagination } from '../../_shared/dto/pagination';
+
+export interface SearchVenuesFilter {
+  limit: number,
+  offset: number,
+  search?: string,
+  city?: string;
+  venueType?: string;
+  capacity?: number;
+}
+
+export interface VenueResponseDto {
+  id: string;
+  ownerId: string;
+  title: string;
+  description: string;
+  venueType: string;
+  addressLine1: string;
+  city: string;
+  state: string;
+  country: string;
+  postalCode: string;
+  latitude: number | null;
+  longitude: number | null;
+  capacity: number;
+  pricePerDay: number;
+  status: string;
+  createdAt: Date;
+  amenities: string[]
+  images: string[]
+}
+
+@Injectable()
+export class SearchVenuesQuery {
+  constructor(
+    @Inject('IVenueRepository')
+    private readonly venueRepository: IVenueRepository,
+  ) { }
+
+  async execute(filter: SearchVenuesFilter): Promise> {
+    const { count, venues } = await this.venueRepository.findAndCountAll({
+      ...filter,
+      status: 'APPROVED'
+    });
+
+    const docs = venues.map((v) => ({
+      id: v.id,
+      ownerId: v.ownerId,
+      title: v.title,
+      description: v.description,
+      venueType: v.venueType,
+      addressLine1: v.address.addressLine1,
+      city: v.address.city,
+      state: v.address.state,
+      country: v.address.country,
+      postalCode: v.address.postalCode,
+      latitude: v.address.latitude || null,
+      longitude: v.address.longitude || null,
+      capacity: v.capacity,
+      pricePerDay: v.pricePerDay,
+      amenities: v.amenities,
+      images: v.images.map(img => img.url),
+      status: v.status,
+      createdAt: v.createdAt,
+    }));
+
+    return new Pagination({
+      data: docs,
+      limit: filter.limit,
+      offset: filter.offset,
+      total: count,
+    })
+  }
+}
diff --git a/backend/src/core/domain/_shared/entity/aggregate-root.ts b/backend/src/core/domain/_shared/entity/aggregate-root.ts
new file mode 100644
index 000000000..59e564975
--- /dev/null
+++ b/backend/src/core/domain/_shared/entity/aggregate-root.ts
@@ -0,0 +1,17 @@
+import type { DomainEvent } from '../event/domain-event';
+import { Entity } from './entity';
+
+export abstract class AggregateRoot extends Entity {
+  private readonly domainEvents: DomainEvent[] = [];
+
+  addDomainEvent(event: DomainEvent): void {
+    this.domainEvents.push(event);
+  }
+
+  pullDomainEvents(): DomainEvent[] {
+    const events = [...this.domainEvents];
+    this.domainEvents.length = 0;
+
+    return events;
+  }
+}
diff --git a/backend/src/core/domain/_shared/entity/entity.ts b/backend/src/core/domain/_shared/entity/entity.ts
new file mode 100644
index 000000000..574ef6b8c
--- /dev/null
+++ b/backend/src/core/domain/_shared/entity/entity.ts
@@ -0,0 +1,15 @@
+export abstract class Entity {
+  protected constructor(protected readonly _id: TId) {}
+
+  get id(): TId {
+    return this._id;
+  }
+
+  equals(entity?: Entity): boolean {
+    if (!entity) {
+      return false;
+    }
+
+    return this._id === entity._id;
+  }
+}
diff --git a/backend/src/core/domain/_shared/entity/identifier.ts b/backend/src/core/domain/_shared/entity/identifier.ts
new file mode 100644
index 000000000..6aa26155d
--- /dev/null
+++ b/backend/src/core/domain/_shared/entity/identifier.ts
@@ -0,0 +1,11 @@
+export abstract class Identifier {
+  constructor(protected readonly value: string) {}
+
+  toString(): string {
+    return this.value;
+  }
+
+  equals(other: Identifier): boolean {
+    return this.value === other.value;
+  }
+}
diff --git a/backend/src/core/domain/_shared/enum/PaymentStatus.enum.ts b/backend/src/core/domain/_shared/enum/PaymentStatus.enum.ts
new file mode 100644
index 000000000..015ca2314
--- /dev/null
+++ b/backend/src/core/domain/_shared/enum/PaymentStatus.enum.ts
@@ -0,0 +1,8 @@
+
+export enum PaymentStatus {
+    PENDING = 'PENDING',
+    INITIATED = 'INITIATED',
+    PAID = 'PAID',
+    FAILED = 'FAILED',
+    REFUNDED = 'REFUNDED',
+}
\ No newline at end of file
diff --git a/backend/src/core/domain/_shared/enum/UserRole.ts b/backend/src/core/domain/_shared/enum/UserRole.ts
new file mode 100644
index 000000000..b4ce02551
--- /dev/null
+++ b/backend/src/core/domain/_shared/enum/UserRole.ts
@@ -0,0 +1,6 @@
+
+export enum UserRole {
+    USER = 'USER',
+    ADMIN = 'ADMIN',
+    VENUE_OWNER = 'VENUE_OWNER',
+}
\ No newline at end of file
diff --git a/backend/src/core/domain/_shared/event/domain-event.ts b/backend/src/core/domain/_shared/event/domain-event.ts
new file mode 100644
index 000000000..247953db5
--- /dev/null
+++ b/backend/src/core/domain/_shared/event/domain-event.ts
@@ -0,0 +1,3 @@
+export interface DomainEvent {
+  readonly occurredAt: Date;
+}
diff --git a/backend/src/core/domain/_shared/event/event-dispatcher.ts b/backend/src/core/domain/_shared/event/event-dispatcher.ts
new file mode 100644
index 000000000..ba1a520fd
--- /dev/null
+++ b/backend/src/core/domain/_shared/event/event-dispatcher.ts
@@ -0,0 +1,5 @@
+import type { DomainEvent } from './domain-event';
+
+export interface EventDispatcher {
+  dispatch(events: DomainEvent[]): Promise;
+}
diff --git a/backend/src/core/domain/_shared/exception/business-rule.exception.ts b/backend/src/core/domain/_shared/exception/business-rule.exception.ts
new file mode 100644
index 000000000..d47416f64
--- /dev/null
+++ b/backend/src/core/domain/_shared/exception/business-rule.exception.ts
@@ -0,0 +1,3 @@
+import { DomainException } from './domain.exception';
+
+export class BusinessRuleException extends DomainException {}
diff --git a/backend/src/core/domain/_shared/exception/domain.exception.ts b/backend/src/core/domain/_shared/exception/domain.exception.ts
new file mode 100644
index 000000000..a316ca2b4
--- /dev/null
+++ b/backend/src/core/domain/_shared/exception/domain.exception.ts
@@ -0,0 +1,7 @@
+export class DomainException extends Error {
+  constructor(message: string) {
+    super(message);
+
+    this.name = this.constructor.name;
+  }
+}
diff --git a/backend/src/core/domain/_shared/exception/notfound.exception.ts b/backend/src/core/domain/_shared/exception/notfound.exception.ts
new file mode 100644
index 000000000..a603622f8
--- /dev/null
+++ b/backend/src/core/domain/_shared/exception/notfound.exception.ts
@@ -0,0 +1,3 @@
+import { DomainException } from './domain.exception';
+
+export class NotFoundException extends DomainException {}
diff --git a/backend/src/core/domain/_shared/specification/specification.interface.ts b/backend/src/core/domain/_shared/specification/specification.interface.ts
new file mode 100644
index 000000000..c0bab1841
--- /dev/null
+++ b/backend/src/core/domain/_shared/specification/specification.interface.ts
@@ -0,0 +1,3 @@
+export interface ISpecification {
+  isSatisfiedBy(candidate: T): boolean;
+}
diff --git a/backend/src/core/domain/_shared/vo/value-object.ts b/backend/src/core/domain/_shared/vo/value-object.ts
new file mode 100644
index 000000000..21f2aa673
--- /dev/null
+++ b/backend/src/core/domain/_shared/vo/value-object.ts
@@ -0,0 +1,11 @@
+export abstract class ValueObject {
+  protected constructor(protected readonly props: T) {}
+
+  equals(vo?: ValueObject): boolean {
+    if (!vo) {
+      return false;
+    }
+
+    return JSON.stringify(this.props) === JSON.stringify(vo.props);
+  }
+}
diff --git a/backend/src/core/domain/bookings/entities/booking.entity.ts b/backend/src/core/domain/bookings/entities/booking.entity.ts
new file mode 100644
index 000000000..c1f1fc9c5
--- /dev/null
+++ b/backend/src/core/domain/bookings/entities/booking.entity.ts
@@ -0,0 +1,113 @@
+import { AggregateRoot } from '../../_shared/entity/aggregate-root';
+import type { PaymentStatus } from '../../_shared/enum/PaymentStatus.enum';
+import { DomainException } from '../../_shared/exception/domain.exception';
+import type { BookingStatus } from '../enum/booking-status.enum';
+import { DateRange } from '../value-objects/date-range.vo';
+
+export interface BookingProps {
+  userId: string;
+  venueId: string;
+  dateRange: DateRange;
+  guestsCount: number;
+  totalAmount: number;
+  status: BookingStatus
+  paymentStatus: PaymentStatus
+  createdAt?: Date;
+  updatedAt?: Date;
+  venue?: {
+    id: string,
+    title: string
+    ownerId: string
+    images: string[]
+  },
+  user?: {
+    id: string,
+    firstName: string,
+    lastName: string,
+    email: string,
+    phone?: string | null
+  }
+}
+
+export class Booking extends AggregateRoot {
+  private props: BookingProps;
+
+  private constructor(id: string, props: BookingProps) {
+    super(id);
+    this.props = {
+      ...props,
+      createdAt: props.createdAt || new Date(),
+      updatedAt: props.updatedAt || new Date(),
+    };
+  }
+
+  public static create(id: string, props: BookingProps): Booking {
+    if (!props.userId) {
+      throw new DomainException('User ID is required');
+    }
+    if (!props.venueId) {
+      throw new DomainException('Venue ID is required');
+    }
+    if (props.guestsCount <= 0) {
+      throw new DomainException('Guests count must be greater than zero');
+    }
+    return new Booking(id, props);
+  }
+
+  public static restore(id: string, props: BookingProps): Booking {
+    return new Booking(id, props);
+  }
+
+  get userId(): string {
+    return this.props.userId;
+  }
+
+  get venueId(): string {
+    return this.props.venueId;
+  }
+
+  get dateRange(): DateRange {
+    return this.props.dateRange;
+  }
+
+  get guestsCount(): number {
+    return this.props.guestsCount;
+  }
+
+  get totalAmount(): number {
+    return this.props.totalAmount;
+  }
+
+  get status(): BookingStatus {
+    return this.props.status;
+  }
+
+  get paymentStatus(): PaymentStatus {
+    return this.props.paymentStatus;
+  }
+
+  get createdAt(): Date {
+    return this.props.createdAt!;
+  }
+
+  get updatedAt(): Date {
+    return this.props.updatedAt!;
+  }
+
+  get venue(): BookingProps['venue'] {
+    return this.props.venue
+  }
+
+  get user(): BookingProps['user'] {
+    return this.props.user
+  }
+
+  public calculateTotalAmount(pricePerDay: number): void {
+    if (pricePerDay < 0) {
+      throw new DomainException('Price per day cannot be negative');
+    }
+    const days = this.dateRange.getDurationInDays();
+    this.props.totalAmount = pricePerDay * days;
+    this.props.updatedAt = new Date();
+  }
+}
diff --git a/backend/src/core/domain/bookings/enum/booking-status.enum.ts b/backend/src/core/domain/bookings/enum/booking-status.enum.ts
new file mode 100644
index 000000000..29f0578d7
--- /dev/null
+++ b/backend/src/core/domain/bookings/enum/booking-status.enum.ts
@@ -0,0 +1,5 @@
+
+export enum BookingStatus {
+    BOOKED = 'BOOKED',
+    CANCELLED = 'CANCELLED'
+}
diff --git a/backend/src/core/domain/bookings/repositories/booking-repository.interface.ts b/backend/src/core/domain/bookings/repositories/booking-repository.interface.ts
new file mode 100644
index 000000000..29cb168d4
--- /dev/null
+++ b/backend/src/core/domain/bookings/repositories/booking-repository.interface.ts
@@ -0,0 +1,16 @@
+import type { PaymentStatus } from '../../_shared/enum/PaymentStatus.enum';
+import type { Booking } from '../entities/booking.entity';
+
+export type UpdateBookingDto = {
+  paymentStatus?: PaymentStatus
+}
+export interface IBookingRepository {
+  findById(id: string): Promise;
+  findByVenueId(venueId: string): Promise;
+  findByUserId(userId: string): Promise;
+  findByOwnerId(ownerId: string): Promise;
+  checkAvailability(venueId: string, startDate: Date, endDate: Date): Promise;
+  save(booking: Booking): Promise;
+  delete(id: string): Promise;
+  update(id: string, data: UpdateBookingDto): Promise
+}
diff --git a/backend/src/core/domain/bookings/value-objects/date-range.vo.ts b/backend/src/core/domain/bookings/value-objects/date-range.vo.ts
new file mode 100644
index 000000000..7018a777f
--- /dev/null
+++ b/backend/src/core/domain/bookings/value-objects/date-range.vo.ts
@@ -0,0 +1,42 @@
+import { ValueObject } from '../../_shared/vo/value-object';
+import { DomainException } from '../../_shared/exception/domain.exception';
+
+export interface DateRangeProps {
+  startDate: Date;
+  endDate: Date;
+}
+
+export class DateRange extends ValueObject {
+  private constructor(props: DateRangeProps) {
+    super(props);
+  }
+
+  public static create(startDate: Date, endDate: Date): DateRange {
+    if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
+      throw new DomainException('Invalid start or end date');
+    }
+    if (startDate >= endDate) {
+      throw new DomainException('Start date must be before end date');
+    }
+    // Simple verification - let's allow bookings on the same day if time is correct, but typically we want in the future
+    return new DateRange({ startDate, endDate });
+  }
+
+  get startDate(): Date {
+    return this.props.startDate;
+  }
+
+  get endDate(): Date {
+    return this.props.endDate;
+  }
+
+  public overlaps(other: DateRange): boolean {
+    return this.startDate < other.endDate && this.endDate > other.startDate;
+  }
+
+  public getDurationInDays(): number {
+    const diffTime = Math.abs(this.endDate.getTime() - this.startDate.getTime());
+    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
+    return diffDays || 1; // Minimum 1 day
+  }
+}
diff --git a/backend/src/core/domain/notification/notification.service.interface.ts b/backend/src/core/domain/notification/notification.service.interface.ts
new file mode 100644
index 000000000..1880798c3
--- /dev/null
+++ b/backend/src/core/domain/notification/notification.service.interface.ts
@@ -0,0 +1,38 @@
+export interface CreateSubscriberInput {
+    subscriberId: string;
+    email: string;
+    firstName?: string;
+    lastName?: string;
+    phone?: string;
+    avatar?: string;
+}
+
+export interface TriggerNotificationInput {
+    subscriberId: string;
+    payload: Record;
+}
+
+export interface NotificationResult {
+    success: boolean;
+    message?: string;
+}
+
+export interface INotificationService {
+
+    createSubscriber(
+        input: CreateSubscriberInput
+    ): Promise;
+
+    updateSubscriber(
+        input: CreateSubscriberInput
+    ): Promise;
+
+    deleteSubscriber(
+        subscriberId: string
+    ): Promise;
+
+    trigger(
+        input: TriggerNotificationInput
+    ): Promise;
+
+}
\ No newline at end of file
diff --git a/backend/src/core/domain/payment/entities/payment.entity.ts b/backend/src/core/domain/payment/entities/payment.entity.ts
new file mode 100644
index 000000000..36f7e4468
--- /dev/null
+++ b/backend/src/core/domain/payment/entities/payment.entity.ts
@@ -0,0 +1,183 @@
+import { AggregateRoot } from '../../_shared/entity/aggregate-root';
+import { PaymentStatus } from '../../_shared/enum/PaymentStatus.enum';
+import { DomainException } from '../../_shared/exception/domain.exception';
+
+export interface PaymentProps {
+    bookingId: string;
+
+    provider: string;
+
+    providerOrderId: string | null;
+
+    providerPaymentId: string | null;
+
+    amount: number;
+
+    currency: string;
+
+    status: PaymentStatus;
+
+    paidAt: Date | null;
+
+    failureReason: string | null;
+
+    createdAt?: Date;
+
+    updatedAt?: Date;
+}
+
+export class Payment extends AggregateRoot {
+
+    private constructor(
+        id: string,
+        private readonly props: PaymentProps,
+    ) {
+        super(id);
+
+        this.props = {
+            ...props,
+            providerOrderId: props.providerOrderId ?? null,
+            providerPaymentId: props.providerPaymentId ?? null,
+            paidAt: props.paidAt ?? null,
+            failureReason: props.failureReason ?? null,
+            createdAt: props.createdAt ?? new Date(),
+            updatedAt: props.updatedAt ?? new Date(),
+        };
+    }
+
+    public static create(
+        id: string,
+        props: PaymentProps,
+    ): Payment {
+
+        if (!props.bookingId) {
+            throw new DomainException('Booking id is required');
+        }
+
+        if (!props.provider) {
+            throw new DomainException('Payment provider is required');
+        }
+
+        if (props.amount <= 0) {
+            throw new DomainException('Amount should be greater than 0');
+        }
+
+        if (!props.currency) {
+            throw new DomainException('Currency is required');
+        }
+
+        return new Payment(id, props);
+    }
+
+    public static restore(
+        id: string,
+        props: PaymentProps,
+    ): Payment {
+        return new Payment(id, props);
+    }
+
+    private touch(): void {
+        this.props.updatedAt = new Date();
+    }
+
+    public setProviderOrderId(orderId: string): void {
+
+        if (this.props.providerOrderId) {
+            throw new DomainException('Provider order id already assigned');
+        }
+
+        this.props.providerOrderId = orderId;
+
+        this.touch();
+    }
+
+    public markPaid(
+        providerPaymentId: string,
+        paidAt: Date = new Date(),
+    ): void {
+
+        if (this.props.status === PaymentStatus.PAID) {
+            throw new DomainException('Payment already completed');
+        }
+
+        this.props.providerPaymentId = providerPaymentId;
+
+        this.props.status = PaymentStatus.PAID;
+
+        this.props.paidAt = paidAt;
+
+        this.props.failureReason = null;
+
+        this.touch();
+    }
+
+    public markFailed(reason: string): void {
+
+        if (this.props.status === PaymentStatus.PAID) {
+            throw new DomainException('Paid payment cannot be marked as failed');
+        }
+
+        this.props.status = PaymentStatus.FAILED;
+
+        this.props.failureReason = reason;
+
+        this.touch();
+    }
+
+    public markInitiated(): void {
+
+        if (this.props.status !== PaymentStatus.PENDING) {
+            return;
+        }
+
+        this.props.status = PaymentStatus.INITIATED;
+
+        this.touch();
+    }
+
+    // Getters
+
+    get bookingId(): string {
+        return this.props.bookingId;
+    }
+
+    get provider(): string {
+        return this.props.provider;
+    }
+
+    get providerOrderId(): string | null {
+        return this.props.providerOrderId;
+    }
+
+    get providerPaymentId(): string | null {
+        return this.props.providerPaymentId;
+    }
+
+    get amount(): number {
+        return this.props.amount;
+    }
+
+    get currency(): string {
+        return this.props.currency;
+    }
+
+    get status(): PaymentStatus {
+        return this.props.status;
+    }
+
+    get paidAt(): Date | null {
+        return this.props.paidAt;
+    }
+
+    get failureReason(): string | null {
+        return this.props.failureReason;
+    }
+
+    get createdAt(): Date {
+        return this.props.createdAt!;
+    }
+
+    get updatedAt(): Date {
+        return this.props.updatedAt!;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/core/domain/payment/payment-provider.interface.ts b/backend/src/core/domain/payment/payment-provider.interface.ts
new file mode 100644
index 000000000..05f54c969
--- /dev/null
+++ b/backend/src/core/domain/payment/payment-provider.interface.ts
@@ -0,0 +1,71 @@
+export interface CreatePaymentRequest {
+    paymentId: string;
+    amount: number;
+    currency: string;
+
+    customerName: string;
+    customerEmail: string;
+    customerPhone: string;
+
+    description: string;
+
+    metadata?: Record;
+}
+
+export interface CreatePaymentResponse {
+    providerOrderId: string;
+    checkoutUrl?: string;
+    providerData?: unknown;
+}
+
+export interface VerifyPaymentRequest {
+    providerOrderId: string;
+    providerPaymentId: string;
+    signature?: string;
+}
+
+export interface VerifyPaymentResponse {
+    success: boolean;
+    providerPaymentId: string;
+    paidAt?: Date;
+    raw?: unknown;
+}
+
+export interface RefundPaymentRequest {
+    providerPaymentId: string;
+    amount: number;
+    reason?: string;
+}
+
+export interface RefundPaymentResponse {
+    refundId: string;
+    success: boolean;
+    refundedAt?: Date;
+    raw?: unknown;
+}
+
+export interface IPaymentProvider {
+
+    /**
+     * Creates a payment order with the gateway.
+     */
+    createPayment(
+        request: CreatePaymentRequest,
+    ): Promise;
+
+    /**
+     * Verifies payment authenticity.
+     */
+    verifyPayment(
+        request: VerifyPaymentRequest,
+    ): Promise;
+
+    /**
+     * Refunds a completed payment.
+     */
+    refundPayment(
+        request: RefundPaymentRequest,
+    ): Promise;
+}
+
+export const PaymentProvider = Symbol('PaymentProvider');
\ No newline at end of file
diff --git a/backend/src/core/domain/payment/repositories/payment-repository.interface.ts b/backend/src/core/domain/payment/repositories/payment-repository.interface.ts
new file mode 100644
index 000000000..3ff9a6d57
--- /dev/null
+++ b/backend/src/core/domain/payment/repositories/payment-repository.interface.ts
@@ -0,0 +1,18 @@
+import type { PaymentStatus } from "../../_shared/enum/PaymentStatus.enum";
+import type { Payment } from "../entities/payment.entity";
+
+export type UpdatePaymentDto = {
+    status?: PaymentStatus,
+    providerPaymentId?: string
+    paidAt?: Date
+    failureReason?: string
+}
+
+export interface IPaymentRepository {
+    findById(id: string): Promise;
+    findAllByBookingId(bookingId: string): Promise
+    findByBookingId(bookingId: string): Promise;
+    findByProviderOrderId(orderId: string): Promise
+    create(Payment: Payment): Promise;
+    update(id: string, data: UpdatePaymentDto): Promise
+}
diff --git a/backend/src/core/domain/users/entities/user.entity.ts b/backend/src/core/domain/users/entities/user.entity.ts
new file mode 100644
index 000000000..19f3b7b19
--- /dev/null
+++ b/backend/src/core/domain/users/entities/user.entity.ts
@@ -0,0 +1,117 @@
+import { AggregateRoot } from '../../_shared/entity/aggregate-root';
+import { DomainException } from '../../_shared/exception/domain.exception';
+import { UserRole as UserRoleEnum } from '../../_shared/enum/UserRole'
+
+export type UserRole = `${UserRoleEnum}`;
+export type UserStatus = 'ACTIVE' | 'BLOCKED' | 'DELETED';
+
+export interface UserProps {
+  email: string;
+  password?: string | null;
+  firstName: string;
+  lastName?: string | null;
+  phone?: string | null;
+  googleId?: string | null;
+  role: UserRole;
+  status: UserStatus;
+  createdAt?: Date;
+  updatedAt?: Date;
+}
+
+export class User extends AggregateRoot {
+  private props: UserProps;
+
+  private constructor(id: string, props: UserProps) {
+    super(id);
+    this.props = {
+      ...props,
+      createdAt: props.createdAt || new Date(),
+      updatedAt: props.updatedAt || new Date(),
+    };
+  }
+
+  public static create(id: string, props: UserProps): User {
+    if (!props.email || !props.email.includes('@')) {
+      throw new DomainException('Invalid email address');
+    }
+    if (!props.firstName || props.firstName.trim().length === 0) {
+      throw new DomainException('First name is required');
+    }
+    return new User(id, props);
+  }
+
+  public static restore(id: string, props: UserProps): User {
+    return new User(id, props);
+  }
+
+  get email(): string {
+    return this.props.email;
+  }
+
+  get password(): string | null | undefined {
+    return this.props.password;
+  }
+
+  get firstName(): string {
+    return this.props.firstName;
+  }
+
+  get lastName(): string | null | undefined {
+    return this.props.lastName;
+  }
+
+  get phone(): string | null | undefined {
+    return this.props.phone;
+  }
+
+  get googleId(): string | null | undefined {
+    return this.props.googleId;
+  }
+
+  get role(): UserRole {
+    return this.props.role;
+  }
+
+  get status(): UserStatus {
+    return this.props.status;
+  }
+
+  get createdAt(): Date {
+    return this.props.createdAt!;
+  }
+
+  get updatedAt(): Date {
+    return this.props.updatedAt!;
+  }
+
+  public block(): void {
+    if (this.props.status === 'DELETED') {
+      throw new DomainException('Cannot block a deleted user');
+    }
+    this.props.status = 'BLOCKED';
+    this.props.updatedAt = new Date();
+  }
+
+  public activate(): void {
+    if (this.props.status === 'DELETED') {
+      throw new DomainException('Cannot activate a deleted user');
+    }
+    this.props.status = 'ACTIVE';
+    this.props.updatedAt = new Date();
+  }
+
+  public delete(): void {
+    this.props.status = 'DELETED';
+    this.props.updatedAt = new Date();
+  }
+
+  public updateProfile(firstName: string, lastName?: string | null, phone?: string | null): void {
+    if (!firstName || firstName.trim().length === 0) {
+      throw new DomainException('First name cannot be empty');
+    }
+    this.props.firstName = firstName;
+    this.props.lastName = lastName;
+    this.props.phone = phone;
+    this.props.updatedAt = new Date();
+  }
+}
diff --git a/backend/src/core/domain/users/repositories/user-repository.interface.ts b/backend/src/core/domain/users/repositories/user-repository.interface.ts
new file mode 100644
index 000000000..6a87e82f1
--- /dev/null
+++ b/backend/src/core/domain/users/repositories/user-repository.interface.ts
@@ -0,0 +1,9 @@
+import type { User } from '../entities/user.entity';
+
+export interface IUserRepository {
+  findById(id: string): Promise;
+  findByEmail(email: string): Promise;
+  findByGoogleId(googleId: string): Promise;
+  save(user: User): Promise;
+  findAll(query?: { search?: string, offset: number, limit: number }): Promise;
+}
diff --git a/backend/src/core/domain/venues/entities/venue-image.entity.ts b/backend/src/core/domain/venues/entities/venue-image.entity.ts
new file mode 100644
index 000000000..d66ddf4f8
--- /dev/null
+++ b/backend/src/core/domain/venues/entities/venue-image.entity.ts
@@ -0,0 +1,74 @@
+import { Entity } from '../../_shared/entity/entity';
+import { DomainException } from '../../_shared/exception/domain.exception';
+
+export interface VenueImageProps {
+    venueId: string;
+    url: string;
+    createdAt?: Date;
+}
+
+export class VenueImage extends Entity {
+    private props: VenueImageProps;
+
+    private constructor(
+        id: string,
+        props: VenueImageProps,
+    ) {
+        super(id);
+
+        this.props = {
+            ...props,
+            createdAt: props.createdAt ?? new Date(),
+        };
+    }
+
+    public static create(
+        id: string,
+        props: VenueImageProps,
+    ): VenueImage {
+        if (!props.venueId?.trim()) {
+            throw new DomainException(
+                'Venue ID is required',
+            );
+        }
+
+        if (!props.url?.trim()) {
+            throw new DomainException(
+                'Image URL is required',
+            );
+        }
+
+        return new VenueImage(id, props);
+    }
+
+    public static restore(
+        id: string,
+        props: VenueImageProps,
+    ): VenueImage {
+        return new VenueImage(id, props);
+    }
+
+    get venueId(): string {
+        return this.props.venueId;
+    }
+
+    get url(): string {
+        return this.props.url;
+    }
+
+    get createdAt(): Date {
+        return this.props.createdAt!;
+    }
+
+    public updateUrl(
+        url: string,
+    ): void {
+        if (!url?.trim()) {
+            throw new DomainException(
+                'Image URL is required',
+            );
+        }
+
+        this.props.url = url;
+    }
+}
\ No newline at end of file
diff --git a/backend/src/core/domain/venues/entities/venue.entity.ts b/backend/src/core/domain/venues/entities/venue.entity.ts
new file mode 100644
index 000000000..0bc1c27a7
--- /dev/null
+++ b/backend/src/core/domain/venues/entities/venue.entity.ts
@@ -0,0 +1,167 @@
+import { AggregateRoot } from '../../_shared/entity/aggregate-root';
+import { DomainException } from '../../_shared/exception/domain.exception';
+import { Address } from '../value-objects/address.vo';
+
+export type VenueStatus = 'PENDING' | 'APPROVED' | 'REJECTED' | 'SUSPENDED';
+
+export interface VenueProps {
+  ownerId: string;
+  title: string;
+  description: string;
+  venueType: string;
+  address: Address;
+  capacity: number;
+  pricePerDay: number;
+  status: VenueStatus;
+  createdAt?: Date;
+  updatedAt?: Date;
+  amenities: string[]
+  images: {
+    id: string,
+    url: string,
+    createdAt: Date
+  }[]
+}
+
+export class Venue extends AggregateRoot {
+  private props: VenueProps;
+
+  private constructor(id: string, props: VenueProps) {
+    super(id);
+    this.props = {
+      ...props,
+      createdAt: props.createdAt || new Date(),
+      updatedAt: props.updatedAt || new Date(),
+    };
+  }
+
+  public static create(id: string, props: VenueProps): Venue {
+    if (!props.ownerId) {
+      throw new DomainException('Owner ID is required');
+    }
+    if (!props.title || props.title.trim().length === 0) {
+      throw new DomainException('Title is required');
+    }
+    if (!props.description || props.description.trim().length === 0) {
+      throw new DomainException('Description is required');
+    }
+    if (!props.venueType || props.venueType.trim().length === 0) {
+      throw new DomainException('Venue type is required');
+    }
+    if (props.capacity <= 0) {
+      throw new DomainException('Capacity must be greater than zero');
+    }
+    if (props.pricePerDay < 0) {
+      throw new DomainException('Price per day cannot be negative');
+    }
+    return new Venue(id, props);
+  }
+
+  public static restore(id: string, props: VenueProps): Venue {
+    return new Venue(id, props);
+  }
+
+  get ownerId(): string {
+    return this.props.ownerId;
+  }
+
+  get title(): string {
+    return this.props.title;
+  }
+
+  get description(): string {
+    return this.props.description;
+  }
+
+  get venueType(): string {
+    return this.props.venueType;
+  }
+
+  get address(): Address {
+    return this.props.address;
+  }
+
+  get capacity(): number {
+    return this.props.capacity;
+  }
+
+  get pricePerDay(): number {
+    return this.props.pricePerDay;
+  }
+
+  get status(): VenueStatus {
+    return this.props.status;
+  }
+
+  get createdAt(): Date {
+    return this.props.createdAt!;
+  }
+
+  get amenities(): string[] {
+    return this.props.amenities;
+  }
+
+  get images(): VenueProps['images'] {
+    return this.props.images;
+  }
+
+  get updatedAt(): Date {
+    return this.props.updatedAt!;
+  }
+
+  public approve(): void {
+    if (this.props.status !== 'PENDING') {
+      throw new DomainException('Only pending venues can be approved');
+    }
+    this.props.status = 'APPROVED';
+    this.props.updatedAt = new Date();
+  }
+
+  public reject(): void {
+    if (this.props.status !== 'PENDING') {
+      throw new DomainException('Only pending venues can be rejected');
+    }
+    this.props.status = 'REJECTED';
+    this.props.updatedAt = new Date();
+  }
+
+  public suspend(): void {
+    if (this.props.status !== 'APPROVED') {
+      throw new DomainException('Only approved venues can be suspended');
+    }
+    this.props.status = 'SUSPENDED';
+    this.props.updatedAt = new Date();
+  }
+
+  public updateDetails(
+    title: string,
+    description: string,
+    venueType: string,
+    address: Address,
+    capacity: number,
+    pricePerDay: number,
+    amenities: string[]
+  ): void {
+    if (!title || title.trim().length === 0) {
+      throw new DomainException('Title cannot be empty');
+    }
+    if (!description || description.trim().length === 0) {
+      throw new DomainException('Description cannot be empty');
+    }
+    if (capacity <= 0) {
+      throw new DomainException('Capacity must be greater than zero');
+    }
+    if (pricePerDay < 0) {
+      throw new DomainException('Price per day cannot be negative');
+    }
+
+    this.props.title = title;
+    this.props.description = description;
+    this.props.venueType = venueType;
+    this.props.address = address;
+    this.props.capacity = capacity;
+    this.props.pricePerDay = pricePerDay;
+    this.props.amenities = amenities
+    this.props.updatedAt = new Date();
+  }
+}
diff --git a/backend/src/core/domain/venues/repositories/venue-image-repository.interface.ts b/backend/src/core/domain/venues/repositories/venue-image-repository.interface.ts
new file mode 100644
index 000000000..b9c85e874
--- /dev/null
+++ b/backend/src/core/domain/venues/repositories/venue-image-repository.interface.ts
@@ -0,0 +1,7 @@
+import type { VenueImage } from "../entities/venue-image.entity";
+
+export interface IVenueImageRepository {
+    create(images: VenueImage[]): Promise;
+    delete(id: string): Promise;
+    findByVenueId(venueId: string,): Promise;
+}
\ No newline at end of file
diff --git a/backend/src/core/domain/venues/repositories/venue-repository.interface.ts b/backend/src/core/domain/venues/repositories/venue-repository.interface.ts
new file mode 100644
index 000000000..6c548ffb5
--- /dev/null
+++ b/backend/src/core/domain/venues/repositories/venue-repository.interface.ts
@@ -0,0 +1,19 @@
+import type { PaginationFilter } from 'src/core/application/_shared/dto/pagination';
+import type { Venue } from '../entities/venue.entity';
+
+export interface VenueFilters {
+  city?: string;
+  venueType?: string;
+  capacity?: number;
+  status?: string;
+  ownerId?: string
+}
+
+export interface VenuePaginationFilters extends VenueFilters, PaginationFilter { }
+
+export interface IVenueRepository {
+  findById(id: string): Promise;
+  findAll(filters?: VenueFilters): Promise;
+  findAndCountAll(filters?: VenuePaginationFilters): Promise<{ count: number, venues: Venue[] }>
+  save(venue: Venue): Promise;
+}
diff --git a/backend/src/core/domain/venues/value-objects/address.vo.ts b/backend/src/core/domain/venues/value-objects/address.vo.ts
new file mode 100644
index 000000000..f1fcbdf60
--- /dev/null
+++ b/backend/src/core/domain/venues/value-objects/address.vo.ts
@@ -0,0 +1,65 @@
+import { ValueObject } from '../../_shared/vo/value-object';
+import { DomainException } from '../../_shared/exception/domain.exception';
+
+export interface AddressProps {
+  addressLine1: string;
+  city: string;
+  state: string;
+  country: string;
+  postalCode: string;
+  latitude?: number | null;
+  longitude?: number | null;
+}
+
+export class Address extends ValueObject {
+  private constructor(props: AddressProps) {
+    super(props);
+  }
+
+  public static create(props: AddressProps): Address {
+    if (!props.addressLine1 || props.addressLine1.trim().length === 0) {
+      throw new DomainException('Address line 1 is required');
+    }
+    if (!props.city || props.city.trim().length === 0) {
+      throw new DomainException('City is required');
+    }
+    if (!props.state || props.state.trim().length === 0) {
+      throw new DomainException('State is required');
+    }
+    if (!props.country || props.country.trim().length === 0) {
+      throw new DomainException('Country is required');
+    }
+    if (!props.postalCode || props.postalCode.trim().length === 0) {
+      throw new DomainException('Postal code is required');
+    }
+    return new Address(props);
+  }
+
+  get addressLine1(): string {
+    return this.props.addressLine1;
+  }
+
+  get city(): string {
+    return this.props.city;
+  }
+
+  get state(): string {
+    return this.props.state;
+  }
+
+  get country(): string {
+    return this.props.country;
+  }
+
+  get postalCode(): string {
+    return this.props.postalCode;
+  }
+
+  get latitude(): number | null | undefined {
+    return this.props.latitude;
+  }
+
+  get longitude(): number | null | undefined {
+    return this.props.longitude;
+  }
+}
diff --git a/backend/src/infra/database/database.module.ts b/backend/src/infra/database/database.module.ts
new file mode 100644
index 000000000..3f51f4188
--- /dev/null
+++ b/backend/src/infra/database/database.module.ts
@@ -0,0 +1,9 @@
+import { Module, Global } from '@nestjs/common';
+import { PrismaService } from './prisma/prisma.service';
+
+@Global()
+@Module({
+  providers: [PrismaService],
+  exports: [PrismaService],
+})
+export class DatabaseModule {}
diff --git a/backend/src/infra/database/prisma/prisma.service.ts b/backend/src/infra/database/prisma/prisma.service.ts
new file mode 100644
index 000000000..6bf3443d7
--- /dev/null
+++ b/backend/src/infra/database/prisma/prisma.service.ts
@@ -0,0 +1,23 @@
+import { Injectable, type OnModuleInit, type OnModuleDestroy } from '@nestjs/common';
+import { PrismaClient } from './generated/prisma/client';
+import { PrismaPg } from '@prisma/adapter-pg';
+import { DB_CONFIG } from 'src/config/app.config';
+
+
+@Injectable()
+export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
+  constructor() {
+    const adapter = new PrismaPg({
+      connectionString: DB_CONFIG.DATABASE_URL,
+    });
+    super({ adapter });
+  }
+
+  async onModuleInit() {
+    await this.$connect();
+  }
+
+  async onModuleDestroy() {
+    await this.$disconnect();
+  }
+}
diff --git a/backend/src/infra/infra.module.ts b/backend/src/infra/infra.module.ts
new file mode 100644
index 000000000..c6c1c553d
--- /dev/null
+++ b/backend/src/infra/infra.module.ts
@@ -0,0 +1,89 @@
+import { ConsoleLogger, Module } from '@nestjs/common';
+import { DatabaseModule } from './database/database.module';
+import { PrismaUserRepository } from './repositories/prisma-user.repository';
+import { PrismaVenueRepository } from './repositories/prisma-venue.repository';
+import { PrismaBookingRepository } from './repositories/prisma-booking.repository';
+import { PrismaRefreshTokenRepository } from './repositories/prisma-refresh-token.repository';
+import { JwtTokenService } from './services/jwt-token.service';
+import { PrismaVenueImageRepository } from './repositories/prisma-venue-image.repository';
+import { LocalFileStorageService } from './storage/local-file.storage';
+import { PrismaDashboardRepository } from './repositories/prisma-dashboard.repository';
+import { PrismaPaymentRepository } from './repositories/prisma-payment.repository';
+import { RazorpayPaymentProvider } from './payment/razorpay-provider';
+import { Argon2PasswordHasher } from './services/argon-password-hasher';
+import { NovuNotificationService } from './notification/novu.notification.service';
+
+@Module({
+  imports: [DatabaseModule],
+  providers: [
+    {
+      provide: 'IUserRepository',
+      useClass: PrismaUserRepository,
+    },
+    {
+      provide: 'IPasswordHasher',
+      useClass: Argon2PasswordHasher,
+    },
+    {
+      provide: 'IFileStorage',
+      useClass: LocalFileStorageService,
+    },
+    {
+      provide: 'ITokenService',
+      useClass: JwtTokenService,
+    },
+    {
+      provide: 'IVenueRepository',
+      useClass: PrismaVenueRepository,
+    },
+    {
+      provide: 'IVenueImageRepository',
+      useClass: PrismaVenueImageRepository,
+    },
+    {
+      provide: 'IBookingRepository',
+      useClass: PrismaBookingRepository,
+    },
+    {
+      provide: 'IRefreshTokenRepository',
+      useClass: PrismaRefreshTokenRepository,
+    },
+    {
+      provide: 'IDashboardRepository',
+      useClass: PrismaDashboardRepository,
+    },
+    {
+      provide: 'IPaymentRepository',
+      useClass: PrismaPaymentRepository,
+      // useClass: PrismaDashboardRepository
+    },
+    {
+      provide: 'IPaymentProvider',
+      useClass: RazorpayPaymentProvider
+    },
+    {
+      provide: 'ILogger',
+      useClass: ConsoleLogger
+    },
+    {
+      provide: 'INotificationService',
+      useClass: NovuNotificationService
+    }
+  ],
+  exports: [
+    'IFileStorage',
+    'IUserRepository',
+    'IPasswordHasher',
+    'ITokenService',
+    'IVenueRepository',
+    'IVenueImageRepository',
+    'IBookingRepository',
+    'IRefreshTokenRepository',
+    'IDashboardRepository',
+    'IPaymentRepository',
+    'IPaymentProvider',
+    'ILogger',
+    'INotificationService'
+  ],
+})
+export class InfraModule { } 
diff --git a/backend/src/infra/logger/console.logger.ts b/backend/src/infra/logger/console.logger.ts
new file mode 100644
index 000000000..9eebc61f0
--- /dev/null
+++ b/backend/src/infra/logger/console.logger.ts
@@ -0,0 +1,33 @@
+import { ConsoleLogger, Injectable } from '@nestjs/common';
+import type { ILogger } from 'src/core/application/_shared/logger/ILogger';
+
+@Injectable()
+export class NestjsConsoleLogger implements ILogger {
+  private readonly logger = new ConsoleLogger();
+
+  // only for nest js internal use
+  log(...args: Parameters): void {
+    this.logger.log(...args);
+  }
+
+  info(message: string, meta?: Record): void {
+    this.logger.log(message, meta);
+  }
+
+  error(message: string, trace?: string, meta?: Record): void {
+    this.logger.error(message, meta);
+    console.log(trace);
+  }
+
+  warn(message: string, meta?: Record): void {
+    this.logger.warn(message, meta);
+  }
+
+  debug(message: string, meta?: Record): void {
+    this.logger.debug(message, meta);
+  }
+
+  verbose(message: string, meta?: Record): void {
+    this.logger.verbose(message, meta);
+  }
+}
diff --git a/backend/src/infra/notification/novu.notification.service.ts b/backend/src/infra/notification/novu.notification.service.ts
new file mode 100644
index 000000000..93c1b1c5e
--- /dev/null
+++ b/backend/src/infra/notification/novu.notification.service.ts
@@ -0,0 +1,82 @@
+import { Novu } from "@novu/api";
+import { NOTIFICATION_CONFIG } from "src/config/app.config";
+import type { CreateSubscriberInput, INotificationService, NotificationResult, TriggerNotificationInput } from "src/core/domain/notification/notification.service.interface";
+
+
+export class NovuNotificationService implements INotificationService {
+
+    private readonly novu: Novu
+
+    constructor() {
+        this.novu = new Novu({
+            secretKey: NOTIFICATION_CONFIG.NOVU_SECRET_KEY,
+        });
+    }
+
+    async createSubscriber(
+        input: CreateSubscriberInput,
+    ): Promise {
+
+        await this.novu.subscribers.create({
+
+            subscriberId: input.subscriberId,
+
+            email: input.email,
+
+            firstName: input.firstName,
+
+            lastName: input.lastName,
+
+            phone: input.phone,
+
+            avatar: input.avatar,
+
+        });
+
+        return {
+            success: true,
+        };
+    }
+
+    async updateSubscriber(
+        input: CreateSubscriberInput,
+    ): Promise {
+
+        throw new Error('not implemented')
+    }
+
+    async deleteSubscriber(
+        subscriberId: string,
+    ): Promise {
+
+        await this.novu.subscribers.delete(
+            subscriberId
+        );
+
+        return {
+            success: true,
+        };
+    }
+
+    async trigger(
+        input: TriggerNotificationInput,
+    ): Promise {
+
+        await this.novu.trigger({
+
+            workflowId: 'generic-in-app-notification',
+            to: {
+                subscriberId: input.subscriberId,
+            },
+            payload: {
+                ...input.payload,
+                actionUrl: 'https://bmv.com'
+            },
+        });
+
+        return {
+            success: true,
+        };
+    }
+
+}
\ No newline at end of file
diff --git a/backend/src/infra/payment/razorpay-provider.ts b/backend/src/infra/payment/razorpay-provider.ts
new file mode 100644
index 000000000..23bc69eb3
--- /dev/null
+++ b/backend/src/infra/payment/razorpay-provider.ts
@@ -0,0 +1,107 @@
+import { Injectable } from '@nestjs/common';
+import Razorpay from 'razorpay';
+import * as crypto from 'node:crypto';
+
+
+import { PAYMENT_CONFIG } from 'src/config/app.config';
+import type { CreatePaymentRequest, CreatePaymentResponse, IPaymentProvider, RefundPaymentRequest, RefundPaymentResponse, VerifyPaymentRequest, VerifyPaymentResponse } from 'src/core/domain/payment/payment-provider.interface';
+
+@Injectable()
+export class RazorpayPaymentProvider implements IPaymentProvider {
+
+    private readonly razorpay: Razorpay;
+
+    constructor() {
+
+        this.razorpay = new Razorpay({
+            key_id: PAYMENT_CONFIG.RAZORPAY_KEY_ID,
+            key_secret: PAYMENT_CONFIG.RAZORPAY_SECRET,
+        });
+
+    }
+
+    async createPayment(request: CreatePaymentRequest,): Promise {
+
+        const order = await this.razorpay.orders.create({
+            amount: Math.round(request.amount * 100),
+            currency: request.currency,
+            receipt: request.paymentId,
+            notes: {
+                customerName: request.customerName,
+                customerEmail: request.customerEmail,
+                customerPhone: request.customerPhone,
+                description: request.description,
+                ...(request.metadata ?? {}),
+            },
+        });
+
+        return {
+            providerOrderId: order.id,
+            providerData: {
+                key: PAYMENT_CONFIG.RAZORPAY_KEY_ID,
+                orderId: order.id,
+                amount: order.amount,
+                currency: order.currency,
+            },
+        };
+
+    }
+
+    async verifyPayment(request: VerifyPaymentRequest,): Promise {
+
+        const secret = PAYMENT_CONFIG.RAZORPAY_SECRET
+
+        const generatedSignature = crypto
+            .createHmac('sha256', secret)
+            .update(
+                `${request.providerOrderId}|${request.providerPaymentId}`,
+            )
+            .digest('hex');
+
+        const verified =
+            generatedSignature === request.signature;
+
+        if (!verified) {
+
+            return {
+                success: false,
+                providerPaymentId: request.providerPaymentId,
+            };
+
+        }
+
+        const payment = await this.razorpay.payments.fetch(
+            request.providerPaymentId,
+        );
+
+        return {
+            success: payment.status === 'captured',
+            providerPaymentId: payment.id,
+            paidAt: new Date(payment.created_at * 1000),
+            raw: payment,
+        };
+
+    }
+
+    async refundPayment(request: RefundPaymentRequest,): Promise {
+
+        const refund = await this.razorpay.payments.refund(
+            request.providerPaymentId,
+            {
+                amount: Math.round(request.amount * 100),
+                notes: {
+                    reason: request.reason ?? '',
+                },
+            },
+        );
+
+        return {
+            refundId: refund.id,
+            success: refund.status === 'processed',
+            refundedAt: new Date(),
+            raw: refund,
+        };
+
+    }
+
+}
\ No newline at end of file
diff --git a/backend/src/infra/repositories/prisma-booking.repository.ts b/backend/src/infra/repositories/prisma-booking.repository.ts
new file mode 100644
index 000000000..e0d5ae5e2
--- /dev/null
+++ b/backend/src/infra/repositories/prisma-booking.repository.ts
@@ -0,0 +1,150 @@
+import { Injectable } from '@nestjs/common';
+import { PrismaService } from '../database/prisma/prisma.service';
+import { Booking } from '../../core/domain/bookings/entities/booking.entity';
+import { DateRange } from '../../core/domain/bookings/value-objects/date-range.vo';
+import type { IBookingRepository, UpdateBookingDto } from '../../core/domain/bookings/repositories/booking-repository.interface';
+
+@Injectable()
+export class PrismaBookingRepository implements IBookingRepository {
+  constructor(private readonly prisma: PrismaService) { }
+
+  private mapToDomain(dbBooking: any): Booking {
+    const dateRange = DateRange.create(dbBooking.booking_start, dbBooking.booking_end);
+
+    return Booking.restore(dbBooking.id, {
+      userId: dbBooking.user_id,
+      venueId: dbBooking.venue_id,
+      dateRange,
+      guestsCount: dbBooking.guests_count,
+      totalAmount: Number(dbBooking.total_amount),
+      status: dbBooking.status,
+      paymentStatus: dbBooking.payment_status,
+      createdAt: dbBooking.created_at,
+      updatedAt: dbBooking.updated_at,
+      venue: {
+        id: dbBooking.venue?.id,
+        title: dbBooking.venue?.title,
+        ownerId: dbBooking.venue?.owner_id,
+        images: (dbBooking.venue?.images || []).map(img => img.image_url),
+      },
+      user: dbBooking.user ? {
+        id: dbBooking.user.id,
+        email: dbBooking.user.email,
+        phone: dbBooking.user.phone,
+        firstName: dbBooking.user.first_name,
+        lastName: dbBooking.user.last_name
+      } : undefined
+    });
+  }
+
+  async findById(id: string): Promise {
+    const dbBooking = await this.prisma.bookings.findUnique({
+      where: { id },
+      include: {
+        venue: {
+          include: { images: true }
+        },
+        user: true,
+      }
+    });
+
+    if (!dbBooking) return null;
+    return this.mapToDomain(dbBooking);
+  }
+
+  async findByVenueId(venueId: string): Promise {
+    const dbBookings = await this.prisma.bookings.findMany({
+      where: { venue_id: venueId },
+      orderBy: { booking_start: 'asc' },
+    });
+    return dbBookings.map((b) => this.mapToDomain(b));
+  }
+
+  async findByUserId(userId: string): Promise {
+    const dbBookings = await this.prisma.bookings.findMany({
+      where: { user_id: userId },
+      orderBy: { booking_start: 'asc' },
+      include: {
+        venue: {
+          include: { images: true }
+        }
+      }
+    });
+
+    return dbBookings.map((b) => (this.mapToDomain(b)))
+  }
+
+  async findByOwnerId(ownerId: string): Promise {
+
+    const venues = await this.prisma.venues.findMany({
+      where: { owner_id: ownerId },
+      select: { id: true }
+    })
+    const bookings = await this.prisma.bookings.findMany({
+      where: {
+        venue_id: { in: venues.map(v => v.id) }
+      },
+      include: {
+        venue: true
+      }
+    })
+
+    return bookings.map(b => this.mapToDomain(b))
+
+  }
+
+  async checkAvailability(venueId: string, startDate: Date, endDate: Date): Promise {
+    const count = await this.prisma.bookings.count({
+      where: {
+        venue_id: venueId,
+        booking_start: {
+          lt: endDate,
+        },
+        booking_end: {
+          gt: startDate,
+        },
+      },
+    });
+    return count === 0;
+  }
+
+  async save(booking: Booking): Promise {
+    const data = {
+      user_id: booking.userId,
+      venue_id: booking.venueId,
+      booking_start: booking.dateRange.startDate,
+      booking_end: booking.dateRange.endDate,
+      guests_count: booking.guestsCount,
+      total_amount: booking.totalAmount as any,
+      updated_at: booking.updatedAt,
+    };
+
+    await this.prisma.bookings.upsert({
+      where: { id: booking.id },
+      update: data,
+      create: {
+        id: booking.id,
+        ...data,
+        created_at: booking.createdAt,
+      },
+    });
+  }
+
+  async delete(id: string): Promise {
+    await this.prisma.bookings.delete({
+      where: { id },
+    });
+  }
+
+  async update(id: string, data: UpdateBookingDto): Promise {
+
+    if (!data.paymentStatus) return
+
+    await this.prisma.bookings.update({
+      where: { id },
+      data: {
+        payment_status: data.paymentStatus
+      }
+    })
+  }
+}
diff --git a/backend/src/infra/repositories/prisma-dashboard.repository.ts b/backend/src/infra/repositories/prisma-dashboard.repository.ts
new file mode 100644
index 000000000..0379e3c9c
--- /dev/null
+++ b/backend/src/infra/repositories/prisma-dashboard.repository.ts
@@ -0,0 +1,89 @@
+import { Injectable } from '@nestjs/common';
+import { PrismaService } from '../database/prisma/prisma.service';
+import type { AdminDashboardDto, IDashboardRepository, OwnerDashboardDto } from 'src/core/application/dashboard/dashboard.repository.interface';
+
+@Injectable()
+export class PrismaDashboardRepository implements IDashboardRepository {
+    constructor(private readonly prisma: PrismaService) { }
+
+    async getAdminDashboard(): Promise {
+
+        const [
+            approvalPendingVenues,
+            totalOwners,
+            totalUsers,
+            statusSummary
+        ] = await Promise.all([
+            this.prisma.venues.findMany({
+                where: { status: 'PENDING' }
+            }),
+            this.prisma.users.count({ where: { role: 'VENUE_OWNER' } }),
+            this.prisma.users.count({ where: { role: 'USER' } }),
+            this.prisma.venues.groupBy({
+                by: 'status',
+                _count: true,
+            })
+        ])
+
+        const totalVenues = statusSummary.reduce((p, c) => p + c._count, 0)
+
+        return {
+            totalOwners,
+            totalUsers,
+            totalVenues,
+            venueStatusSummary: statusSummary.map((sm) => ({
+                count: sm._count,
+                status: sm.status
+            })),
+            approvalPendingVenues: approvalPendingVenues.map(v => ({
+                id: v.id,
+                addressLine1: v.address_line_1,
+                capacity: v.capacity,
+                title: v.title,
+                venueType: v.venue_type
+            })),
+
+        }
+    }
+
+    async getOwnerDashboard(ownerId: string): Promise {
+
+        const [
+            bookingCount,
+            totalRevenue,
+            venueCount,
+            recentBookings
+        ] = await Promise.all([
+            this.prisma.bookings.count({ where: { venue: { owner_id: ownerId } } }),
+            this.prisma.bookings.aggregate({
+                _sum: { total_amount: true },
+                where: {
+                    venue: { owner_id: ownerId }
+                }
+            }),
+            this.prisma.venues.count({ where: { owner_id: ownerId } }),
+            this.prisma.bookings.findMany({
+                where: { venue: { owner_id: ownerId } },
+                take: 10,
+                orderBy: { created_at: 'desc' },
+                include: {
+                    venue: true
+                }
+            })
+        ])
+
+        return {
+            bookingCount,
+            venueCount,
+            totalRevenue: totalRevenue._sum.total_amount?.toNumber() || 0,
+            recentBookings: recentBookings.map(b => ({
+                id: b.id,
+                amount: b.total_amount.toNumber(),
+                endDate: b.booking_end,
+                startDate: b.booking_start,
+                guestsCount: b.guests_count,
+                venueName: b.venue.title,
+            }))
+        }
+    }
+}
diff --git a/backend/src/infra/repositories/prisma-payment.repository.ts b/backend/src/infra/repositories/prisma-payment.repository.ts
new file mode 100644
index 000000000..37894fcdf
--- /dev/null
+++ b/backend/src/infra/repositories/prisma-payment.repository.ts
@@ -0,0 +1,146 @@
+import { Injectable } from "@nestjs/common";
+import type { IPaymentRepository, UpdatePaymentDto } from "src/core/domain/payment/repositories/payment-repository.interface";
+import { PrismaService } from "../database/prisma/prisma.service";
+import { Payment } from "src/core/domain/payment/entities/payment.entity";
+import type { PaymentStatus } from "src/core/domain/_shared/enum/PaymentStatus.enum";
+
+
+@Injectable()
+export class PrismaPaymentRepository implements IPaymentRepository {
+
+    constructor(private readonly prisma: PrismaService) { }
+
+    async create(payment: Payment): Promise {
+        await this.prisma.payments.create({
+            data: {
+                id: payment.id,
+                amount: payment.amount,
+                provider: payment.provider,
+                booking_id: payment.bookingId,
+                provider_order_id: payment.providerOrderId,
+                status: payment.status,
+                currency: payment.currency,
+            }
+        })
+    }
+
+    async findById(id: string): Promise {
+
+        const payment = await this.prisma.payments.findUnique({ where: { id } })
+
+        if (!payment) return null
+
+        return Payment.restore(payment.id, {
+            amount: payment.amount.toNumber(),
+            bookingId: payment.booking_id,
+            paidAt: payment.paid_at,
+            provider: payment.provider,
+            providerPaymentId: payment.provider_payment_id,
+            status: payment.status as PaymentStatus,
+            currency: payment.currency,
+            providerOrderId: payment.provider_order_id,
+            failureReason: payment.failure_reason,
+            createdAt: payment.created_at,
+            updatedAt: payment.updated_at
+        })
+
+    }
+
+    async findAllByBookingId(bookingId: string): Promise {
+        const payments = await this.prisma.payments.findMany({
+            where: { booking_id: bookingId }
+        })
+
+        return payments.map(payment => (
+            Payment.restore(payment.id, {
+                amount: payment.amount.toNumber(),
+                bookingId: payment.booking_id,
+                paidAt: payment.paid_at,
+                provider: payment.provider,
+                providerPaymentId: payment.provider_payment_id,
+                status: payment.status as PaymentStatus,
+                currency: payment.currency,
+                providerOrderId: payment.provider_order_id,
+                failureReason: payment.failure_reason,
+                createdAt: payment.created_at,
+                updatedAt: payment.updated_at
+            })
+        ))
+    }
+
+    async findByBookingId(bookingId: string): Promise {
+        const payment = await this.prisma.payments.findFirst({
+            where: { booking_id: bookingId },
+            orderBy: { created_at: 'desc' }
+        })
+
+        if (!payment) return null
+
+        return Payment.restore(payment.id, {
+            amount: payment.amount.toNumber(),
+            bookingId: payment.booking_id,
+            paidAt: payment.paid_at,
+            provider: payment.provider,
+            providerPaymentId: payment.provider_payment_id,
+            status: payment.status as PaymentStatus,
+            currency: payment.currency,
+            providerOrderId: payment.provider_order_id,
+            failureReason: payment.failure_reason,
+            createdAt: payment.created_at,
+            updatedAt: payment.updated_at
+        })
+
+    }
+
+    async findByProviderOrderId(orderId: string): Promise {
+        const payment = await this.prisma.payments.findFirst({
+            where: { provider_order_id: orderId },
+            orderBy: { created_at: 'desc' }
+        })
+
+        if (!payment) return null
+
+        return Payment.restore(payment.id, {
+            amount: payment.amount.toNumber(),
+            bookingId: payment.booking_id,
+            paidAt: payment.paid_at,
+            provider: payment.provider,
+            providerPaymentId: payment.provider_payment_id,
+            status: payment.status as PaymentStatus,
+            currency: payment.currency,
+            providerOrderId: payment.provider_order_id,
+            failureReason: payment.failure_reason,
+            createdAt: payment.created_at,
+            updatedAt: payment.updated_at
+        })
+
+    }
+
+    async update(id: string, data: UpdatePaymentDto): Promise {
+
+        const payment = await this.prisma.payments.update({
+            where: { id },
+            data: {
+                status: data.status,
+                provider_payment_id: data.providerPaymentId,
+                paid_at: data.paidAt,
+                failure_reason: data.failureReason
+            }
+        })
+
+        return Payment.restore(id, {
+            amount: payment.amount.toNumber(),
+            bookingId: payment.booking_id,
+            paidAt: payment.paid_at,
+            provider: payment.provider,
+            providerPaymentId: payment.provider_payment_id,
+            status: payment.status as PaymentStatus,
+            currency: payment.currency,
+            providerOrderId: payment.provider_order_id,
+            failureReason: payment.failure_reason,
+            createdAt: payment.created_at,
+            updatedAt: payment.updated_at
+        })
+    }
+
+}
diff --git a/backend/src/infra/repositories/prisma-refresh-token.repository.ts b/backend/src/infra/repositories/prisma-refresh-token.repository.ts
new file mode 100644
index 000000000..6c8f5af52
--- /dev/null
+++ b/backend/src/infra/repositories/prisma-refresh-token.repository.ts
@@ -0,0 +1,41 @@
+import { Injectable } from '@nestjs/common';
+import * as crypto from 'crypto';
+import { PrismaService } from '../database/prisma/prisma.service';
+import type { IRefreshTokenRepository } from '../../core/application/users/services/refresh-token-repository.interface';
+
+@Injectable()
+export class PrismaRefreshTokenRepository implements IRefreshTokenRepository {
+  constructor(private readonly prisma: PrismaService) {}
+
+  private hashToken(rawToken: string): string {
+    return crypto.createHash('sha256').update(rawToken).digest('hex');
+  }
+
+  async save(userId: string, rawToken: string, expiresAt: Date): Promise {
+    await this.prisma.refresh_tokens.create({
+      data: {
+        id: crypto.randomUUID(),
+        user_id: userId,
+        token_hash: this.hashToken(rawToken),
+        expires_at: expiresAt,
+      },
+    });
+  }
+
+  async verify(userId: string, rawToken: string): Promise {
+    const record = await this.prisma.refresh_tokens.findFirst({
+      where: {
+        user_id: userId,
+        token_hash: this.hashToken(rawToken),
+        expires_at: { gt: new Date() },
+      },
+    });
+    return record !== null;
+  }
+
+  async deleteByUserId(userId: string): Promise {
+    await this.prisma.refresh_tokens.deleteMany({
+      where: { user_id: userId },
+    });
+  }
+}
diff --git a/backend/src/infra/repositories/prisma-user.repository.ts b/backend/src/infra/repositories/prisma-user.repository.ts
new file mode 100644
index 000000000..6fb8a0b11
--- /dev/null
+++ b/backend/src/infra/repositories/prisma-user.repository.ts
@@ -0,0 +1,91 @@
+import { Injectable } from '@nestjs/common';
+import { PrismaService } from '../database/prisma/prisma.service';
+import { User, type UserRole, type UserStatus } from '../../core/domain/users/entities/user.entity';
+import type { IUserRepository } from '../../core/domain/users/repositories/user-repository.interface';
+import { role as PrismaRole, user_status as PrismaStatus } from '../database/prisma/generated/prisma/client';
+
+@Injectable()
+export class PrismaUserRepository implements IUserRepository {
+  constructor(private readonly prisma: PrismaService) { }
+
+  private mapToDomain(dbUser: any): User {
+    return User.restore(dbUser.id, {
+      email: dbUser.email,
+      password: dbUser.password,
+      firstName: dbUser.first_name,
+      lastName: dbUser.last_name,
+      phone: dbUser.phone,
+      googleId: dbUser.google_id,
+      role: dbUser.role as UserRole,
+      status: dbUser.status as UserStatus,
+      createdAt: dbUser.created_at,
+      updatedAt: dbUser.updated_at,
+    });
+  }
+
+  async findAll(query?: { search?: string, offset: number, limit: number }): Promise {
+    const dbUsers = await this.prisma.users.findMany({
+      where: query?.search ? {
+        OR: [
+          { email: { contains: query.search, mode: 'insensitive' } },
+          { first_name: { contains: query.search, mode: 'insensitive' } },
+          { last_name: { contains: query.search, mode: 'insensitive' } },
+          { phone: { contains: query.search, mode: 'insensitive' } },
+        ],
+      } : undefined,
+      skip: query?.offset,
+      take: query?.limit,
+      orderBy: { created_at: 'desc' },
+    });
+
+    return dbUsers.map(this.mapToDomain);
+  }
+
+  async findById(id: string): Promise {
+    const dbUser = await this.prisma.users.findUnique({
+      where: { id },
+    });
+    if (!dbUser) return null;
+    return this.mapToDomain(dbUser);
+  }
+
+  async findByEmail(email: string): Promise {
+    const dbUser = await this.prisma.users.findUnique({
+      where: { email },
+    });
+    if (!dbUser) return null;
+    return this.mapToDomain(dbUser);
+  }
+
+  async findByGoogleId(googleId: string): Promise {
+    const dbUser = await this.prisma.users.findUnique({
+      where: { google_id: googleId },
+    });
+    if (!dbUser) return null;
+    return this.mapToDomain(dbUser);
+  }
+
+  async save(user: User): Promise {
+    const data = {
+      email: user.email,
+      password: user.password,
+      first_name: user.firstName,
+      last_name: user.lastName,
+      phone: user.phone,
+      google_id: user.googleId,
+      role: user.role as PrismaRole,
+      status: user.status as PrismaStatus,
+      updated_at: user.updatedAt,
+    };
+
+    await this.prisma.users.upsert({
+      where: { id: user.id },
+      update: data,
+      create: {
+        id: user.id,
+        ...data,
+        created_at: user.createdAt,
+      },
+    });
+  }
+}
diff --git a/backend/src/infra/repositories/prisma-venue-image.repository.ts b/backend/src/infra/repositories/prisma-venue-image.repository.ts
new file mode 100644
index 000000000..e2f9f6b9b
--- /dev/null
+++ b/backend/src/infra/repositories/prisma-venue-image.repository.ts
@@ -0,0 +1,65 @@
+import { Injectable } from '@nestjs/common';
+import type { IVenueImageRepository } from 'src/core/domain/venues/repositories/venue-image-repository.interface';
+import { PrismaService } from '../database/prisma/prisma.service';
+import { VenueImage } from 'src/core/domain/venues/entities/venue-image.entity';
+
+
+
+@Injectable()
+export class PrismaVenueImageRepository implements IVenueImageRepository {
+
+    constructor(
+        private readonly prisma: PrismaService,
+    ) { }
+
+    async create(
+        images: VenueImage[],
+    ): Promise {
+
+        if (images.length === 0) {
+            return;
+        }
+
+        await this.prisma.venue_images.createMany({
+            data: images.map(image => ({
+                id: image.id,
+                venue_id: image.venueId,
+                image_url: image.url,
+                created_at: image.createdAt,
+            })),
+        });
+    }
+
+    async delete(
+        id: string,
+    ): Promise {
+
+        await this.prisma.venue_images.delete({
+            where: { id },
+        });
+    }
+
+    async findByVenueId(
+        venueId: string,
+    ): Promise {
+
+        const images =
+            await this.prisma.venue_images.findMany({
+                where: { venue_id: venueId },
+                orderBy: {
+                    created_at: 'asc',
+                },
+            });
+
+        return images.map(image =>
+            VenueImage.restore(
+                image.id,
+                {
+                    venueId: image.venue_id,
+                    url: image.image_url,
+                    createdAt: image.created_at,
+                },
+            ),
+        );
+    }
+}
\ No newline at end of file
diff --git a/backend/src/infra/repositories/prisma-venue.repository.ts b/backend/src/infra/repositories/prisma-venue.repository.ts
new file mode 100644
index 000000000..5437b4b30
--- /dev/null
+++ b/backend/src/infra/repositories/prisma-venue.repository.ts
@@ -0,0 +1,149 @@
+import { Injectable } from '@nestjs/common';
+import { PrismaService } from '../database/prisma/prisma.service';
+import { Venue, type VenueStatus } from '../../core/domain/venues/entities/venue.entity';
+import { Address } from '../../core/domain/venues/value-objects/address.vo';
+import type { IVenueRepository, VenueFilters, VenuePaginationFilters } from '../../core/domain/venues/repositories/venue-repository.interface';
+import { venue_status as PrismaVenueStatus } from '../database/prisma/generated/prisma/client';
+
+@Injectable()
+export class PrismaVenueRepository implements IVenueRepository {
+  constructor(private readonly prisma: PrismaService) { }
+
+  private mapToDomain(dbVenue: any): Venue {
+    const address = Address.create({
+      addressLine1: dbVenue.address_line_1,
+      city: dbVenue.city,
+      state: dbVenue.state,
+      country: dbVenue.country,
+      postalCode: dbVenue.postal_code,
+      latitude: dbVenue.latitude ? Number(dbVenue.latitude) : null,
+      longitude: dbVenue.longitude ? Number(dbVenue.longitude) : null,
+    });
+
+    return Venue.restore(dbVenue.id, {
+      ownerId: dbVenue.owner_id,
+      title: dbVenue.title,
+      description: dbVenue.description,
+      venueType: dbVenue.venue_type,
+      address,
+      capacity: dbVenue.capacity,
+      pricePerDay: Number(dbVenue.price_per_day),
+      status: dbVenue.status as VenueStatus,
+      amenities: dbVenue.amenities,
+      images: dbVenue.images.map(img => ({
+        id: img.id,
+        url: img.image_url
+      })),
+      createdAt: dbVenue.created_at,
+      updatedAt: dbVenue.updated_at,
+    });
+  }
+
+  async findById(id: string): Promise {
+    const dbVenue = await this.prisma.venues.findUnique({
+      where: { id },
+      include: { images: true }
+    });
+    if (!dbVenue) return null;
+    return this.mapToDomain(dbVenue);
+  }
+
+  async findAll(filters?: VenueFilters): Promise {
+    const where: any = {};
+
+    if (filters) {
+      if (filters.city) {
+        where.city = { contains: filters.city, mode: 'insensitive' };
+      }
+      if (filters.venueType) {
+        where.venue_type = filters.venueType;
+      }
+      if (filters.capacity) {
+        where.capacity = { gte: filters.capacity };
+      }
+      if (filters.ownerId) {
+        where.owner_id = filters.ownerId;
+      }
+      if (filters.status) {
+        where.status = filters.status as PrismaVenueStatus;
+      }
+    }
+
+    const dbVenues = await this.prisma.venues.findMany({
+      where,
+      include: { images: true },
+      orderBy: { created_at: 'desc' },
+    });
+
+    return dbVenues.map((dbVenue) => this.mapToDomain(dbVenue));
+  }
+
+  async findAndCountAll(filters: VenuePaginationFilters): Promise<{ count: number; venues: Venue[]; }> {
+
+    const where: any = {};
+
+    if (filters) {
+      if (filters.city) {
+        where.city = { contains: filters.city, mode: 'insensitive' };
+      }
+      if (filters.venueType) {
+        where.venue_type = filters.venueType;
+      }
+      if (filters.capacity) {
+        where.capacity = { gte: filters.capacity };
+      }
+      if (filters.ownerId) {
+        where.owner_id = filters.ownerId;
+      }
+      if (filters.status) {
+        where.status = filters.status as PrismaVenueStatus;
+      }
+    }
+
+    const dbVenues = await this.prisma.venues.findMany({
+      where,
+      include: { images: true },
+      orderBy: { created_at: 'desc' },
+      take: filters.limit,
+      skip: filters.offset
+    });
+    const count = await this.prisma.venues.count({ where })
+
+    const venues = dbVenues.map((dbVenue) => this.mapToDomain(dbVenue));
+
+    return {
+      venues,
+      count
+    }
+  }
+
+  async save(venue: Venue): Promise {
+    const data = {
+      owner_id: venue.ownerId,
+      title: venue.title,
+      description: venue.description,
+      venue_type: venue.venueType,
+      address_line_1: venue.address.addressLine1,
+      city: venue.address.city,
+      state: venue.address.state,
+      country: venue.address.country,
+      postal_code: venue.address.postalCode,
+      latitude: venue.address.latitude ? (venue.address.latitude as any) : null,
+      longitude: venue.address.longitude ? (venue.address.longitude as any) : null,
+      capacity: venue.capacity,
+      price_per_day: venue.pricePerDay as any,
+      status: venue.status as PrismaVenueStatus,
+      updated_at: venue.updatedAt,
+    };
+
+    await this.prisma.venues.upsert({
+      where: { id: venue.id },
+      update: data,
+      create: {
+        id: venue.id,
+        ...data,
+        created_at: venue.createdAt,
+      },
+    });
+  }
+}
diff --git a/backend/src/infra/services/argon-password-hasher.ts b/backend/src/infra/services/argon-password-hasher.ts
new file mode 100644
index 000000000..811cbc7a3
--- /dev/null
+++ b/backend/src/infra/services/argon-password-hasher.ts
@@ -0,0 +1,12 @@
+import * as argon2 from 'argon2';
+import type { IPasswordHasher } from 'src/core/application/users/services/password-hasher.interface';
+
+export class Argon2PasswordHasher implements IPasswordHasher {
+    async hash(password: string): Promise {
+        return argon2.hash(password);
+    }
+
+    async compare(password: string, hashed: string): Promise {
+        return argon2.verify(hashed, password);
+    }
+}
\ No newline at end of file
diff --git a/backend/src/infra/services/jwt-token.service.ts b/backend/src/infra/services/jwt-token.service.ts
new file mode 100644
index 000000000..663f54953
--- /dev/null
+++ b/backend/src/infra/services/jwt-token.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from '@nestjs/common';
+import * as jwt from 'jsonwebtoken';
+import type { ITokenService, TokenPayload } from '../../core/application/users/services/token.interface';
+
+@Injectable()
+export class JwtTokenService implements ITokenService {
+  private readonly jwtSecret = process.env.JWT_SECRET || 'bmv-secret-key-123456';
+  private readonly jwtRefreshSecret = process.env.JWT_REFRESH_SECRET || 'bmv-refresh-secret-key-123456';
+
+  generateAccessToken(payload: TokenPayload): string {
+    // @ts-ignore
+    return jwt.sign(payload, this.jwtSecret, {
+      expiresIn: process.env.JWT_ACCESS_EXPIRATION || '1h',
+    });
+  }
+  generateRefreshToken(payload: TokenPayload): string {
+    // @ts-ignore
+    return jwt.sign(payload, this.jwtRefreshSecret, {
+      expiresIn: process.env.JWT_REFRESH_EXPIRATION || '7d',
+    });
+  }
+
+  verifyAccessToken(token: string): TokenPayload | null {
+    try {
+      const decoded = jwt.verify(token, this.jwtSecret) as jwt.JwtPayload;
+      return {
+        userId: decoded.userId,
+        email: decoded.email,
+        role: decoded.role,
+      };
+    } catch {
+      return null;
+    }
+  }
+
+  verifyRefreshToken(token: string): TokenPayload | null {
+    try {
+      const decoded = jwt.verify(token, this.jwtRefreshSecret) as jwt.JwtPayload;
+      return {
+        userId: decoded.userId,
+        email: decoded.email,
+        role: decoded.role,
+      };
+    } catch {
+      return null;
+    }
+  }
+}
diff --git a/backend/src/infra/storage/local-file.storage.ts b/backend/src/infra/storage/local-file.storage.ts
new file mode 100644
index 000000000..8f24c1028
--- /dev/null
+++ b/backend/src/infra/storage/local-file.storage.ts
@@ -0,0 +1,52 @@
+import { promises as fs } from 'fs';
+import * as path from 'path';
+import { randomUUID } from 'crypto';
+import type { IFileStorage } from 'src/core/application/_shared/storage/file-storage.interface';
+import { APP_CONFIG } from 'src/config/app.config';
+
+export class LocalFileStorageService implements IFileStorage {
+    private readonly uploadDir = path.join(
+        process.cwd(),
+        'uploads',
+        'venues',
+    );
+
+    async upload(
+        fileName: string,
+        buffer: Buffer,
+    ): Promise {
+        await fs.mkdir(
+            this.uploadDir,
+            { recursive: true },
+        );
+
+        const extension =
+            path.extname(fileName);
+
+        const storedFileName =
+            `${randomUUID()}${extension}`;
+
+        const fullPath = path.join(
+            this.uploadDir,
+            storedFileName,
+        );
+
+        await fs.writeFile(
+            fullPath,
+            buffer,
+        );
+
+        return APP_CONFIG.BASE_URL + `/uploads/venues/${storedFileName}`;
+    }
+
+    async delete(
+        filePath: string,
+    ): Promise {
+        const fullPath = path.join(
+            process.cwd(),
+            filePath,
+        );
+
+        await fs.unlink(fullPath);
+    }
+}
\ No newline at end of file
diff --git a/backend/src/main.ts b/backend/src/main.ts
new file mode 100644
index 000000000..2ba01b30d
--- /dev/null
+++ b/backend/src/main.ts
@@ -0,0 +1,66 @@
+import { NestFactory } from '@nestjs/core';
+import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
+import { AppModule } from './presentation/app.module';
+import { NestjsConsoleLogger } from './infra/logger/console.logger';
+import { DomainExceptionFilter } from './presentation/filters/domain-exception.filter';
+import { VersioningType } from '@nestjs/common';
+import type { NestExpressApplication } from '@nestjs/platform-express';
+import { join } from 'path';
+
+async function bootstrap() {
+  const app = await NestFactory.create(AppModule,);
+
+  app.useLogger(new NestjsConsoleLogger());
+  app.useGlobalFilters(new DomainExceptionFilter());
+
+  // versioning
+  app.enableVersioning({
+    type: VersioningType.URI,
+  });
+
+  app.enableCors({
+    origin: process.env.CORS_ORIGIN?.split(',') || '*',
+    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
+    credentials: true,
+  });
+
+  app.useStaticAssets(
+    join(process.cwd(), 'uploads'),
+    {
+      prefix: '/uploads',
+    },
+  );
+
+  app.setGlobalPrefix('api', {
+    exclude: ['health/*', '/']
+  });
+
+  const config = new DocumentBuilder()
+    .setTitle('BMV API Documentation')
+    .setDescription('API documentation for the BookMyVenue application')
+    .setVersion('1.0')
+    .addBearerAuth(
+      {
+        type: 'http',
+        scheme: 'bearer',
+        bearerFormat: 'JWT',
+        name: 'Authorization',
+        description: 'Enter JWT token',
+        in: 'header',
+      },
+      'JWT-auth',
+    )
+    .build();
+  const documentFactory = () => SwaggerModule.createDocument(app, config);
+  SwaggerModule.setup('docs', app, documentFactory, {
+    swaggerOptions: {
+      persistAuthorization: true,
+      tryItOutEnabled: true,
+    },
+    swaggerUiEnabled: true
+  });
+
+  await app.listen(process.env.PORT ?? 3000);
+  console.log(`Application is running on: ${await app.getUrl()}`);
+}
+bootstrap();
diff --git a/backend/src/presentation/app.controller.ts b/backend/src/presentation/app.controller.ts
new file mode 100644
index 000000000..cce879ee6
--- /dev/null
+++ b/backend/src/presentation/app.controller.ts
@@ -0,0 +1,12 @@
+import { Controller, Get } from '@nestjs/common';
+import { AppService } from './app.service';
+
+@Controller()
+export class AppController {
+  constructor(private readonly appService: AppService) {}
+
+  @Get()
+  getHello(): string {
+    return this.appService.getHello();
+  }
+}
diff --git a/backend/src/presentation/app.module.ts b/backend/src/presentation/app.module.ts
new file mode 100644
index 000000000..8c8c1ea87
--- /dev/null
+++ b/backend/src/presentation/app.module.ts
@@ -0,0 +1,29 @@
+import { ConsoleLogger, Module } from '@nestjs/common';
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+import { UsersModule } from './modules/users/users.module';
+import { AuthModule } from './modules/auth/auth.module';
+import { BookingsModule } from './modules/bookings/bookings.module';
+import { VenuesModule } from './modules/venues/venues.module';
+import { AdminModule } from './modules/admin/admin.module';
+import { DashboardModule } from './modules/dashboard/dashboard.module';
+import { PaymentModule } from './modules/payment/payment.module';
+import { HealthController } from './modules/health.controller';
+import { PrismaService } from 'src/infra/database/prisma/prisma.service';
+import { InfraModule } from 'src/infra/infra.module';
+
+@Module({
+  imports: [
+    InfraModule,
+    AuthModule,
+    DashboardModule,
+    AdminModule,
+    BookingsModule,
+    VenuesModule,
+    UsersModule,
+    PaymentModule
+  ],
+  controllers: [AppController, HealthController],
+  providers: [AppService, PrismaService, ConsoleLogger],
+})
+export class AppModule { }
diff --git a/backend/src/presentation/app.service.ts b/backend/src/presentation/app.service.ts
new file mode 100644
index 000000000..60ba4f577
--- /dev/null
+++ b/backend/src/presentation/app.service.ts
@@ -0,0 +1,13 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class AppService {
+  getHello(): string {
+    return `
+    

Welcome to BookMyVenue API

+

+ Explore our API documentation at /docs +

+ `; + } +} diff --git a/backend/src/presentation/decorators/current-user.decorator.ts b/backend/src/presentation/decorators/current-user.decorator.ts new file mode 100644 index 000000000..77d1a3d7e --- /dev/null +++ b/backend/src/presentation/decorators/current-user.decorator.ts @@ -0,0 +1,8 @@ +import { createParamDecorator, type ExecutionContext } from '@nestjs/common'; + +export const CurrentUser = createParamDecorator( + (data: unknown, ctx: ExecutionContext) => { + const request = ctx.switchToHttp().getRequest(); + return request.user; + }, +); diff --git a/backend/src/presentation/decorators/roles.decorator.ts b/backend/src/presentation/decorators/roles.decorator.ts new file mode 100644 index 000000000..e038e1682 --- /dev/null +++ b/backend/src/presentation/decorators/roles.decorator.ts @@ -0,0 +1,4 @@ +import { SetMetadata } from '@nestjs/common'; + +export const ROLES_KEY = 'roles'; +export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles); diff --git a/backend/src/presentation/filters/domain-exception.filter.ts b/backend/src/presentation/filters/domain-exception.filter.ts new file mode 100644 index 000000000..607ecb569 --- /dev/null +++ b/backend/src/presentation/filters/domain-exception.filter.ts @@ -0,0 +1,31 @@ +import { + type ExceptionFilter, + type ArgumentsHost, + Catch, + HttpStatus, +} from '@nestjs/common'; +import { type Response } from 'express'; +import { NotFoundException } from '../../core/domain/_shared/exception/notfound.exception'; +import { BusinessRuleException } from '../../core/domain/_shared/exception/business-rule.exception'; +import { DomainException } from '../../core/domain/_shared/exception/domain.exception'; + +@Catch(DomainException) +export class DomainExceptionFilter implements ExceptionFilter { + catch(exception: DomainException, host: ArgumentsHost): void { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + + let status = HttpStatus.BAD_REQUEST; + if (exception instanceof NotFoundException) { + status = HttpStatus.NOT_FOUND; + } else if (exception instanceof BusinessRuleException) { + status = HttpStatus.BAD_REQUEST; + } + + response.status(status).json({ + statusCode: status, + message: exception.message, + error: exception.name, + }); + } +} diff --git a/backend/src/presentation/guards/jwt-auth.guard.ts b/backend/src/presentation/guards/jwt-auth.guard.ts new file mode 100644 index 000000000..95c65ed4b --- /dev/null +++ b/backend/src/presentation/guards/jwt-auth.guard.ts @@ -0,0 +1,37 @@ +import { + type CanActivate, + type ExecutionContext, + Injectable, + Inject, + UnauthorizedException, +} from '@nestjs/common'; +import type { ITokenService } from '../../core/application/users/services/token.interface'; + +@Injectable() +export class JwtAuthGuard implements CanActivate { + constructor( + @Inject('ITokenService') + private readonly tokenService: ITokenService, + ) {} + + canActivate(context: ExecutionContext): boolean { + const request = context.switchToHttp().getRequest(); + const authHeader = request.headers.authorization; + if (!authHeader || !authHeader.startsWith('Bearer ')) { + throw new UnauthorizedException('Missing or invalid Authorization header'); + } + + const token = authHeader.split(' ')[1]; + if (!token) { + throw new UnauthorizedException('Token not found'); + } + + const payload = this.tokenService.verifyAccessToken(token); + if (!payload) { + throw new UnauthorizedException('Invalid or expired token'); + } + + request.user = payload; + return true; + } +} diff --git a/backend/src/presentation/guards/roles.guard.ts b/backend/src/presentation/guards/roles.guard.ts new file mode 100644 index 000000000..478871a62 --- /dev/null +++ b/backend/src/presentation/guards/roles.guard.ts @@ -0,0 +1,33 @@ +import { + type CanActivate, + type ExecutionContext, + Injectable, + ForbiddenException, +} from '@nestjs/common'; +import { Reflector } from '@nestjs/core'; +import { ROLES_KEY } from '../decorators/roles.decorator'; + +@Injectable() +export class RolesGuard implements CanActivate { + constructor(private readonly reflector: Reflector) {} + + canActivate(context: ExecutionContext): boolean { + const requiredRoles = this.reflector.getAllAndOverride(ROLES_KEY, [ + context.getHandler(), + context.getClass(), + ]); + + if (!requiredRoles || requiredRoles.length === 0) { + return true; + } + + const request = context.switchToHttp().getRequest(); + const user = request.user; + + if (!user || !requiredRoles.includes(user.role)) { + throw new ForbiddenException('Insufficient permissions'); + } + + return true; + } +} diff --git a/backend/src/presentation/modules/admin/admin.controller.ts b/backend/src/presentation/modules/admin/admin.controller.ts new file mode 100644 index 000000000..bac86a0e7 --- /dev/null +++ b/backend/src/presentation/modules/admin/admin.controller.ts @@ -0,0 +1,49 @@ +import { Body, Controller, Get, Param, ParseUUIDPipe, Post, UseGuards } from '@nestjs/common'; +import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { ApproveVenueCommand } from 'src/core/application/admin/commands/approve-venue.command'; +import { RejectVenueCommand } from 'src/core/application/admin/commands/reject-venue.command'; +import { ListVenueQuery } from 'src/core/application/admin/queries/list-venues.query'; +import { UserRole } from 'src/core/domain/_shared/enum/UserRole'; +import { Roles } from 'src/presentation/decorators/roles.decorator'; +import { JwtAuthGuard } from 'src/presentation/guards/jwt-auth.guard'; +import { RolesGuard } from 'src/presentation/guards/roles.guard'; +import { CreateUserDTO } from './dto/create-user'; +import { CreateUserCommand } from 'src/core/application/admin/commands/create-user.command'; + +@ApiTags('admin') +@Controller({ + version: '1', + path: 'admin', +}) +@UseGuards(JwtAuthGuard, RolesGuard) +@Roles(UserRole.ADMIN) +@ApiBearerAuth('JWT-auth') +export class AdminController { + constructor( + private readonly listVenuesQuery: ListVenueQuery, + private readonly approveVenueCommand: ApproveVenueCommand, + private readonly rejectVenueCommand: RejectVenueCommand, + private readonly createUserCommand: CreateUserCommand + ) { } + + @Get('venues') + create() { + return this.listVenuesQuery.execute({ limit: 20, offset: 0, search: '' }) + } + + @Post('venues/:id/approve') + approveVenue(@Param('id', ParseUUIDPipe) id: string) { + return this.approveVenueCommand.execute(id) + } + + @Post('venues/:id/reject') + rejectVenue(@Param('id', ParseUUIDPipe) id: string) { + return this.rejectVenueCommand.execute(id) + } + + @Post('users') + createUser(@Body() data: CreateUserDTO) { + return this.createUserCommand.execute(data) + } + +} diff --git a/backend/src/presentation/modules/admin/admin.module.ts b/backend/src/presentation/modules/admin/admin.module.ts new file mode 100644 index 000000000..8fe1458f2 --- /dev/null +++ b/backend/src/presentation/modules/admin/admin.module.ts @@ -0,0 +1,14 @@ +import { Module } from '@nestjs/common'; +import { AdminController } from './admin.controller'; +import { InfraModule } from 'src/infra/infra.module'; +import { ListVenueQuery } from 'src/core/application/admin/queries/list-venues.query'; +import { ApproveVenueCommand } from 'src/core/application/admin/commands/approve-venue.command'; +import { RejectVenueCommand } from 'src/core/application/admin/commands/reject-venue.command'; +import { CreateUserCommand } from 'src/core/application/admin/commands/create-user.command'; + +@Module({ + imports: [InfraModule], + controllers: [AdminController], + providers: [ListVenueQuery, ApproveVenueCommand, RejectVenueCommand, CreateUserCommand] +}) +export class AdminModule { } diff --git a/backend/src/presentation/modules/admin/dto/create-user.ts b/backend/src/presentation/modules/admin/dto/create-user.ts new file mode 100644 index 000000000..c0220adab --- /dev/null +++ b/backend/src/presentation/modules/admin/dto/create-user.ts @@ -0,0 +1,22 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { UserRole } from 'src/core/domain/_shared/enum/UserRole'; + +export class CreateUserDTO { + @ApiProperty({ example: 'user@bmv.com' }) + email!: string; + + @ApiProperty({ example: 'password123' }) + password!: string; + + @ApiProperty({ example: 'John' }) + firstName!: string; + + @ApiProperty({ example: 'Doe', required: false }) + lastName?: string; + + @ApiProperty({ example: '+919876543210', required: false }) + phone?: string; + + @ApiProperty({ enum: [UserRole.USER, UserRole.VENUE_OWNER] }) + role!: UserRole.USER | UserRole.VENUE_OWNER +} diff --git a/backend/src/presentation/modules/auth/auth.controller.ts b/backend/src/presentation/modules/auth/auth.controller.ts new file mode 100644 index 000000000..4bd1ee498 --- /dev/null +++ b/backend/src/presentation/modules/auth/auth.controller.ts @@ -0,0 +1,65 @@ +import { Controller, Post, Body, UseGuards, Get } from '@nestjs/common'; +import { RegisterUserCommand } from '../../../core/application/users/commands/register-user.command'; +import { LoginUserCommand } from '../../../core/application/users/commands/login-user.command'; +import { RefreshAccessTokenCommand } from '../../../core/application/users/commands/refresh-access-token.command'; +import { LogoutCommand } from '../../../core/application/users/commands/logout.command'; +import { ZodValidationPipe } from '../../pipes/zod-validation.pipe'; +import { loginSchema } from '../../validation/auth/login.schema'; +import { registerSchema } from '../../validation/auth/register.schema'; +import { refreshTokenSchema } from '../../validation/auth/refresh-token.schema'; +import { RegisterDto } from './dto/register.dto'; +import { LoginDto } from './dto/login.dto'; +import { RefreshTokenDto } from './dto/refresh-token.dto'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { CurrentUser } from '../../decorators/current-user.decorator'; +import { type TokenPayload } from '../../../core/application/users/services/token.interface'; +import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger'; + +@ApiTags('auth') +@Controller({ + version: '1', + path: 'auth', +}) +export class AuthController { + constructor( + private readonly registerUserCommand: RegisterUserCommand, + private readonly loginUserCommand: LoginUserCommand, + private readonly refreshAccessTokenCommand: RefreshAccessTokenCommand, + private readonly logoutCommand: LogoutCommand, + ) { } + + @Post('register') + @ApiOperation({ summary: 'Register a new user' }) + @ApiResponse({ status: 201, description: 'User successfully registered' }) + @ApiResponse({ status: 400, description: 'Validation or business rule failure' }) + register(@Body(new ZodValidationPipe(registerSchema as any)) data: RegisterDto) { + return this.registerUserCommand.execute(data); + } + + @Post('login') + @ApiOperation({ summary: 'Login a user and obtain tokens' }) + @ApiResponse({ status: 200, description: 'Successfully authenticated' }) + @ApiResponse({ status: 400, description: 'Validation or business rule failure' }) + login(@Body(new ZodValidationPipe(loginSchema as any)) data: LoginDto) { + return this.loginUserCommand.execute(data); + } + + @Post('refresh') + @ApiOperation({ summary: 'Refresh access token using a refresh token' }) + @ApiResponse({ status: 200, description: 'Tokens refreshed successfully' }) + @ApiResponse({ status: 400, description: 'Invalid or expired refresh token' }) + refresh(@Body(new ZodValidationPipe(refreshTokenSchema as any)) data: RefreshTokenDto) { + return this.refreshAccessTokenCommand.execute(data); + } + + @Post('logout') + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + @ApiOperation({ summary: 'Logout and revoke refresh tokens' }) + @ApiResponse({ status: 200, description: 'Logged out successfully' }) + logout(@CurrentUser() user: TokenPayload) { + return this.logoutCommand.execute({ userId: user.userId }); + } + +} + diff --git a/backend/src/presentation/modules/auth/auth.module.ts b/backend/src/presentation/modules/auth/auth.module.ts new file mode 100644 index 000000000..592dcec05 --- /dev/null +++ b/backend/src/presentation/modules/auth/auth.module.ts @@ -0,0 +1,21 @@ +import { Module } from '@nestjs/common'; +import { AuthController } from './auth.controller'; +import { RegisterUserCommand } from '../../../core/application/users/commands/register-user.command'; +import { LoginUserCommand } from '../../../core/application/users/commands/login-user.command'; +import { RefreshAccessTokenCommand } from '../../../core/application/users/commands/refresh-access-token.command'; +import { LogoutCommand } from '../../../core/application/users/commands/logout.command'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { InfraModule } from '../../../infra/infra.module'; + +@Module({ + imports: [InfraModule], + controllers: [AuthController], + providers: [ + RegisterUserCommand, + LoginUserCommand, + RefreshAccessTokenCommand, + LogoutCommand, + JwtAuthGuard, + ], +}) +export class AuthModule {} diff --git a/backend/src/presentation/modules/auth/dto/login.dto.ts b/backend/src/presentation/modules/auth/dto/login.dto.ts new file mode 100644 index 000000000..7bfde1e72 --- /dev/null +++ b/backend/src/presentation/modules/auth/dto/login.dto.ts @@ -0,0 +1,11 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class LoginDto { + + @ApiProperty({ example: 'user@bmv.com' }) + email!: string; + + @ApiProperty({ example: 'password123' }) + password!: string; + +} diff --git a/backend/src/presentation/modules/auth/dto/refresh-token.dto.ts b/backend/src/presentation/modules/auth/dto/refresh-token.dto.ts new file mode 100644 index 000000000..0be323eef --- /dev/null +++ b/backend/src/presentation/modules/auth/dto/refresh-token.dto.ts @@ -0,0 +1,6 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class RefreshTokenDto { + @ApiProperty() + refreshToken!: string; +} diff --git a/backend/src/presentation/modules/auth/dto/register.dto.ts b/backend/src/presentation/modules/auth/dto/register.dto.ts new file mode 100644 index 000000000..9e973d145 --- /dev/null +++ b/backend/src/presentation/modules/auth/dto/register.dto.ts @@ -0,0 +1,18 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class RegisterDto { + @ApiProperty({ example: 'user@bmv.com' }) + email!: string; + + @ApiProperty({ example: 'password123' }) + password!: string; + + @ApiProperty({ example: 'John' }) + firstName!: string; + + @ApiProperty({ example: 'Doe', required: false }) + lastName?: string; + + @ApiProperty({ example: '+919876543210', required: false }) + phone?: string; +} diff --git a/backend/src/presentation/modules/bookings/bookings.controller.ts b/backend/src/presentation/modules/bookings/bookings.controller.ts new file mode 100644 index 000000000..76fa55ec1 --- /dev/null +++ b/backend/src/presentation/modules/bookings/bookings.controller.ts @@ -0,0 +1,98 @@ +import { Controller, Get, Post, Delete, Body, Param, UseGuards, ParseUUIDPipe } from '@nestjs/common'; +import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse } from '@nestjs/swagger'; +import { CreateBookingCommand } from '../../../core/application/bookings/commands/create-booking.command'; +import { CancelBookingCommand } from '../../../core/application/bookings/commands/cancel-booking.command'; +import { GetUserBookingsQuery } from '../../../core/application/bookings/queries/get-user-bookings.query'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { CurrentUser } from '../../decorators/current-user.decorator'; +import { type TokenPayload } from '../../../core/application/users/services/token.interface'; +import { ZodValidationPipe } from '../../pipes/zod-validation.pipe'; +import { createBookingSchema } from '../../validation/bookings/create-booking.schema'; +import { CreateBookingDto } from './dto/create-booking.dto'; +import { RolesGuard } from 'src/presentation/guards/roles.guard'; +import { Roles } from 'src/presentation/decorators/roles.decorator'; +import { UserRole } from 'src/core/domain/_shared/enum/UserRole'; +import { GetBookingsByVenueQuery } from 'src/core/application/bookings/queries/get-venue-bookings.query'; +import { GetBookingsByOwnerQuery } from 'src/core/application/bookings/queries/get-bookings-for-owner.query'; +import { GetBookingDetailsQuery } from 'src/core/application/bookings/queries/get-booking-details.query'; + +@ApiTags('bookings') +@Controller({ + version: '1', + path: 'bookings', +}) +@ApiBearerAuth('JWT-auth') +@UseGuards(JwtAuthGuard, RolesGuard) +export class BookingsController { + constructor( + private readonly createBookingCommand: CreateBookingCommand, + private readonly cancelBookingCommand: CancelBookingCommand, + private readonly getUserBookingsQuery: GetUserBookingsQuery, + private readonly getBookingsByVenueQuery: GetBookingsByVenueQuery, + private readonly getBookingsByOwnerQuery: GetBookingsByOwnerQuery, + private readonly getBookingDetailsQuery: GetBookingDetailsQuery, + ) { } + + @Post() + @ApiOperation({ summary: 'Create a new booking' }) + @ApiResponse({ status: 201, description: 'Booking created successfully' }) + create( + @CurrentUser() user: TokenPayload, + @Body(new ZodValidationPipe(createBookingSchema as any)) data: CreateBookingDto, + ) { + return this.createBookingCommand.execute({ + userId: user.userId, + ...data, + }); + } + + @Get('my-bookings') + @ApiOperation({ summary: 'Get current user bookings' }) + @ApiResponse({ status: 200, description: 'Bookings retrieved successfully' }) + findMine(@CurrentUser() user: TokenPayload) { + return this.getUserBookingsQuery.execute(user.userId); + } + + @Get(':bookingId') + @Roles(UserRole.USER, UserRole.VENUE_OWNER) + @ApiOperation({ summary: 'Get current user bookings' }) + @ApiResponse({ status: 200, description: 'Bookings retrieved successfully' }) + getBookingDetails( + @Param('bookingId', ParseUUIDPipe) bookingId: string, + @CurrentUser() user: TokenPayload, + ) { + return this.getBookingDetailsQuery.execute({ + bookingId, + userId: user.userId, + role: user.role + }); + } + + @Delete(':id') + @ApiOperation({ summary: 'Cancel a booking' }) + @ApiResponse({ status: 200, description: 'Booking cancelled successfully' }) + cancel(@Param('id') id: string, @CurrentUser() user: TokenPayload) { + return this.cancelBookingCommand.execute({ + bookingId: id, + userId: user.userId, + userRole: user.role, + }); + } + + @Get('owner/all-bookings') + @Roles(UserRole.VENUE_OWNER) + @ApiOperation({ summary: 'LIst All bookings for all venues (Venue Owner only)' }) + getBookingForOwner(@CurrentUser() user: TokenPayload) { + return this.getBookingsByOwnerQuery.execute(user.userId) + } + + @Get('venues/:venueId') + @Roles(UserRole.VENUE_OWNER) + @ApiOperation({ summary: 'LIst bookings by venueId (Venue Owner only)' }) + getBookingByVenueId( + @Param('venueId', ParseUUIDPipe) venueId: string, + @CurrentUser() user: TokenPayload + ) { + return this.getBookingsByVenueQuery.execute(venueId, user.userId) + } +} diff --git a/backend/src/presentation/modules/bookings/bookings.module.ts b/backend/src/presentation/modules/bookings/bookings.module.ts new file mode 100644 index 000000000..2ba495e14 --- /dev/null +++ b/backend/src/presentation/modules/bookings/bookings.module.ts @@ -0,0 +1,25 @@ +import { Module } from '@nestjs/common'; +import { BookingsController } from './bookings.controller'; +import { CreateBookingCommand } from '../../../core/application/bookings/commands/create-booking.command'; +import { CancelBookingCommand } from '../../../core/application/bookings/commands/cancel-booking.command'; +import { GetUserBookingsQuery } from '../../../core/application/bookings/queries/get-user-bookings.query'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { InfraModule } from '../../../infra/infra.module'; +import { GetBookingsByVenueQuery } from 'src/core/application/bookings/queries/get-venue-bookings.query'; +import { GetBookingsByOwnerQuery } from 'src/core/application/bookings/queries/get-bookings-for-owner.query'; +import { GetBookingDetailsQuery } from 'src/core/application/bookings/queries/get-booking-details.query'; + +@Module({ + imports: [InfraModule], + controllers: [BookingsController], + providers: [ + CreateBookingCommand, + CancelBookingCommand, + GetUserBookingsQuery, + JwtAuthGuard, + GetBookingsByVenueQuery, + GetBookingsByOwnerQuery, + GetBookingDetailsQuery + ], +}) +export class BookingsModule { } diff --git a/backend/src/presentation/modules/bookings/dto/create-booking.dto.ts b/backend/src/presentation/modules/bookings/dto/create-booking.dto.ts new file mode 100644 index 000000000..ad15fc9dc --- /dev/null +++ b/backend/src/presentation/modules/bookings/dto/create-booking.dto.ts @@ -0,0 +1,15 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateBookingDto { + @ApiProperty({ format: 'uuid' }) + venueId!: string; + + @ApiProperty({ type: String, format: 'date-time' }) + startDate!: Date; + + @ApiProperty({ type: String, format: 'date-time' }) + endDate!: Date; + + @ApiProperty({ minimum: 1 }) + guestsCount!: number; +} diff --git a/backend/src/presentation/modules/dashboard/dashboard.controller.ts b/backend/src/presentation/modules/dashboard/dashboard.controller.ts new file mode 100644 index 000000000..a33eed873 --- /dev/null +++ b/backend/src/presentation/modules/dashboard/dashboard.controller.ts @@ -0,0 +1,43 @@ +import { Controller, Get, UseGuards } from '@nestjs/common'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { CurrentUser } from '../../decorators/current-user.decorator'; +import { type TokenPayload } from '../../../core/application/users/services/token.interface'; +import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse } from '@nestjs/swagger'; +import { RolesGuard } from 'src/presentation/guards/roles.guard'; +import { Roles } from 'src/presentation/decorators/roles.decorator'; +import { UserRole } from 'src/core/domain/_shared/enum/UserRole'; +import { GetAdminDashboardQuery } from 'src/core/application/dashboard/query/admin-dashboard.query'; +import { GetOwnerDashboardQuery } from 'src/core/application/dashboard/query/owner-dashboard.query'; + +@ApiTags('dashboard') +@Controller({ + version: '1', + path: 'dashboard', +}) +@UseGuards(JwtAuthGuard, RolesGuard) +@ApiBearerAuth('JWT-auth') +export class DashboardController { + constructor( + private readonly getAdminDashboardQuery: GetAdminDashboardQuery, + private readonly getOwnerDashboardQuery: GetOwnerDashboardQuery, + ) { } + + @Get('admin') + @Roles(UserRole.ADMIN) + @ApiOperation({ summary: 'Get admin dashboard (for admin)' }) + @ApiResponse({ status: 200, description: 'List of users' }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) + adminDashboard(@CurrentUser() user: TokenPayload) { + return this.getAdminDashboardQuery.execute(); + } + + @Get('owner') + @Roles(UserRole.VENUE_OWNER) + @ApiOperation({ summary: 'Get owner dashboard (for owner)' }) + @ApiResponse({ status: 200, description: 'List of users' }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) + ownerDashboard(@CurrentUser() user: TokenPayload) { + return this.getOwnerDashboardQuery.execute(user.userId); + } + +} diff --git a/backend/src/presentation/modules/dashboard/dashboard.module.ts b/backend/src/presentation/modules/dashboard/dashboard.module.ts new file mode 100644 index 000000000..33b90606d --- /dev/null +++ b/backend/src/presentation/modules/dashboard/dashboard.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { InfraModule } from '../../../infra/infra.module'; +import { DashboardController } from './dashboard.controller'; +import { GetAdminDashboardQuery } from 'src/core/application/dashboard/query/admin-dashboard.query'; +import { GetOwnerDashboardQuery } from 'src/core/application/dashboard/query/owner-dashboard.query'; + +@Module({ + imports: [InfraModule], + controllers: [DashboardController], + providers: [GetAdminDashboardQuery, GetOwnerDashboardQuery, JwtAuthGuard], +}) +export class DashboardModule { } diff --git a/backend/src/presentation/modules/health.controller.ts b/backend/src/presentation/modules/health.controller.ts new file mode 100644 index 000000000..909b5fc37 --- /dev/null +++ b/backend/src/presentation/modules/health.controller.ts @@ -0,0 +1,69 @@ +import { + Controller, + Get, + HttpStatus, + Inject, + Injectable, + VERSION_NEUTRAL, +} from '@nestjs/common'; +import type { ILogger } from 'src/core/application/_shared/logger/ILogger'; +import { PrismaService } from 'src/infra/database/prisma/prisma.service'; + +@Controller({ + path: 'health', + version: VERSION_NEUTRAL, +}) +@Injectable() +export class HealthController { + + constructor( + private readonly prisma: PrismaService, + @Inject('ILogger') private readonly logger: ILogger + ) { } + + @Get() + health() { + return { + statusCode: HttpStatus.OK, + status: 'ok', + service: 'venue-booking-api', + timestamp: new Date().toISOString(), + uptime: process.uptime(), + }; + } + + @Get('live') + liveness() { + return { + statusCode: HttpStatus.OK, + status: 'alive', + timestamp: new Date().toISOString(), + }; + } + + @Get('ready') + async readiness() { + // TODO: + // - Check database connection + // - Check Redis + // - Check RabbitMQ/Kafka + // Throw ServiceUnavailableException if any dependency is unavailable. + let databaseUP = false + + try { + databaseUP = !!(await this.prisma.$queryRaw`select 1 `) + } catch (error) { + // @ts-ignore + this.logger.error('Database connection error ,', error?.stack, error) + } + + return { + statusCode: HttpStatus.OK, + status: 'ready', + timestamp: new Date().toISOString(), + checks: { + database: databaseUP ? 'up' : 'down', + }, + }; + } +} \ No newline at end of file diff --git a/backend/src/presentation/modules/payment/dto/payment.dto.ts b/backend/src/presentation/modules/payment/dto/payment.dto.ts new file mode 100644 index 000000000..80d2fbdaa --- /dev/null +++ b/backend/src/presentation/modules/payment/dto/payment.dto.ts @@ -0,0 +1,23 @@ +import { ApiProperty } from "@nestjs/swagger"; + +export class InitiatePaymentDto { + + @ApiProperty() + bookingId!: string + + @ApiProperty() + customerPhone!: string +} + +export class VerifyPaymentDto { + + @ApiProperty() + providerOrderId!: string; + + @ApiProperty() + providerPaymentId!: string; + + @ApiProperty() + signature!: string; + +} \ No newline at end of file diff --git a/backend/src/presentation/modules/payment/payment.controller.ts b/backend/src/presentation/modules/payment/payment.controller.ts new file mode 100644 index 000000000..41b357fad --- /dev/null +++ b/backend/src/presentation/modules/payment/payment.controller.ts @@ -0,0 +1,44 @@ +import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { CurrentUser } from '../../decorators/current-user.decorator'; +import { type TokenPayload } from '../../../core/application/users/services/token.interface'; +import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse } from '@nestjs/swagger'; +import { RolesGuard } from 'src/presentation/guards/roles.guard'; +import { InitiatePaymentCommandHandler } from 'src/core/application/payment/commands/initiate-payment.command'; +import { VerifyPaymentCommandHandler } from 'src/core/application/payment/commands/verify-payment.command'; +import { InitiatePaymentDto, VerifyPaymentDto } from './dto/payment.dto'; + +@ApiTags('payment') +@Controller({ + version: '1', + path: 'payment', +}) +@UseGuards(JwtAuthGuard, RolesGuard) +@ApiBearerAuth('JWT-auth') +export class PaymentController { + constructor( + private readonly verifyPaymentCommand: VerifyPaymentCommandHandler, + private readonly initiatePaymentCommand: InitiatePaymentCommandHandler, + ) { } + + @Post('initiate') + @ApiOperation({ summary: 'Initiate payment' }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) + adminDashboard( + @CurrentUser() user: TokenPayload, + @Body() data: InitiatePaymentDto + ) { + return this.initiatePaymentCommand.execute(data, user.userId); + } + + @Post('verify') + @ApiOperation({ summary: 'verify payment' }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) + ownerDashboard( + @CurrentUser() user: TokenPayload, + @Body() data: VerifyPaymentDto + ) { + return this.verifyPaymentCommand.execute(data, user.userId); + } + +} diff --git a/backend/src/presentation/modules/payment/payment.module.ts b/backend/src/presentation/modules/payment/payment.module.ts new file mode 100644 index 000000000..1bc2112a4 --- /dev/null +++ b/backend/src/presentation/modules/payment/payment.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { InfraModule } from '../../../infra/infra.module'; +import { PaymentController } from './payment.controller'; +import { InitiatePaymentCommandHandler } from 'src/core/application/payment/commands/initiate-payment.command'; +import { VerifyPaymentCommandHandler } from 'src/core/application/payment/commands/verify-payment.command'; + +@Module({ + imports: [InfraModule], + controllers: [PaymentController], + providers: [InitiatePaymentCommandHandler, VerifyPaymentCommandHandler, JwtAuthGuard], +}) +export class PaymentModule { } diff --git a/backend/src/presentation/modules/users/dto/create-user.dto.ts b/backend/src/presentation/modules/users/dto/create-user.dto.ts new file mode 100644 index 000000000..0311be138 --- /dev/null +++ b/backend/src/presentation/modules/users/dto/create-user.dto.ts @@ -0,0 +1 @@ +export class CreateUserDto {} diff --git a/backend/src/presentation/modules/users/dto/update-user.dto.ts b/backend/src/presentation/modules/users/dto/update-user.dto.ts new file mode 100644 index 000000000..78ab602d8 --- /dev/null +++ b/backend/src/presentation/modules/users/dto/update-user.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateUserDto } from './create-user.dto'; + +export class UpdateUserDto extends PartialType(CreateUserDto) {} diff --git a/backend/src/presentation/modules/users/users.controller.ts b/backend/src/presentation/modules/users/users.controller.ts new file mode 100644 index 000000000..8f3fa56b8 --- /dev/null +++ b/backend/src/presentation/modules/users/users.controller.ts @@ -0,0 +1,51 @@ +import { Controller, Get, Param, UseGuards } from '@nestjs/common'; +import { GetUserProfileQuery } from '../../../core/application/users/queries/get-user-profile.query'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { CurrentUser } from '../../decorators/current-user.decorator'; +import { type TokenPayload } from '../../../core/application/users/services/token.interface'; +import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse } from '@nestjs/swagger'; +import { RolesGuard } from 'src/presentation/guards/roles.guard'; +import { Roles } from 'src/presentation/decorators/roles.decorator'; +import { UserRole } from 'src/core/domain/_shared/enum/UserRole'; +import { ListUsersQuery } from 'src/core/application/users/queries/list-users.query'; + +@ApiTags('users') +@Controller({ + version: '1', + path: 'users', +}) +@UseGuards(JwtAuthGuard, RolesGuard) +@ApiBearerAuth('JWT-auth') +export class UsersController { + constructor( + private readonly getUserProfileQuery: GetUserProfileQuery, + private readonly listUsersQuery: ListUsersQuery, + ) { } + + @Get() + @Roles(UserRole.ADMIN) + @ApiOperation({ summary: 'Get all users (admin only)' }) + @ApiResponse({ status: 200, description: 'List of users' }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) + listUsers(@CurrentUser() user: TokenPayload) { + return this.listUsersQuery.execute(); + } + + @Get('me') + @ApiOperation({ summary: 'Get current user profile' }) + @ApiResponse({ status: 200, description: 'Profile found' }) + @ApiResponse({ status: 401, description: 'Unauthorized' }) + getMe(@CurrentUser() user: TokenPayload) { + return this.getUserProfileQuery.execute(user.userId); + } + + @Get(':id') + @Roles(UserRole.ADMIN) + @ApiOperation({ summary: 'Get user profile by ID (admin only)' }) + @ApiResponse({ status: 200, description: 'Profile found' }) + @ApiResponse({ status: 404, description: 'User not found' }) + findOne(@Param('id') id: string) { + return this.getUserProfileQuery.execute(id); + } + +} diff --git a/backend/src/presentation/modules/users/users.module.ts b/backend/src/presentation/modules/users/users.module.ts new file mode 100644 index 000000000..7af98d89c --- /dev/null +++ b/backend/src/presentation/modules/users/users.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { UsersController } from './users.controller'; +import { GetUserProfileQuery } from '../../../core/application/users/queries/get-user-profile.query'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { InfraModule } from '../../../infra/infra.module'; +import { ListUsersQuery } from 'src/core/application/users/queries/list-users.query'; + +@Module({ + imports: [InfraModule], + controllers: [UsersController], + providers: [GetUserProfileQuery, ListUsersQuery, JwtAuthGuard], +}) +export class UsersModule { } diff --git a/backend/src/presentation/modules/venues/dto/approve-venue.dto.ts b/backend/src/presentation/modules/venues/dto/approve-venue.dto.ts new file mode 100644 index 000000000..f9acafc08 --- /dev/null +++ b/backend/src/presentation/modules/venues/dto/approve-venue.dto.ts @@ -0,0 +1,6 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class ApproveVenueDto { + @ApiProperty() + approve!: boolean; +} diff --git a/backend/src/presentation/modules/venues/dto/create-venue.dto.ts b/backend/src/presentation/modules/venues/dto/create-venue.dto.ts new file mode 100644 index 000000000..00382fea3 --- /dev/null +++ b/backend/src/presentation/modules/venues/dto/create-venue.dto.ts @@ -0,0 +1,42 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; + +export class CreateVenueDto { + @ApiProperty({ example: 'Grand Ballroom' }) + title!: string; + + @ApiProperty({ example: 'A beautiful ballroom for your special event' }) + description!: string; + + @ApiProperty({ example: 'Conference Hall' }) + venueType!: string; + + @ApiProperty({ example: '123 Main Street' }) + addressLine1!: string; + + @ApiProperty({ example: 'Calicut' }) + city!: string; + + @ApiProperty({ example: 'KOK' }) + state!: string; + + @ApiProperty({ example: 'IND' }) + country!: string; + + @ApiProperty({ example: '676305' }) + postalCode!: string; + + @ApiPropertyOptional({ example: 11.258753 }) + latitude?: number; + + @ApiPropertyOptional({ example: 75.780411 }) + longitude?: number; + + @ApiProperty({ example: 100 }) + capacity!: number; + + @ApiProperty({ example: 500 }) + pricePerDay!: number; + + @ApiProperty({ example: ['AC', 'WiFi'] }) + amenities!: string[]; +} diff --git a/backend/src/presentation/modules/venues/dto/search-pagination.dto.ts b/backend/src/presentation/modules/venues/dto/search-pagination.dto.ts new file mode 100644 index 000000000..19987bd6f --- /dev/null +++ b/backend/src/presentation/modules/venues/dto/search-pagination.dto.ts @@ -0,0 +1,23 @@ +import { ApiProperty } from "@nestjs/swagger" + + +export class SearchPaginationDto { + @ApiProperty() + limit: number = 10 + + @ApiProperty() + offset: number = 0 + + @ApiProperty() + search?: string + + @ApiProperty() + city?: string + + @ApiProperty() + venueType?: string + + @ApiProperty() + capacity?: number + +} \ No newline at end of file diff --git a/backend/src/presentation/modules/venues/venues.controller.ts b/backend/src/presentation/modules/venues/venues.controller.ts new file mode 100644 index 000000000..33fea7440 --- /dev/null +++ b/backend/src/presentation/modules/venues/venues.controller.ts @@ -0,0 +1,120 @@ +import { Controller, Get, Post, Body, Param, Query, UseGuards, UseInterceptors, ParseUUIDPipe, UploadedFiles } from '@nestjs/common'; +import { CreateVenueCommand } from '../../../core/application/venues/commands/create-venue.command'; +import { SearchVenuesQuery } from '../../../core/application/venues/queries/search-venues.query'; +import { GetVenueDetailsQuery } from '../../../core/application/venues/queries/get-venue-details.query'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { CurrentUser } from '../../decorators/current-user.decorator'; +import { type TokenPayload } from '../../../core/application/users/services/token.interface'; +import { ZodValidationPipe } from '../../pipes/zod-validation.pipe'; +import { createVenueSchema } from '../../validation/venues/create-venue.schema'; +import { CreateVenueDto } from './dto/create-venue.dto'; +import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse, ApiQuery, ApiConsumes, ApiBody } from '@nestjs/swagger'; +import { FindMyVenuesQuery } from 'src/core/application/venues/queries/find-my-venues.query'; +import { RolesGuard } from 'src/presentation/guards/roles.guard'; +import { Roles } from 'src/presentation/decorators/roles.decorator'; +import { UserRole } from 'src/core/domain/_shared/enum/UserRole'; +import { FilesInterceptor } from '@nestjs/platform-express'; +import { UploadVenueImagesCommand } from 'src/core/application/venues/commands/upload-venue-images.command'; +import { Express } from 'express' +import type { SearchPaginationDto } from './dto/search-pagination.dto'; +import { searchPaginationSchema } from 'src/presentation/validation/venues/search-pagination'; + +@ApiTags('venues') +@Controller({ + version: '1', + path: 'venues', +}) +@ApiBearerAuth('JWT-auth') +export class VenuesController { + constructor( + private readonly createVenueCommand: CreateVenueCommand, + private readonly searchVenuesQuery: SearchVenuesQuery, + private readonly getVenueDetailsQuery: GetVenueDetailsQuery, + private readonly findMyVenuesQuery: FindMyVenuesQuery, + private readonly uploadVenueImageCommand: UploadVenueImagesCommand + ) { } + + @Post() + @UseGuards(JwtAuthGuard, RolesGuard) + @Roles(UserRole.VENUE_OWNER) + @ApiBearerAuth() + @ApiOperation({ summary: 'Create a new venue' }) + @ApiResponse({ status: 201, description: 'Venue created successfully' }) + create( + @CurrentUser() user: TokenPayload, + @Body(new ZodValidationPipe(createVenueSchema as any)) data: CreateVenueDto, + ) { + return this.createVenueCommand.execute({ + ownerId: user.userId, + ...data, + }); + } + + @Get() + @ApiOperation({ summary: 'Search and filter venues' }) + @ApiQuery({ name: 'city', required: false }) + @ApiQuery({ name: 'venueType', required: false }) + @ApiQuery({ name: 'capacity', required: false, type: Number }) + findAll(@Query(new ZodValidationPipe(searchPaginationSchema)) query: SearchPaginationDto) { + return this.searchVenuesQuery.execute(query); + } + + @Post(':venueId/images') + @UseGuards(JwtAuthGuard, RolesGuard) + @Roles(UserRole.VENUE_OWNER) + @UseInterceptors( + FilesInterceptor( + 'files', + 10, + ), + ) + @ApiOperation({ summary: 'Venue images upload api' }) + @ApiConsumes('multipart/form-data') + @ApiBody({ + schema: { + type: 'object', + properties: { + files: { + type: 'array', + items: { + type: 'string', + format: 'binary', + }, + }, + }, + }, + }) + async uploadVenueImages( + @Param('venueId', ParseUUIDPipe,) venueId: string, + // @ts-expect-error docker and typescript issue + @UploadedFiles() files: Express.Multer.File[], + @CurrentUser() user: TokenPayload + ) { + + return this.uploadVenueImageCommand.execute({ + ownerId: user.userId, + venueId, + files: files.map(file => ({ + buffer: file.buffer, + fileName: file.originalname + })) + }) + } + + @Get('my-venues') + @UseGuards(JwtAuthGuard, RolesGuard) + @Roles(UserRole.VENUE_OWNER) + @ApiOperation({ summary: 'Get the list of all venues created by owner' }) + findMyVenues(@CurrentUser() user: TokenPayload) { + return this.findMyVenuesQuery.execute(user.userId); + } + + @Get(':id') + @ApiOperation({ summary: 'Get details of a specific venue by ID' }) + @ApiResponse({ status: 200, description: 'Venue found' }) + @ApiResponse({ status: 404, description: 'Venue not found' }) + findOne(@Param('id') id: string) { + return this.getVenueDetailsQuery.execute(id); + } + +} diff --git a/backend/src/presentation/modules/venues/venues.module.ts b/backend/src/presentation/modules/venues/venues.module.ts new file mode 100644 index 000000000..1ee5da99b --- /dev/null +++ b/backend/src/presentation/modules/venues/venues.module.ts @@ -0,0 +1,25 @@ +import { Module } from '@nestjs/common'; +import { VenuesController } from './venues.controller'; +import { CreateVenueCommand } from '../../../core/application/venues/commands/create-venue.command'; +import { SearchVenuesQuery } from '../../../core/application/venues/queries/search-venues.query'; +import { GetVenueDetailsQuery } from '../../../core/application/venues/queries/get-venue-details.query'; +import { FindMyVenuesQuery } from '../../../core/application/venues/queries/find-my-venues.query'; +import { JwtAuthGuard } from '../../guards/jwt-auth.guard'; +import { RolesGuard } from '../../guards/roles.guard'; +import { InfraModule } from '../../../infra/infra.module'; +import { UploadVenueImagesCommand } from 'src/core/application/venues/commands/upload-venue-images.command'; + +@Module({ + imports: [InfraModule], + controllers: [VenuesController], + providers: [ + FindMyVenuesQuery, + CreateVenueCommand, + SearchVenuesQuery, + GetVenueDetailsQuery, + UploadVenueImagesCommand, + JwtAuthGuard, + RolesGuard, + ], +}) +export class VenuesModule { } diff --git a/backend/src/presentation/pipes/zod-validation.pipe.ts b/backend/src/presentation/pipes/zod-validation.pipe.ts new file mode 100644 index 000000000..799c89f66 --- /dev/null +++ b/backend/src/presentation/pipes/zod-validation.pipe.ts @@ -0,0 +1,19 @@ +import { + type PipeTransform, + type ArgumentMetadata, + BadRequestException, +} from '@nestjs/common'; +import { type ZodObject, type ZodError } from 'zod'; + +export class ZodValidationPipe implements PipeTransform { + constructor(private schema: ZodObject) {} + + transform(value: unknown, metadata: ArgumentMetadata) { + try { + const parsedValue = this.schema.parse(value); + return parsedValue; + } catch (error) { + throw new BadRequestException(error); + } + } +} diff --git a/backend/src/presentation/validation/auth/login.schema.ts b/backend/src/presentation/validation/auth/login.schema.ts new file mode 100644 index 000000000..0a127c1bf --- /dev/null +++ b/backend/src/presentation/validation/auth/login.schema.ts @@ -0,0 +1,6 @@ +import z from 'zod'; + +export const loginSchema = z.object({ + email: z.email(), + password: z.string().min(6), +}); diff --git a/backend/src/presentation/validation/auth/refresh-token.schema.ts b/backend/src/presentation/validation/auth/refresh-token.schema.ts new file mode 100644 index 000000000..4a9a9e5fd --- /dev/null +++ b/backend/src/presentation/validation/auth/refresh-token.schema.ts @@ -0,0 +1,5 @@ +import z from 'zod'; + +export const refreshTokenSchema = z.object({ + refreshToken: z.string().min(1), +}); diff --git a/backend/src/presentation/validation/auth/register.schema.ts b/backend/src/presentation/validation/auth/register.schema.ts new file mode 100644 index 000000000..39c122100 --- /dev/null +++ b/backend/src/presentation/validation/auth/register.schema.ts @@ -0,0 +1,10 @@ +import z from 'zod'; + +export const registerSchema = z.object({ + email: z.string().email(), + password: z.string().min(6), + firstName: z.string().min(1), + lastName: z.string().optional().nullable(), + phone: z.string().optional().nullable(), + role: z.enum(['USER', 'VENUE_OWNER', 'ADMIN']).optional(), +}); diff --git a/backend/src/presentation/validation/bookings/create-booking.schema.ts b/backend/src/presentation/validation/bookings/create-booking.schema.ts new file mode 100644 index 000000000..e36b3cdf1 --- /dev/null +++ b/backend/src/presentation/validation/bookings/create-booking.schema.ts @@ -0,0 +1,8 @@ +import z from 'zod'; + +export const createBookingSchema = z.object({ + venueId: z.string().uuid(), + startDate: z.coerce.date(), + endDate: z.coerce.date(), + guestsCount: z.number().int().positive(), +}); diff --git a/backend/src/presentation/validation/venues/create-venue.schema.ts b/backend/src/presentation/validation/venues/create-venue.schema.ts new file mode 100644 index 000000000..d73698737 --- /dev/null +++ b/backend/src/presentation/validation/venues/create-venue.schema.ts @@ -0,0 +1,16 @@ +import z from 'zod'; + +export const createVenueSchema = z.object({ + title: z.string().min(1), + description: z.string().min(1), + venueType: z.string().min(1), + addressLine1: z.string().min(1), + city: z.string().min(1), + state: z.string().min(1), + country: z.string().min(1), + postalCode: z.string().min(1), + latitude: z.number().optional().nullable(), + longitude: z.number().optional().nullable(), + capacity: z.number().int().positive(), + pricePerDay: z.number().positive(), +}); diff --git a/backend/src/presentation/validation/venues/search-pagination.ts b/backend/src/presentation/validation/venues/search-pagination.ts new file mode 100644 index 000000000..13228b10d --- /dev/null +++ b/backend/src/presentation/validation/venues/search-pagination.ts @@ -0,0 +1,38 @@ +import { z } from 'zod'; + +export const searchPaginationSchema = z.object({ + limit: z.coerce + .number() + .int() + .positive() + .max(100) + .default(10), + + offset: z.coerce + .number() + .int() + .min(0) + .default(0), + + search: z.string() + .trim() + .optional(), + + city: z.string() + .trim() + .optional(), + + venueType: z.string() + .trim() + .optional(), + + capacity: z.coerce + .number() + .int() + .positive() + .optional(), +}); + +export type SearchPaginationDto = z.infer< + typeof searchPaginationSchema +>; \ No newline at end of file diff --git a/backend/test/app.e2e-spec.ts b/backend/test/app.e2e-spec.ts new file mode 100644 index 000000000..3cd5fca63 --- /dev/null +++ b/backend/test/app.e2e-spec.ts @@ -0,0 +1,29 @@ +import { Test, type TestingModule } from '@nestjs/testing'; +import { type INestApplication } from '@nestjs/common'; +import request from 'supertest'; +import { type App } from 'supertest/types'; +import { AppModule } from './../src/presentation/app.module'; + +describe('AppController (e2e)', () => { + let app: INestApplication; + + beforeEach(async () => { + const moduleFixture: TestingModule = await Test.createTestingModule({ + imports: [AppModule], + }).compile(); + + app = moduleFixture.createNestApplication(); + await app.init(); + }); + + it('/ (GET)', () => { + return request(app.getHttpServer()) + .get('/') + .expect(200) + .expect('Hello World!'); + }); + + afterEach(async () => { + await app.close(); + }); +}); diff --git a/backend/test/jest-e2e.json b/backend/test/jest-e2e.json new file mode 100644 index 000000000..e9d912f3e --- /dev/null +++ b/backend/test/jest-e2e.json @@ -0,0 +1,9 @@ +{ + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": ".", + "testEnvironment": "node", + "testRegex": ".e2e-spec.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + } +} diff --git a/backend/tsconfig.build.json b/backend/tsconfig.build.json new file mode 100644 index 000000000..64f86c6bd --- /dev/null +++ b/backend/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/backend/tsconfig.json b/backend/tsconfig.json new file mode 100644 index 000000000..138682de5 --- /dev/null +++ b/backend/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "module": "nodenext", + "moduleResolution": "nodenext", + "resolvePackageJsonExports": true, + "esModuleInterop": true, + "isolatedModules": true, + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "ES2023", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true, + "strictNullChecks": true, + "forceConsistentCasingInFileNames": true, + "noImplicitAny": false, + "strictBindCallApply": false, + "noFallthroughCasesInSwitch": false, + "types": [ + "node", + // "Multer" + ] + }, + "watchOptions": { + "watchFile": "fixedPollingInterval" + } +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..11f1a524d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +services: + backend: + image: ${BACKEND_IMAGE} + container_name: ${BACKEND_CONTAINER_NAME} + restart: unless-stopped + environment: + DATABASE_URL: ${DATABASE_URL} + BASE_URL: ${BASE_URL} + NODE_ENV: ${NODE_ENV} + JWT_SECRET: ${JWT_SECRET} + RAZORPAY_KEY_ID: ${RAZORPAY_KEY_ID} + RAZORPAY_SECRET: ${RAZORPAY_SECRET} + UPLOAD_DIR: ${UPLOAD_DIR} + ports: + - "${BACKEND_PORT}:3000" + volumes: + - uploads_data:${UPLOAD_DIR} + + frontend: + image: ${FRONTEND_IMAGE} + container_name: ${FRONTEND_CONTAINER_NAME} + restart: unless-stopped + depends_on: + - backend + ports: + - "${FRONTEND_PORT}:80" + +volumes: + uploads_data: \ No newline at end of file diff --git a/frontend/.dockerignore b/frontend/.dockerignore new file mode 100644 index 000000000..08654ff9d --- /dev/null +++ b/frontend/.dockerignore @@ -0,0 +1,8 @@ +node_modules +dist +.git +.gitignore +Dockerfile +docker-compose.yml +.vscode +.idea \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 000000000..ef34ba70e --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,38 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# dependencies +node_modules +.pnp +.pnp.js + +# testing +coverage + +# production +.next +.swc +_static +out +dist +build + +# environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# misc +.DS_Store +.vercel +.netlify +.vscode +tsconfig.tsbuildinfo +.ncurc.js +knip.jsonc diff --git a/frontend/.prettierignore b/frontend/.prettierignore new file mode 100644 index 000000000..34d65be44 --- /dev/null +++ b/frontend/.prettierignore @@ -0,0 +1,11 @@ +# Build directories +build/* +dist/* +public/* +**/out/* +**/.next/* +**/node_modules/* + +yarn.lock +package-lock.json +jsconfig.json diff --git a/frontend/CHANGELOG.md b/frontend/CHANGELOG.md new file mode 100644 index 000000000..3e97f622c --- /dev/null +++ b/frontend/CHANGELOG.md @@ -0,0 +1,106 @@ +### v3.0.0 + +###### Apr 3, 2025 + +- Support MUI v7. +- Support React v19. +- Support Eslint v9. +- Upgrade and restructure the directory. +- Upgrade some dependencies to the latest versions. + +--- + +### v2.0.0 + +###### Aug 24, 2024 + +- [New] Migrate to typescript. +- Upgrade and restructure the directory. +- Upgrade some dependencies to the latest versions. + +--- + +### v1.8.0 + +###### Wed 11, 2023 + +- [New] Migrate to vite.js. +- Upgrade and restructure the directory. +- Upgrade some dependencies to the latest versions + +--- + +### v1.7.0 + +###### Feb 21, 2023 + +- Upgrade some dependencies to the latest versions + +--- + +### v1.6.0 + +###### Oct 17, 2022 + +- Upgrade and restructure the directory. +- Upgrade some dependencies to the latest versions + +--- + +### v1.5.0 + +###### Jul 04, 2022 + +- Support react 18. +- Upgrade some dependencies to the latest versions + +--- + +### v1.4.0 + +###### Apr 12, 2022 + +- Update `src/components`. +- Update `src/sections`. +- Update `src/pages`. +- Update `src/layouts`. +- Update `src/theme`. +- Upgrade some dependencies to the latest versions + +--- + +### v1.3.0 + +###### Feb 21, 2022 + +- Support react-script v5.0.0 +- Source code improvement +- Upgrade some dependencies to the latest versions + +--- + +### v1.2.0 + +###### Sep 18, 2021 + +- Support MIU v5.0.0 official release +- Upgrade some dependencies to the latest versions +- Update `src/theme/typography.js` +- Upgrade some dependencies to the latest versions + +--- + +### v1.1.0 + +###### Jul 23, 2021 + +- Support MUI v5.0.0-beta.1 +- Upgrade some dependencies to the latest versions + +--- + +### v1.0.0 + +###### Jun 28, 2021 + +Initial release. diff --git a/frontend/Dockerfile b/frontend/Dockerfile new file mode 100644 index 000000000..4793cd13e --- /dev/null +++ b/frontend/Dockerfile @@ -0,0 +1,22 @@ +# ---------- Build Stage ---------- +FROM node:22-alpine AS builder + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci + +COPY . . + +RUN npm run build + + +# ---------- Production Stage ---------- +FROM nginx:alpine + +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=builder /app/dist /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/frontend/LICENSE.md b/frontend/LICENSE.md new file mode 100644 index 000000000..1274ba0ee --- /dev/null +++ b/frontend/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Minimal UI ([https://minimals.cc/](https://minimals.cc/)) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 000000000..bacb87d27 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,48 @@ +## Minimal UI ([Free version](https://free.minimals.cc/)) + +![license](https://img.shields.io/badge/license-MIT-blue.svg) + +![preview](public/assets/images/minimal-free-preview.jpg) + +> Free React Admin Dashboard made with Material-UI components and React + Vite.js. + +## Pages + +- [Dashboard](https://free.minimals.cc/) +- [Users](https://free.minimals.cc/user) +- [Products](https://free.minimals.cc/products) +- [Blog](https://free.minimals.cc/blog) +- [Sign in](https://free.minimals.cc/sign-in) +- [Not found](https://free.minimals.cc/404) + +## Quick start + +- Clone the repo: `git clone https://github.com/minimal-ui-kit/material-kit-react.git` +- Recommended: `Node.js v20.x` +- **Install:** `npm i` or `yarn install` +- **Start:** `npm run dev` or `yarn dev` +- **Build:** `npm run build` or `yarn build` +- Open browser: `http://localhost:3039` + +## Upgrade to PRO Version + +| Minimal Free | [Minimal Pro](https://material-ui.com/store/items/minimal-dashboard/) | +| :-------------------------- | :------------------------------------------------------------------------------------------------------ | +| **6** Pages | **70+** Pages | +| **Partial** theme customize | **Fully** theme customize | +| - | **Next.js** version | +| - | **TypeScript** version (Standard Plus and Extended license) | +| - | Design **Figma** file (Standard Plus and Extended license) | +| - | Authentication with **Amplify**, **Auth0**, **JWT**, **Firebase** and **Supabase** | +| - | Light/dark mode, right-to-left, form validation... ([+more components](https://minimals.cc/components)) | +| - | Complete users flows | +| - | 1 year of free updates / 6 months of technical support | +| - | Learn more: [Package & license](https://docs.minimals.cc/package) | + +## License + +Distributed under the [MIT](https://github.com/minimal-ui-kit/minimal.free/blob/main/LICENSE.md) license. + +## Contact us + +Email: support@minimals.cc diff --git a/frontend/agent.md b/frontend/agent.md new file mode 100644 index 000000000..540db7689 --- /dev/null +++ b/frontend/agent.md @@ -0,0 +1,285 @@ +# BookMyVenue Frontend Development Instructions + +You are working on the BookMyVenue frontend application. + +## Primary Goal + +Build a premium, modern, mobile-first venue discovery and booking experience for end users. + +The platform should feel closer to Airbnb, Booking.com, and Zomato rather than an admin dashboard. + +Focus on: + +* Venue discovery +* Venue browsing +* Venue booking +* User account management +* Mobile experience +* Conversion-focused UI + +--- + +## Critical Rules + +### Rule 1: Do NOT modify existing pages + +Never update, refactor, rename, move, delete, or alter existing pages unless explicitly instructed. + +Existing pages are considered stable. + +You may: + +* Read existing pages +* Reuse existing pages as reference +* Import existing components + +You may NOT: + +* Change layouts +* Change styles +* Change business logic +* Change routes +* Change API integrations + +--- + +### Rule 2: Do NOT modify existing components + +Never modify any existing component. + +If an existing component is not suitable: + +Create a new component instead. + +Examples: + +Good: + +* Create VenueCardV2 +* Create SearchHero +* Create VenueGallery + +Bad: + +* Edit existing Card component +* Modify existing Table component +* Update existing Layout component + +--- + +### Rule 3: Reuse when possible + +Before creating a new component: + +Check whether an existing component can be reused without modification. + +Reuse: + +* Buttons +* Inputs +* Form controls +* Typography +* Dialogs +* Loading states +* Empty states + +Only create new components when necessary. + +--- + +### Rule 4: Create new pages in isolated folders + +All newly created user-facing pages must be isolated. + +Example: + +src/sections/user/ +src/pages/user/ + +or + +src/features/user/ + +depending on existing architecture. + +Do not place new user pages inside admin or owner modules. + +--- + +### Rule 5: Preserve project architecture + +Follow existing project conventions: + +* Folder structure +* Naming conventions +* Import ordering +* API service usage +* React Query usage +* Form handling patterns +* MUI usage + +Do not introduce a new architecture. + +--- + +## UI Requirements + +### Design Style + +Premium Consumer Product + +Avoid: + +* Admin dashboard appearance +* Dense tables +* Large forms +* Enterprise styling + +Prefer: + +* Large images +* Spacious layouts +* Rounded cards +* Soft shadows +* Modern search experiences +* Mobile-first design + +--- + +### Theme Usage + +Use existing MUI theme. + +Must use: + +* Existing color palette +* Existing typography +* Existing spacing system +* Existing shadows + +Do not introduce custom theme systems. + +--- + +## Mobile First + +Every page must work well on: + +* Mobile +* Tablet +* Desktop + +Design mobile first. + +--- + +## User Pages To Build + +Priority Order: + +1. Landing Page +2. Search Page +3. Venue Details Page +4. Booking Flow +5. Booking Success Page +6. User Dashboard +7. My Bookings +8. Booking Details +9. Favorites +10. About Page +11. FAQ Page +12. Contact Page + +--- + +## Landing Page Sections + +* Hero Search Section +* Popular Categories +* Featured Venues +* How It Works +* Benefits +* Testimonials +* Become a Host CTA +* Footer + +--- + +## Search Page + +Features: + +* Search Bar +* Location Search +* Date Filter +* Capacity Filter +* Price Filter +* Category Filter +* Sorting +* Grid View +* Empty State +* Loading State + +--- + +## Venue Details Page + +Sections: + +* Image Gallery +* Venue Information +* Amenities +* Pricing +* Availability Calendar +* Reviews +* Similar Venues +* Sticky Booking Card + +--- + +## Booking Flow + +Multi-step flow: + +1. Venue Selection +2. Date Selection +3. Guest Information +4. Booking Review +5. Payment +6. Confirmation + +--- + +## Code Quality + +Always: + +* Use TypeScript +* Strong typing +* Functional components +* React Query for API calls +* Proper loading states +* Proper error states +* Skeleton loaders +* Responsive layouts + +Avoid: + +* any +* inline styles +* duplicated code +* hardcoded colors +* hardcoded spacing + +--- + +## Output Expectations + +When generating code: + +1. First explain folder structure. +2. List all files to be created. +3. Generate complete code. +4. Do not generate partial implementations. +5. Do not modify existing files unless explicitly requested. +6. If an existing file would normally need modification, create an alternative implementation instead and explain why. diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs new file mode 100644 index 000000000..fe7c17e1c --- /dev/null +++ b/frontend/eslint.config.mjs @@ -0,0 +1,194 @@ +import globals from 'globals'; +import eslintJs from '@eslint/js'; +import eslintTs from 'typescript-eslint'; +import reactPlugin from 'eslint-plugin-react'; +import importPlugin from 'eslint-plugin-import'; +import reactHooksPlugin from 'eslint-plugin-react-hooks'; +import perfectionistPlugin from 'eslint-plugin-perfectionist'; +import unusedImportsPlugin from 'eslint-plugin-unused-imports'; + +// ---------------------------------------------------------------------- + +/** + * @rules common + * from 'react', 'eslint-plugin-react-hooks'... + */ +const commonRules = () => ({ + ...reactHooksPlugin.configs.recommended.rules, + 'func-names': 1, + 'no-bitwise': 2, + 'no-unused-vars': 0, + 'object-shorthand': 1, + 'no-useless-rename': 1, + 'default-case-last': 2, + 'consistent-return': 2, + 'no-constant-condition': 1, + 'default-case': [2, { commentPattern: '^no default$' }], + 'lines-around-directive': [2, { before: 'always', after: 'always' }], + 'arrow-body-style': [2, 'as-needed', { requireReturnForObjectLiteral: false }], + // react + 'react/jsx-key': 0, + 'react/prop-types': 0, + 'react/display-name': 0, + 'react/no-children-prop': 0, + 'react/jsx-boolean-value': 2, + 'react/self-closing-comp': 2, + 'react/react-in-jsx-scope': 0, + 'react/jsx-no-useless-fragment': [1, { allowExpressions: true }], + 'react/jsx-curly-brace-presence': [2, { props: 'never', children: 'never' }], + // typescript + '@typescript-eslint/no-shadow': 2, + '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/no-empty-object-type': 0, + '@typescript-eslint/consistent-type-imports': 1, + '@typescript-eslint/no-unused-vars': [1, { args: 'none' }], +}); + +/** + * @rules import + * from 'eslint-plugin-import'. + */ +const importRules = () => ({ + ...importPlugin.configs.recommended.rules, + 'import/named': 0, + 'import/export': 0, + 'import/default': 0, + 'import/namespace': 0, + 'import/no-named-as-default': 0, + 'import/newline-after-import': 2, + 'import/no-named-as-default-member': 0, + 'import/no-cycle': [ + 0, // disabled if slow + { maxDepth: '∞', ignoreExternal: false, allowUnsafeDynamicCyclicDependency: false }, + ], +}); + +/** + * @rules unused imports + * from 'eslint-plugin-unused-imports'. + */ +const unusedImportsRules = () => ({ + 'unused-imports/no-unused-imports': 1, + 'unused-imports/no-unused-vars': [ + 0, + { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' }, + ], +}); + +/** + * @rules sort or imports/exports + * from 'eslint-plugin-perfectionist'. + */ +const sortImportsRules = () => { + const customGroups = { + mui: ['custom-mui'], + auth: ['custom-auth'], + hooks: ['custom-hooks'], + utils: ['custom-utils'], + types: ['custom-types'], + routes: ['custom-routes'], + sections: ['custom-sections'], + components: ['custom-components'], + }; + + return { + 'perfectionist/sort-named-imports': [1, { type: 'line-length', order: 'asc' }], + 'perfectionist/sort-named-exports': [1, { type: 'line-length', order: 'asc' }], + 'perfectionist/sort-exports': [ + 1, + { + order: 'asc', + type: 'line-length', + groupKind: 'values-first', + }, + ], + 'perfectionist/sort-imports': [ + 2, + { + order: 'asc', + ignoreCase: true, + type: 'line-length', + environment: 'node', + maxLineLength: undefined, + newlinesBetween: 'always', + internalPattern: ['^src/.+'], + groups: [ + 'style', + 'side-effect', + 'type', + ['builtin', 'external'], + customGroups.mui, + customGroups.routes, + customGroups.hooks, + customGroups.utils, + 'internal', + customGroups.components, + customGroups.sections, + customGroups.auth, + customGroups.types, + ['parent', 'sibling', 'index'], + ['parent-type', 'sibling-type', 'index-type'], + 'object', + 'unknown', + ], + customGroups: { + value: { + [customGroups.mui]: ['^@mui/.+'], + [customGroups.auth]: ['^src/auth/.+'], + [customGroups.hooks]: ['^src/hooks/.+'], + [customGroups.utils]: ['^src/utils/.+'], + [customGroups.types]: ['^src/types/.+'], + [customGroups.routes]: ['^src/routes/.+'], + [customGroups.sections]: ['^src/sections/.+'], + [customGroups.components]: ['^src/components/.+'], + }, + }, + }, + ], + }; +}; + +/** + * Custom ESLint configuration. + */ +export const customConfig = { + plugins: { + 'react-hooks': reactHooksPlugin, + 'unused-imports': unusedImportsPlugin, + perfectionist: perfectionistPlugin, + import: importPlugin, + }, + settings: { + // https://www.npmjs.com/package/eslint-import-resolver-typescript + ...importPlugin.configs.typescript.settings, + 'import/resolver': { + ...importPlugin.configs.typescript.settings['import/resolver'], + typescript: { + project: './tsconfig.json', + }, + }, + }, + rules: { + ...commonRules(), + ...importRules(), + ...unusedImportsRules(), + ...sortImportsRules(), + }, +}; + +// ---------------------------------------------------------------------- + +export default [ + { files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'] }, + { ignores: ['*', '!src/', '!eslint.config.*'] }, + { + languageOptions: { + globals: { ...globals.browser, ...globals.node }, + }, + settings: { react: { version: 'detect' } }, + }, + eslintJs.configs.recommended, + ...eslintTs.configs.recommended, + reactPlugin.configs.flat.recommended, + customConfig, +]; diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 000000000..efb687cbc --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,15 @@ + + + + + + + + Minimal UI Kit + + + +
+ + + diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 000000000..610bf3ac4 --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,16 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + } +} \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 000000000..277f35717 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,7739 @@ +{ + "name": "@minimal/material-kit-react", + "version": "3.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@minimal/material-kit-react", + "version": "3.0.0", + "dependencies": { + "@emotion/cache": "^11.14.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@fontsource-variable/dm-sans": "^5.2.5", + "@fontsource/barlow": "^5.2.5", + "@hookform/resolvers": "^5.4.0", + "@iconify/react": "^5.2.1", + "@mui/lab": "^7.0.0-beta.10", + "@mui/material": "^7.0.1", + "@novu/react": "^3.17.0", + "@tanstack/react-query": "^5.101.0", + "apexcharts": "^4.5.0", + "axios": "^1.18.0", + "dayjs": "^1.11.13", + "es-toolkit": "^1.34.1", + "minimal-shared": "^1.0.7", + "react": "^19.1.0", + "react-apexcharts": "^1.7.0", + "react-dom": "^19.1.0", + "react-hook-form": "^7.79.0", + "react-router-dom": "^7.4.1", + "simplebar-react": "^3.3.0", + "zod": "^4.4.3" + }, + "devDependencies": { + "@eslint/js": "^9.23.0", + "@types/node": "^22.14.0", + "@types/react": "^19.1.0", + "@types/react-dom": "^19.1.1", + "@typescript-eslint/parser": "^8.29.0", + "@vitejs/plugin-react-swc": "^3.8.1", + "eslint": "^9.23.0", + "eslint-import-resolver-typescript": "^4.3.1", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-perfectionist": "^4.11.0", + "eslint-plugin-react": "^7.37.4", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-unused-imports": "^4.1.4", + "globals": "^16.0.0", + "prettier": "^3.5.3", + "typescript": "^5.8.2", + "typescript-eslint": "^8.29.0", + "vite": "^6.2.5", + "vite-plugin-checker": "^0.9.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@corvu/utils": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@corvu/utils/-/utils-0.4.2.tgz", + "integrity": "sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.6.11" + }, + "peerDependencies": { + "solid-js": "^1.8" + } + }, + "node_modules/@emnapi/core": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.0.tgz", + "integrity": "sha512-H+N/FqT07NmLmt6OFFtDfwe8PNygprzBikrEMyQfgqSmT0vzE515Pz7R8izwB9q/zsH/MA64AKoul3sA6/CzVg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.0.tgz", + "integrity": "sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", + "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz", + "integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "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/eslint-utils/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-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.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "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.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "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.1", + "minimatch": "^3.1.5", + "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/eslintrc/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "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.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@fontsource-variable/dm-sans": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@fontsource-variable/dm-sans/-/dm-sans-5.2.5.tgz", + "integrity": "sha512-ynWdb1Ncn5ywUOE6OkTsvgjkiZKj+xM/GS2iVE47MBvS3AlfOSyOy3xynfkQsM3ngaxdCamT/06hZGAgPmao0A==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, + "node_modules/@fontsource/barlow": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@fontsource/barlow/-/barlow-5.2.5.tgz", + "integrity": "sha512-p+2XXEM7v85kbn0Dh8g0YLMjTCDiRCAi9nHik6w/2owZ9CkT1yYGGgaUMshJRqykh7efv1gE0QxAkOhZHd8tEg==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, + "node_modules/@hookform/resolvers": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.4.0.tgz", + "integrity": "sha512-EIsqr/t/qbinPIhGjMdtvutIN1Kk4uwbROE9/UQ93CAVGR7GkA7Y92+fX80OzXi/OB67jVFYwKGO1WzkxmkFZw==", + "license": "MIT", + "dependencies": { + "@standard-schema/utils": "^0.3.0" + }, + "peerDependencies": { + "react-hook-form": "^7.55.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.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "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.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@iconify/react": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@iconify/react/-/react-5.2.1.tgz", + "integrity": "sha512-37GDR3fYDZmnmUn9RagyaX+zca24jfVOMY8E1IXTqJuE8pxNtN51KWPQe3VODOWvuUurq7q9uUu3CFrpqj5Iqg==", + "license": "MIT", + "dependencies": { + "@iconify/types": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/cyberalien" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@internationalized/number": { + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.7.tgz", + "integrity": "sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kobalte/core": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/@kobalte/core/-/core-0.13.12.tgz", + "integrity": "sha512-aumsbsPe99/z2igcX2+p+Mdhzw89uuZx8ZdgfEqSlVuuWeTvkoBtCId5sl/Y7sWvllIOFwPoMzE3u0rAzDNkvg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.5.1", + "@internationalized/number": "^3.2.1", + "@kobalte/utils": "^0.9.2", + "@solid-primitives/props": "^3.1.8", + "@solid-primitives/resize-observer": "^2.0.26", + "solid-presence": "^0.1.8", + "solid-prevent-scroll": "^0.1.4" + }, + "peerDependencies": { + "solid-js": "^1.8.15" + } + }, + "node_modules/@kobalte/utils": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@kobalte/utils/-/utils-0.9.2.tgz", + "integrity": "sha512-jRVXr+zsVHxzDXRoh+CDeXzvCsFJ6uiHhqqNQ26Cw9ZsZ3D6nqPUBt1gGVtj2ZPmRL3a9Uk1v8D1aJ8/I12Dow==", + "license": "MIT", + "dependencies": { + "@solid-primitives/event-listener": "^2.2.14", + "@solid-primitives/keyed": "^1.2.0", + "@solid-primitives/map": "^0.4.7", + "@solid-primitives/media": "^2.2.4", + "@solid-primitives/props": "^3.1.8", + "@solid-primitives/refs": "^1.0.5", + "@solid-primitives/utils": "^6.2.1" + }, + "peerDependencies": { + "solid-js": "^1.8.8" + } + }, + "node_modules/@motionone/animation": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz", + "integrity": "sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==", + "license": "MIT", + "dependencies": { + "@motionone/easing": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz", + "integrity": "sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==", + "license": "MIT", + "dependencies": { + "@motionone/animation": "^10.18.0", + "@motionone/generators": "^10.18.0", + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz", + "integrity": "sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==", + "license": "MIT", + "dependencies": { + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz", + "integrity": "sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==", + "license": "MIT", + "dependencies": { + "@motionone/types": "^10.17.1", + "@motionone/utils": "^10.18.0", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.17.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz", + "integrity": "sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==", + "license": "MIT" + }, + "node_modules/@motionone/utils": { + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz", + "integrity": "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==", + "license": "MIT", + "dependencies": { + "@motionone/types": "^10.17.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.0.1.tgz", + "integrity": "sha512-T5DNVnSD9pMbj4Jk/Uphz+yvj9dfpl2+EqsOuJtG12HxEihNG5pd3qzX5yM1Id4dDwKRvM3dPVcxyzavTFhJeA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/lab": { + "version": "7.0.0-beta.10", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-7.0.0-beta.10.tgz", + "integrity": "sha512-ide9oABYRAvJAFtxjc+bAaeAR74yVZ4avV7Ffj/D5CbbgSp/d5ns9SQtuWIZ7oJ3S7l1fcR06dj8EZuPRTmo8A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10", + "@mui/system": "^7.0.1", + "@mui/types": "^7.4.0", + "@mui/utils": "^7.0.1", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": "^7.0.1", + "@mui/material-pigment-css": "^7.0.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.0.1.tgz", + "integrity": "sha512-tQwjIIsn/UUSCHoCIQVkANuLua67h7Ro9M9gIHoGWaFbJFuF6cSO4Oda2olDVqIs4SWG+PaDChuu6SngxsaoyQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10", + "@mui/core-downloads-tracker": "^7.0.1", + "@mui/system": "^7.0.1", + "@mui/types": "^7.4.0", + "@mui/utils": "^7.0.1", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.0.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.0.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/private-theming": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.0.1.tgz", + "integrity": "sha512-1kQ7REYjjzDukuMfTbAjm3pLEhD7gUMC2bWhg9VD6f6sHzyokKzX0XHzlr3IdzNWBjPytGkzHpPIRQrUOoPLCQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10", + "@mui/utils": "^7.0.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.0.1.tgz", + "integrity": "sha512-BeGe4xZmF7tESKhmctYrL54Kl25kGHPKVdZYM5qj5Xz76WM/poY+d8EmAqUesT6k2rbJWPp2gtOAXXinNCGunQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.0.1.tgz", + "integrity": "sha512-pK+puz0hRPHEKGlcPd80mKYD3jpyi0uVIwWffox1WZgPTQMw2dCKLcD+9ndMDJADnrKzmKlpoH756PPFh2UvWA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10", + "@mui/private-theming": "^7.0.1", + "@mui/styled-engine": "^7.0.1", + "@mui/types": "^7.4.0", + "@mui/utils": "^7.0.1", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.0.tgz", + "integrity": "sha512-TxJ4ezEeedWHBjOmLtxI203a9DII9l4k83RXmz1PYSAmnyEcK2PglTNmJGxswC/wM5cdl9ap2h8lnXvt2swAGQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-SJKrrebNpmK9rJCnVL29nGPhPXQYtBZmb7Dsp0f58uIUhQfAKcBXHE4Kjs06SX4CwqeCuwEVgcHY+MgAO6XQ/g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.26.10", + "@mui/types": "^7.4.0", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.8.tgz", + "integrity": "sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.0", + "@emnapi/runtime": "^1.4.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "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/@novu/js": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@novu/js/-/js-3.17.0.tgz", + "integrity": "sha512-vZkGBROVwiIceengZlZyqeUisBVzvHCS99WqR763ki+qQFxjAMSRIMIWX+shU6EIjUPGhXR4OjLV6ob/4bN63Q==", + "license": "ISC", + "dependencies": { + "@floating-ui/dom": "^1.6.13", + "@kobalte/core": "^0.13.10", + "@types/json-logic-js": "^2.0.8", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.1", + "event-target-polyfill": "^0.0.4", + "mitt": "^3.0.1", + "partysocket": "^1.1.4", + "socket.io-client": "4.7.2", + "solid-floating-ui": "^0.3.1", + "solid-js": "^1.9.4", + "solid-motionone": "^1.0.3", + "tailwind-merge": "^2.4.0" + } + }, + "node_modules/@novu/react": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@novu/react/-/react-3.17.0.tgz", + "integrity": "sha512-9DdDxJo24mNx5xPETgi4yWVNJcI8MigQlwWrjLg2ySvm5SnBkUbIcz6kqjGtGhQ1NN3xiYNOHnIGrmKPMiic1A==", + "license": "ISC", + "dependencies": { + "@novu/js": "3.17.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-0", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.0.tgz", + "integrity": "sha512-IPIQ55ythEHkfEd9jMEi32OQ7SxURsGA43JI22lj01OLZNt2NUbJX8YUHxkVWyQ6daHPNn0truF5nSj3DQp6YQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.0.tgz", + "integrity": "sha512-M6s9cr10MibETyo8JsOkq+Lo1+lU6hcvb1MApnUql5qte/5hMEgzlN8/ReIKNfRV8rrqX50W1BX9zoUhC192RA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.0.tgz", + "integrity": "sha512-BqCoMoIbn0keKys+dEAdBa70EtOwV1bEsQCUgU9FdiZmmMge/Zk7LlkYGqbrdHR+Frnt0E1FOanly+rlwvvQzw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.0.tgz", + "integrity": "sha512-SIMzST3VFNXDAbeIWDWiFCNM5qncUBDWaEV7NfE7oZbDt2mgfW4MvbKdbYiGOLoM32gbTv608UMd0XktEYSD7w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.0.tgz", + "integrity": "sha512-ezjfSQMP7ArdUsbBwbQIfwAlhE84I2iVnzQNCFSveqV42q+BmKlzVpf7mxv5EchLcoWU4y6/heFzVg1F+hodUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.0.tgz", + "integrity": "sha512-9+qTWGW9AZRhnUgwtTwzNwcPlL87ngkeN0LA+q1bADvmY9aNvWaF2TFW8BZgnQPYxpDI7+rMVLivcd4V737TAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.0.tgz", + "integrity": "sha512-T1dMEQhXA/jkJ/jyMIw9IovK8bSUq7A8kLIlvZTb/6YIVsp2zLavr4F3oyllHWo7eIVJRyE5n3tUjQJEbE1IuQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.0.tgz", + "integrity": "sha512-2as0LgT7qQpyceQq6VUJYnumUMUrgGQCWIiDIN9DE0/tglsk6o66uCB4f3djRawAltvfCNLyZZrsqbPA6inCsA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.0.tgz", + "integrity": "sha512-bVURMg+6eNN9C/yc0aVjooZcwTTtYF4YW3xta5pP0//r3o1V8gXEHXWCndj47w/HhwsFroZrFhR+6uQP5T0n0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.0.tgz", + "integrity": "sha512-Ful8pM/2yYI83PViWdFdpZhdI8HJ5qsXANe5atypbHDf+KIBBDsZsbyy8hbXnULVvW9NsTh5DHwbcBftyLTfiw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.0.tgz", + "integrity": "sha512-9Gp/DgrkzfUBmNPVTyPTvay+4xEP7M/clXpj3efXBcm6uTIVIgDg4rqUpqKXvLEuFRVuEpSAOkhgNeecvaZ4Cg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.0.tgz", + "integrity": "sha512-m9tsJz54LUXkSYM8+8PG81B9IKK5r+2T0clMq4QrS16xFosufU7firBDAZEsDheDs7wTlP7h3++S7lMsU955HA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.0.tgz", + "integrity": "sha512-3UvJ5PNVU16aJf6M3tFI24pWzAl2/ynfbyRN3ICyQajK1lSkrnVYNnLz3v04J32qKa0FczJc22zeToc0lr2A3w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.0.tgz", + "integrity": "sha512-vRWUAbYLGHBZS6Q8Msb2sfnf1fvJf+47t8l/TwOerM2qArzy+IeNMTHrYLHXh95h8MoatPHI5hhSZNs+mGXKPg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.0.tgz", + "integrity": "sha512-c00T5SYENHAt86cfW47URaP3Us5vLC/4QO7GYud1G5VNRffCwwCuBspwqYrriuJB+5m0WFzClCn9wed0FBjKvg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.0.tgz", + "integrity": "sha512-krrCDilhXOwFkSkO3Wm9I/f9H0L92XHHwy2fwxjukxIbh0dem8gZqOW5Y8BsHrpJv5qwlRBV+Wl4ZFyRWhUpwg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.0.tgz", + "integrity": "sha512-7pfYFSTc4/rUC/FtAI0Qp6QthDBCIi6/AuP1xYqFk5vanI6KnL5dWKP60OM/05LOsbwTmIcvr6eXC4CJuJ75IA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.0.tgz", + "integrity": "sha512-7SDIalKeIpG0Ifogbbdn58HmSotYMlf23K3dCJEmiVd9Fg36Vmni82iPQec27N3wY4Bvbxftkxz6vSx9OcouTg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.0.tgz", + "integrity": "sha512-eRZevouTH2i1HeAVLqJuLnt256krQkGY0TN6WsTmsIhuzbh457HuWDMakKwmi0Cjadux983CoSr8Lim2QhUIFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.0.tgz", + "integrity": "sha512-3oVS7FLGa4U1qcvao9ylGxrjXZyUQqR8UwxEcnUEyPX53O/C/mKDZegNXTdHCP+h3e6ta/f1EN38Yif1mmZHYg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.0.tgz", + "integrity": "sha512-yTB9TgfWj5wHe5QgktAgXTLLot1gvEjl1NiPPAUiCs4oPrIWFl5V4nC3GrkNdj9LaAU4s94nVrGbGOCqUpyWsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.0.tgz", + "integrity": "sha512-5LOhoaesY3doG1c+ac/2JtgREpKoJr5bUHH8tKY0V8di7+uSV6BwLs2PlR0/yzefGOkR+wE7ZolZphHCsyG5Rw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.0.tgz", + "integrity": "sha512-yYkWHhmbhRTWTnWos5HC4GcPQfjlzzCNbM9e/+GXrLuaBXYA3qSDR9f0Vgufd5S8yX81U8jPKp7ZnAjZFMtRnw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.0.tgz", + "integrity": "sha512-SoTb6lPg25xZlA2ibwQ++ahCCnH+FP0qmEuafMJ4gznZKOlXioKEAeJLgCrqjM98ACziXM9V1amFjICVL4IFoA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.0.tgz", + "integrity": "sha512-5L+T1fMX4RIEBoZzT0+sQ0PhTS36NULFmMXtl1TZo44TMAROIMHbZufSOjVWt/Y622BtxgxtaNOokbTDvfsrZA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "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/@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/@solid-primitives/event-listener": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@solid-primitives/event-listener/-/event-listener-2.4.6.tgz", + "integrity": "sha512-5I0YJcTVYIWoMmgBSROBZGcz+ymhew/pGTg2dHW74BUjFKsV8Li4bOZYl0YAGP4mHw5o4UBd9/BEesqBci3wxw==", + "license": "MIT", + "dependencies": { + "@solid-primitives/utils": "^6.4.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/keyed": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@solid-primitives/keyed/-/keyed-1.5.3.tgz", + "integrity": "sha512-zNadtyYBhJSOjXtogkGHmRxjGdz9KHc8sGGVAGlUABkE8BED2tbIZoxkwSqzOwde8OcUEH0bb5DLZUWIMvyBSA==", + "license": "MIT", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/map": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/@solid-primitives/map/-/map-0.4.13.tgz", + "integrity": "sha512-B1zyFbsiTQvqPr+cuPCXO72sRuczG9Swncqk5P74NCGw1VE8qa/Ry9GlfI1e/VdeQYHjan+XkbE3rO2GW/qKew==", + "license": "MIT", + "dependencies": { + "@solid-primitives/trigger": "^1.1.0" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/media": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@solid-primitives/media/-/media-2.3.6.tgz", + "integrity": "sha512-pk49gPOq/UMRUJ+pTSrOfBiR8xJjRYHXIf1iR/jSnyQ/KroU+ZXhkZzavC7hvfp2vJeOTW5k2/HN0r3Q1VJ7Pw==", + "license": "MIT", + "dependencies": { + "@solid-primitives/event-listener": "^2.4.6", + "@solid-primitives/rootless": "^1.5.4", + "@solid-primitives/static-store": "^0.1.4", + "@solid-primitives/utils": "^6.4.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/props": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@solid-primitives/props/-/props-3.2.4.tgz", + "integrity": "sha512-MXXdvi2TSB6d+0N6ueA/HP1j/Kh9SEc4WdF1ZDMLwPagxW6pIHHSS9xbRO0RjqSVpNP4j0nxCWT1hx3CkJNhNA==", + "license": "MIT", + "dependencies": { + "@solid-primitives/utils": "^6.4.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/refs": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@solid-primitives/refs/-/refs-1.1.4.tgz", + "integrity": "sha512-bLjwIs6ZPu8NQnuw04sU3Zc8qKSpbc0umUU/O4SHf6oWOdO4+dHY8vb1T7C4b/Tg103+9WGr6sEE0+NFlbaB/A==", + "license": "MIT", + "dependencies": { + "@solid-primitives/utils": "^6.4.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/resize-observer": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@solid-primitives/resize-observer/-/resize-observer-2.1.6.tgz", + "integrity": "sha512-GFj6b81KIahl5SBf35VlyClHshDhVEREeZz2WYkHHKBvam66mE5H5f1g3EralabAAjmcU1bBd18YYYETPv0Knw==", + "license": "MIT", + "dependencies": { + "@solid-primitives/event-listener": "^2.4.6", + "@solid-primitives/rootless": "^1.5.4", + "@solid-primitives/static-store": "^0.1.4", + "@solid-primitives/utils": "^6.4.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/rootless": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@solid-primitives/rootless/-/rootless-1.5.4.tgz", + "integrity": "sha512-TOIZa1VUfVJ+9nkCcRajw3U4t9vBOP1HxX1WHNTbXq32mXwlqTvUnC4CRIilohcryBkT9u2ZkhUDSHRTaGp55g==", + "license": "MIT", + "dependencies": { + "@solid-primitives/utils": "^6.4.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/static-store": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@solid-primitives/static-store/-/static-store-0.1.4.tgz", + "integrity": "sha512-LgtVaVBtB7EbmS4+M0b8xY5Iq6pUWXBsIC4VgtrFKDGDdyCaDt88sHk0fUlx1Enxm/XZnZyLXJABRoa39RjJqA==", + "license": "MIT", + "dependencies": { + "@solid-primitives/utils": "^6.4.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/transition-group": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@solid-primitives/transition-group/-/transition-group-1.1.2.tgz", + "integrity": "sha512-gnHS0OmcdjeoHN9n7Khu8KNrOlRc8a2weETDt2YT6o1zeW/XtUC6Db3Q9pkMU/9cCKdEmN4b0a/41MKAHRhzWA==", + "license": "MIT", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/trigger": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@solid-primitives/trigger/-/trigger-1.2.4.tgz", + "integrity": "sha512-Ju0e+ZOD7hpOp7nptJimvDSZHWFvIvF9iBWMvuwt30smX7c5wmB8Kmc0AdDuv0wOTi06PQ1J5IrP1WJbH2yUBQ==", + "license": "MIT", + "dependencies": { + "@solid-primitives/utils": "^6.4.1" + }, + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@solid-primitives/utils": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.4.1.tgz", + "integrity": "sha512-ISSB5QX1qP2ynrheIpYwc4oKR5Ny4siNuUyf1qZniy+Il+p/PtDB0QK1Dnle8noiHpwRD3gpPdubOC3qI/Zamg==", + "license": "MIT", + "peerDependencies": { + "solid-js": "^1.6.12" + } + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@svgdotjs/svg.draggable.js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.6.tgz", + "integrity": "sha512-7iJFm9lL3C40HQcqzEfezK2l+dW2CpoVY3b77KQGqc8GXWa6LhhmX5Ckv7alQfUXBuZbjpICZ+Dvq1czlGx7gA==", + "license": "MIT", + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4" + } + }, + "node_modules/@svgdotjs/svg.filter.js": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.9.tgz", + "integrity": "sha512-/69XMRCDoam2HgC4ldHIaDgeQf1ViHIsa0Ld4uWgiXtZ+E24DWHe/9Ib6kbNiZ7WRIdlVokUDR1Fg0kjIpkfbw==", + "license": "MIT", + "dependencies": { + "@svgdotjs/svg.js": "^3.2.4" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@svgdotjs/svg.js": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.4.tgz", + "integrity": "sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Fuzzyma" + } + }, + "node_modules/@svgdotjs/svg.resize.js": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.resize.js/-/svg.resize.js-2.0.5.tgz", + "integrity": "sha512-4heRW4B1QrJeENfi7326lUPYBCevj78FJs8kfeDxn5st0IYPIRXoTtOSYvTzFWgaWWXd3YCDE6ao4fmv91RthA==", + "license": "MIT", + "engines": { + "node": ">= 14.18" + }, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4", + "@svgdotjs/svg.select.js": "^4.0.1" + } + }, + "node_modules/@svgdotjs/svg.select.js": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.select.js/-/svg.select.js-4.0.2.tgz", + "integrity": "sha512-5gWdrvoQX3keo03SCmgaBbD+kFftq0F/f2bzCbNnpkkvW6tk4rl4MakORzFuNjvXPWwB4az9GwuvVxQVnjaK2g==", + "license": "MIT", + "engines": { + "node": ">= 14.18" + }, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4" + } + }, + "node_modules/@swc/core": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.16.tgz", + "integrity": "sha512-wgjrJqVUss8Lxqilg0vkiE0tkEKU3mZkoybQM1Ehy+PKWwwB6lFAwKi20cAEFlSSWo8jFR8hRo19ZELAoLDowg==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.21" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.11.16", + "@swc/core-darwin-x64": "1.11.16", + "@swc/core-linux-arm-gnueabihf": "1.11.16", + "@swc/core-linux-arm64-gnu": "1.11.16", + "@swc/core-linux-arm64-musl": "1.11.16", + "@swc/core-linux-x64-gnu": "1.11.16", + "@swc/core-linux-x64-musl": "1.11.16", + "@swc/core-win32-arm64-msvc": "1.11.16", + "@swc/core-win32-ia32-msvc": "1.11.16", + "@swc/core-win32-x64-msvc": "1.11.16" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.16.tgz", + "integrity": "sha512-l6uWMU+MUdfLHCl3dJgtVEdsUHPskoA4BSu0L1hh9SGBwPZ8xeOz8iLIqZM27lTuXxL4KsYH6GQR/OdQ/vhLtg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.16.tgz", + "integrity": "sha512-TH0IW8Ao1WZ4ARFHIh29dAQHYBEl4YnP74n++rjppmlCjY+8v3s5nXMA7IqxO3b5LVHyggWtU4+46DXTyMJM7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.16.tgz", + "integrity": "sha512-2IxD9t09oNZrbv37p4cJ9cTHMUAK6qNiShi9s2FJ9LcqSnZSN4iS4hvaaX6KZuG54d58vWnMU7yycjkdOTQcMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.16.tgz", + "integrity": "sha512-AYkN23DOiPh1bf3XBf/xzZQDKSsgZTxlbyTyUIhprLJpAAAT0ZCGAUcS5mHqydk0nWQ13ABUymodvHoroutNzw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.16.tgz", + "integrity": "sha512-n/nWXDRCIhM51dDGELfBcTMNnCiFatE7LDvsbYxb7DJt1HGjaCNvHHCKURb/apJTh/YNtWfgFap9dbsTgw8yPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.16.tgz", + "integrity": "sha512-xr182YQrF47n7Awxj+/ruI21bYw+xO/B26KFVnb+i3ezF9NOhqoqTX+33RL1ZLA/uFTq8ksPZO/y+ZVS/odtQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.16.tgz", + "integrity": "sha512-k2JBfiwWfXCIKrBRjFO9/vEdLSYq0QLJ+iNSLdfrejZ/aENNkbEg8O7O2GKUSb30RBacn6k8HMfJrcPLFiEyCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.16.tgz", + "integrity": "sha512-taOb5U+abyEhQgex+hr6cI48BoqSvSdfmdirWcxprIEUBHCxa1dSriVwnJRAJOFI9T+5BEz88by6rgbB9MjbHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.16.tgz", + "integrity": "sha512-b7yYggM9LBDiMY+XUt5kYWvs5sn0U3PXSOGvF3CbLufD/N/YQiDcYON2N3lrWHYL8aYnwbuZl45ojmQHSQPcdA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.11.16", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.16.tgz", + "integrity": "sha512-/ibq/YDc3B5AROkpOKPGxVkSyCKOg+ml8k11RxrW7FAPy6a9y5y9KPcWIqV74Ahq4RuaMNslTQqHWAGSm0xJsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@swc/types": { + "version": "0.1.21", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.21.tgz", + "integrity": "sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.101.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.0.tgz", + "integrity": "sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.101.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.0.tgz", + "integrity": "sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.101.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-logic-js": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/json-logic-js/-/json-logic-js-2.0.8.tgz", + "integrity": "sha512-WgNsDPuTPKYXl0Jh0IfoCoJoAGGYZt5qzpmjuLSEg7r0cKp/kWtWp0HAsVepyPSPyXiHo6uXp/B/kW/2J1fa2Q==", + "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": "22.14.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", + "integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.0.tgz", + "integrity": "sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.1.tgz", + "integrity": "sha512-jFf/woGTVTjUJsl2O7hcopJ1r0upqoq/vIOoCj0yLh3RIXxWcljlpuZ+vEBRXsymD1jhfeJrlyTy/S1UW+4y1w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.0.tgz", + "integrity": "sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/type-utils": "8.29.0", + "@typescript-eslint/utils": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.1" + }, + "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.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.0.tgz", + "integrity": "sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/typescript-estree": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", + "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 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.0.tgz", + "integrity": "sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.0.tgz", + "integrity": "sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.29.0", + "@typescript-eslint/utils": "8.29.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.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 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz", + "integrity": "sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==", + "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.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.0.tgz", + "integrity": "sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/visitor-keys": "8.29.0", + "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.0.1" + }, + "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 <5.9.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.0.tgz", + "integrity": "sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.29.0", + "@typescript-eslint/types": "8.29.0", + "@typescript-eslint/typescript-estree": "8.29.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 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.0.tgz", + "integrity": "sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.29.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-EpRILdWr3/xDa/7MoyfO7JuBIJqpBMphtu4+80BK1bRfFcniVT74h3Z7q1+WOc92FuIAYatB1vn9TJR67sORGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.3.3.tgz", + "integrity": "sha512-ntj/g7lPyqwinMJWZ+DKHBse8HhVxswGTmNgFKJtdgGub3M3zp5BSZ3bvMP+kBT6dnYJLSVlDqdwOq1P8i0+/g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.3.3.tgz", + "integrity": "sha512-l6BT8f2CU821EW7U8hSUK8XPq4bmyTlt9Mn4ERrfjJNoCw0/JoHAh9amZZtV3cwC3bwwIat+GUnrcHTG9+qixw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.3.3.tgz", + "integrity": "sha512-8ScEc5a4y7oE2BonRvzJ+2GSkBaYWyh0/Ko4Q25e/ix6ANpJNhwEPZvCR6GVRmsQAYMIfQvYLdM6YEN+qRjnAQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.3.3.tgz", + "integrity": "sha512-8qQ6l1VTzLNd3xb2IEXISOKwMGXDCzY/UNy/7SovFW2Sp0K3YbL7Ao7R18v6SQkLqQlhhqSBIFRk+u6+qu5R5A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.3.3.tgz", + "integrity": "sha512-v81R2wjqcWXJlQY23byqYHt9221h4anQ6wwN64oMD/WAE+FmxPHFZee5bhRkNVtzqO/q7wki33VFWlhiADwUeQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.3.3.tgz", + "integrity": "sha512-cAOx/j0u5coMg4oct/BwMzvWJdVciVauUvsd+GQB/1FZYKQZmqPy0EjJzJGbVzFc6gbnfEcSqvQE6gvbGf2N8Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.3.3.tgz", + "integrity": "sha512-mq2blqwErgDJD4gtFDlTX/HZ7lNP8YCHYFij2gkXPtMzrXxPW1hOtxL6xg4NWxvnj4bppppb0W3s/buvM55yfg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.3.3.tgz", + "integrity": "sha512-u0VRzfFYysarYHnztj2k2xr+eu9rmgoTUUgCCIT37Nr+j0A05Xk2c3RY8Mh5+DhCl2aYibihnaAEJHeR0UOFIQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.3.3.tgz", + "integrity": "sha512-OrVo5ZsG29kBF0Ug95a2KidS16PqAMmQNozM6InbquOfW/udouk063e25JVLqIBhHLB2WyBnixOQ19tmeC/hIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.3.3.tgz", + "integrity": "sha512-PYnmrwZ4HMp9SkrOhqPghY/aoL+Rtd4CQbr93GlrRTjK6kDzfMfgz3UH3jt6elrQAfupa1qyr1uXzeVmoEAxUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.3.3.tgz", + "integrity": "sha512-81AnQY6fShmktQw4hWDUIilsKSdvr/acdJ5azAreu2IWNlaJOKphJSsUVWE+yCk6kBMoQyG9ZHCb/krb5K0PEA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.7" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.3.3.tgz", + "integrity": "sha512-X/42BMNw7cW6xrB9syuP5RusRnWGoq+IqvJO8IDpp/BZg64J1uuIW6qA/1Cl13Y4LyLXbJVYbYNSKwR/FiHEng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.3.3.tgz", + "integrity": "sha512-EGNnNGQxMU5aTN7js3ETYvuw882zcO+dsVjs+DwO2j/fRVKth87C8e2GzxW1L3+iWAXMyJhvFBKRavk9Og1Z6A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.3.3.tgz", + "integrity": "sha512-GraLbYqOJcmW1qY3osB+2YIiD62nVf2/bVLHZmrb4t/YSUwE03l7TwcDJl08T/Tm3SVhepX8RQkpzWbag/Sb4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vitejs/plugin-react-swc": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.8.1.tgz", + "integrity": "sha512-aEUPCckHDcFyxpwFm0AIkbtv6PpUp3xTb9wYGFjtABynXjCYKkWoxX0AOK9NT9XCrdk6mBBUOeHQS+RKdcNO1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@swc/core": "^1.11.11" + }, + "peerDependencies": { + "vite": "^4 || ^5 || ^6" + } + }, + "node_modules/@yr/monotone-cubic-spline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "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/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "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": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/apexcharts": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.5.0.tgz", + "integrity": "sha512-E7ZkrVqPNBUWy/Rmg8DEIqHNBmElzICE/oxOX5Ekvs2ICQUOK/VkEkMH09JGJu+O/EA0NL31hxlmF+wrwrSLaQ==", + "license": "MIT", + "dependencies": { + "@svgdotjs/svg.draggable.js": "^3.0.4", + "@svgdotjs/svg.filter.js": "^3.0.8", + "@svgdotjs/svg.js": "^3.2.4", + "@svgdotjs/svg.resize.js": "^2.0.2", + "@svgdotjs/svg.select.js": "^4.0.1", + "@yr/monotone-cubic-spline": "^1.0.3" + } + }, + "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/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.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "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", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "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/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/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "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/axios": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz", + "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "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/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "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/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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "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/cross-spawn/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/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/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/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "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/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "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/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "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==", + "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/engine.io-client": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz", + "integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==", + "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.0.0" + } + }, + "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/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "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.3", + "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.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "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-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.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.18" + }, + "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==", + "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==", + "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==", + "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==", + "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/es-toolkit": { + "version": "1.34.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.34.1.tgz", + "integrity": "sha512-OA6cd94fJV9bm8dWhIySkWq4xV+rAQnBZUr2dnpXam0QJ8c+hurLbKA8/QooL9Mx4WCAxvIDsiEkid5KPQ5xgQ==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "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.5", + "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-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": "4.3.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.3.1.tgz", + "integrity": "sha512-/dR9YMomeBlvfuvX5q0C3Y/2PHC9OCRdT2ijFwdfq/4Bq+4m5/lqstEp9k3P6ocha1pCbhoY9fkwVYLmOqR0VQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.12", + "unrs-resolver": "^1.3.3" + }, + "engines": { + "node": "^16.17.0 || >=18.6.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.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "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.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "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/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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-perfectionist": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.11.0.tgz", + "integrity": "sha512-5s+ehXydnLPQpLDj5mJ0CnYj2fQe6v6gKA3tS+FZVBLzwMOh8skH+l+1Gni08rG0SdEcNhJyjQp/mEkDYK8czw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.29.0", + "@typescript-eslint/utils": "^8.29.0", + "natural-orderby": "^5.0.0" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "eslint": ">=8.45.0" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "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.8", + "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/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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-plugin-unused-imports": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz", + "integrity": "sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", + "eslint": "^9.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, + "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": "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/eslint/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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/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/event-target-polyfill": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/event-target-polyfill/-/event-target-polyfill-0.0.4.tgz", + "integrity": "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ==", + "license": "MIT" + }, + "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/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/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-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, + "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.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "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/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "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-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "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==", + "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.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "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/globals": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.0.0.tgz", + "integrity": "sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==", + "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/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "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==", + "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==", + "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.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==", + "license": "MIT" + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/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==", + "license": "MIT" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "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-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "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-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==", + "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-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-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/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.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "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-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "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/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/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==", + "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.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "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/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "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/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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/minimal-shared": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minimal-shared/-/minimal-shared-1.0.7.tgz", + "integrity": "sha512-KP+8dQw43lTkE1vCqjV4dakapCP5sk5trFAo8d2kpJYBZQc3DrGoE1Q9uwKe0hDtbgSwE4zmVYdgmsatF9/JZw==", + "license": "MIT", + "dependencies": { + "es-toolkit": "^1.32.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "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/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "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/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/natural-orderby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz", + "integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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-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==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/partysocket": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/partysocket/-/partysocket-1.3.0.tgz", + "integrity": "sha512-1zToNyolZFK/7nuAw/K2bZrNzFqaZyRoCEkS+9vG6WSC5ikrN6qWRe96q6ImU51uptz2r+dAwSkwhJVdQi4LiA==", + "license": "MIT", + "dependencies": { + "event-target-polyfill": "^0.0.4" + }, + "peerDependencies": { + "react": ">=17" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "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": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "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.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "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.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/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==", + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-apexcharts": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.7.0.tgz", + "integrity": "sha512-03oScKJyNLRf0Oe+ihJxFZliBQM9vW3UWwomVn4YVRTN1jsIR58dLWt0v1sb8RwJVHDMbeHiKQueM0KGpn7nOA==", + "license": "MIT", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "apexcharts": ">=4.0.0", + "react": ">=0.13" + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/react-hook-form": { + "version": "7.79.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.79.0.tgz", + "integrity": "sha512-mhYp/MTmXvzYX6AJcJVko0rktoIhhmRnEouObj4wF5i/tCttgJvnp1+9wRkpITZjDTqpo4IOSJqu0dBlPlV/Lw==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", + "license": "MIT" + }, + "node_modules/react-router": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.17.0.tgz", + "integrity": "sha512-FDELK7rTMlCHO5+reyXsPlmfr7N1F91lPHsWYfMEGQm/KQ+F4JFM8jGoeQDmDvdTs93Fw9aSilH+uKRb4/jXvQ==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.17.0.tgz", + "integrity": "sha512-fyU2yjGups/hE6Xz0I5ZYbVL8Gx29eCjgpHaRaTaVU+OOAdfRX05KsvyRm0GO8YQwOkhpU3MurW1jyMUJn+zSw==", + "license": "MIT", + "dependencies": { + "react-router": "7.17.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "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/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "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/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "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==", + "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/rollup": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.0.tgz", + "integrity": "sha512-nc72Wgq62I7rtDV4izT5/aaS0zxy3kttkinf9586ApknY3jZO9NYsmtc24fUckA0X7Q2v+ML4a15pdUlV5V/jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.0", + "@rollup/rollup-android-arm64": "4.62.0", + "@rollup/rollup-darwin-arm64": "4.62.0", + "@rollup/rollup-darwin-x64": "4.62.0", + "@rollup/rollup-freebsd-arm64": "4.62.0", + "@rollup/rollup-freebsd-x64": "4.62.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.0", + "@rollup/rollup-linux-arm-musleabihf": "4.62.0", + "@rollup/rollup-linux-arm64-gnu": "4.62.0", + "@rollup/rollup-linux-arm64-musl": "4.62.0", + "@rollup/rollup-linux-loong64-gnu": "4.62.0", + "@rollup/rollup-linux-loong64-musl": "4.62.0", + "@rollup/rollup-linux-ppc64-gnu": "4.62.0", + "@rollup/rollup-linux-ppc64-musl": "4.62.0", + "@rollup/rollup-linux-riscv64-gnu": "4.62.0", + "@rollup/rollup-linux-riscv64-musl": "4.62.0", + "@rollup/rollup-linux-s390x-gnu": "4.62.0", + "@rollup/rollup-linux-x64-gnu": "4.62.0", + "@rollup/rollup-linux-x64-musl": "4.62.0", + "@rollup/rollup-openbsd-x64": "4.62.0", + "@rollup/rollup-openharmony-arm64": "4.62.0", + "@rollup/rollup-win32-arm64-msvc": "4.62.0", + "@rollup/rollup-win32-ia32-msvc": "4.62.0", + "@rollup/rollup-win32-x64-gnu": "4.62.0", + "@rollup/rollup-win32-x64-msvc": "4.62.0", + "fsevents": "~2.3.2" + } + }, + "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/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.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/seroval": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.5.4.tgz", + "integrity": "sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/seroval-plugins": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.5.4.tgz", + "integrity": "sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "seroval": "^1.0" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "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/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/simplebar-core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/simplebar-core/-/simplebar-core-1.3.0.tgz", + "integrity": "sha512-LpWl3w0caz0bl322E68qsrRPpIn+rWBGAaEJ0lUJA7Xpr2sw92AkIhg6VWj988IefLXYh50ILatfAnbNoCFrlA==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/simplebar-react": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/simplebar-react/-/simplebar-react-3.3.0.tgz", + "integrity": "sha512-sxzy+xRuU41He4tT4QLGYutchtOuye/xxVeq7xhyOiwMiHNK1ZpvbOTyy+7P0i7gfpXLGTJ8Bep8+4Mhdgtz/g==", + "license": "MIT", + "dependencies": { + "simplebar-core": "^1.3.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/socket.io-client": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz", + "integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "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.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/solid-floating-ui": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/solid-floating-ui/-/solid-floating-ui-0.3.1.tgz", + "integrity": "sha512-o/QmGsWPS2Z3KidAxP0nDvN7alI7Kqy0kU+wd85Fz+au5SYcnYm7I6Fk3M60Za35azsPX0U+5fEtqfOuk6Ao0Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@floating-ui/dom": "^1.5", + "solid-js": "^1.8" + } + }, + "node_modules/solid-js": { + "version": "1.9.14", + "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.14.tgz", + "integrity": "sha512-sAEXC0Kk0S1EDg+8ysEWJDbYhA3RRoEjwuySUGlKIemeo0I5YZfOyumNjNs9Sv3y2nmhD+0rW66ag2HsMuQiGQ==", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.0", + "seroval": "~1.5.4", + "seroval-plugins": "~1.5.4" + } + }, + "node_modules/solid-motionone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/solid-motionone/-/solid-motionone-1.0.4.tgz", + "integrity": "sha512-aqEjgecoO9raDFznu/dEci7ORSmA26Kjj9J4Cn1Gyr0GZuOVdvsNxdxClTL9J40Aq/uYFx4GLwC8n70fMLHiuA==", + "license": "MIT", + "dependencies": { + "@motionone/dom": "^10.17.0", + "@motionone/utils": "^10.17.0", + "@solid-primitives/props": "^3.1.11", + "@solid-primitives/refs": "^1.0.8", + "@solid-primitives/transition-group": "^1.0.5", + "csstype": "^3.1.3" + }, + "peerDependencies": { + "solid-js": "^1.8.0" + } + }, + "node_modules/solid-presence": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/solid-presence/-/solid-presence-0.1.8.tgz", + "integrity": "sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA==", + "license": "MIT", + "dependencies": { + "@corvu/utils": "~0.4.0" + }, + "peerDependencies": { + "solid-js": "^1.8" + } + }, + "node_modules/solid-prevent-scroll": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/solid-prevent-scroll/-/solid-prevent-scroll-0.1.10.tgz", + "integrity": "sha512-KplGPX2GHiWJLZ6AXYRql4M127PdYzfwvLJJXMkO+CMb8Np4VxqDAg5S8jLdwlEuBis/ia9DKw2M8dFx5u8Mhw==", + "license": "MIT", + "dependencies": { + "@corvu/utils": "~0.4.1" + }, + "peerDependencies": { + "solid-js": "^1.8" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "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/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": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "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/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/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz", + "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "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/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/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/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.8.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", + "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.29.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.29.0.tgz", + "integrity": "sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.29.0", + "@typescript-eslint/parser": "8.29.0", + "@typescript-eslint/utils": "8.29.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 <5.9.0" + } + }, + "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": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unrs-resolver": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.3.3.tgz", + "integrity": "sha512-PFLAGQzYlyjniXdbmQ3dnGMZJXX5yrl2YS4DLRfR3BhgUsE1zpRIrccp9XMOGRfIHpdFvCn/nr5N1KMVda4x3A==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/JounQin" + }, + "optionalDependencies": { + "@unrs/resolver-binding-darwin-arm64": "1.3.3", + "@unrs/resolver-binding-darwin-x64": "1.3.3", + "@unrs/resolver-binding-freebsd-x64": "1.3.3", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.3.3", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.3.3", + "@unrs/resolver-binding-linux-arm64-gnu": "1.3.3", + "@unrs/resolver-binding-linux-arm64-musl": "1.3.3", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.3.3", + "@unrs/resolver-binding-linux-s390x-gnu": "1.3.3", + "@unrs/resolver-binding-linux-x64-gnu": "1.3.3", + "@unrs/resolver-binding-linux-x64-musl": "1.3.3", + "@unrs/resolver-binding-wasm32-wasi": "1.3.3", + "@unrs/resolver-binding-win32-arm64-msvc": "1.3.3", + "@unrs/resolver-binding-win32-ia32-msvc": "1.3.3", + "@unrs/resolver-binding-win32-x64-msvc": "1.3.3" + } + }, + "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/vite": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz", + "integrity": "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-checker": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.9.1.tgz", + "integrity": "sha512-neH3CSNWdkZ+zi+WPt/0y5+IO2I0UAI0NX6MaXqU/KxN1Lz6np/7IooRB6VVAMBa4nigqm1GRF6qNa4+EL5jDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "chokidar": "^4.0.3", + "npm-run-path": "^6.0.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.2", + "strip-ansi": "^7.1.0", + "tiny-invariant": "^1.3.3", + "tinyglobby": "^0.2.12", + "vscode-uri": "^3.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "peerDependencies": { + "@biomejs/biome": ">=1.7", + "eslint": ">=7", + "meow": "^13.2.0", + "optionator": "^0.9.4", + "stylelint": ">=16", + "typescript": "*", + "vite": ">=2.0.0", + "vls": "*", + "vti": "*", + "vue-tsc": "~2.2.2" + }, + "peerDependenciesMeta": { + "@biomejs/biome": { + "optional": true + }, + "eslint": { + "optional": true + }, + "meow": { + "optional": true + }, + "optionator": { + "optional": true + }, + "stylelint": { + "optional": true + }, + "typescript": { + "optional": true + }, + "vls": { + "optional": true + }, + "vti": { + "optional": true + }, + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "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/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.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "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/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 000000000..58dd37846 --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,76 @@ +{ + "name": "@minimal/material-kit-react", + "author": "minimals.cc", + "licence": "MIT", + "version": "3.0.0", + "private": false, + "type": "module", + "scripts": { + "dev": "vite", + "start": "vite preview", + "build": "tsc && vite build", + "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", + "lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx}\"", + "lint:print": "npx eslint --print-config eslint.config.mjs > eslint-show-config.json", + "fm:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx}\"", + "fm:fix": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"", + "fix:all": "npm run lint:fix && npm run fm:fix", + "clean": "rm -rf node_modules .next out dist build", + "re:dev": "yarn clean && yarn install && yarn dev", + "re:build": "yarn clean && yarn install && yarn build", + "re:build-npm": "npm run clean && npm install && npm run build", + "tsc:dev": "yarn dev & yarn tsc:watch", + "tsc:watch": "tsc --noEmit --watch", + "tsc:print": "npx tsc --showConfig" + }, + "engines": { + "node": ">=20" + }, + "packageManager": "yarn@1.22.22", + "dependencies": { + "@emotion/cache": "^11.14.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@fontsource-variable/dm-sans": "^5.2.5", + "@fontsource/barlow": "^5.2.5", + "@hookform/resolvers": "^5.4.0", + "@iconify/react": "^5.2.1", + "@mui/lab": "^7.0.0-beta.10", + "@mui/material": "^7.0.1", + "@novu/react": "^3.17.0", + "@tanstack/react-query": "^5.101.0", + "apexcharts": "^4.5.0", + "axios": "^1.18.0", + "dayjs": "^1.11.13", + "es-toolkit": "^1.34.1", + "minimal-shared": "^1.0.7", + "react": "^19.1.0", + "react-apexcharts": "^1.7.0", + "react-dom": "^19.1.0", + "react-hook-form": "^7.79.0", + "react-router-dom": "^7.4.1", + "simplebar-react": "^3.3.0", + "zod": "^4.4.3" + }, + "devDependencies": { + "@eslint/js": "^9.23.0", + "@types/node": "^22.14.0", + "@types/react": "^19.1.0", + "@types/react-dom": "^19.1.1", + "@typescript-eslint/parser": "^8.29.0", + "@vitejs/plugin-react-swc": "^3.8.1", + "eslint": "^9.23.0", + "eslint-import-resolver-typescript": "^4.3.1", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-perfectionist": "^4.11.0", + "eslint-plugin-react": "^7.37.4", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-unused-imports": "^4.1.4", + "globals": "^16.0.0", + "prettier": "^3.5.3", + "typescript": "^5.8.2", + "typescript-eslint": "^8.29.0", + "vite": "^6.2.5", + "vite-plugin-checker": "^0.9.1" + } +} diff --git a/frontend/prettier.config.mjs b/frontend/prettier.config.mjs new file mode 100644 index 000000000..a3b4e4ef0 --- /dev/null +++ b/frontend/prettier.config.mjs @@ -0,0 +1,15 @@ +/** + * @type {import("prettier").Config} + * Need to restart IDE when changing configuration + * Open the command palette (Ctrl + Shift + P) and execute the command > Reload Window. + */ +const config = { + semi: true, + tabWidth: 2, + endOfLine: 'lf', + printWidth: 100, + singleQuote: true, + trailingComma: 'es5', +}; + +export default config; diff --git a/frontend/public/assets/background/overlay.jpg b/frontend/public/assets/background/overlay.jpg new file mode 100644 index 000000000..e6e7a327c Binary files /dev/null and b/frontend/public/assets/background/overlay.jpg differ diff --git a/frontend/public/assets/background/shape-square.svg b/frontend/public/assets/background/shape-square.svg new file mode 100644 index 000000000..b62e4303a --- /dev/null +++ b/frontend/public/assets/background/shape-square.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/flags/ic-flag-de.svg b/frontend/public/assets/icons/flags/ic-flag-de.svg new file mode 100644 index 000000000..c36170786 --- /dev/null +++ b/frontend/public/assets/icons/flags/ic-flag-de.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/flags/ic-flag-en.svg b/frontend/public/assets/icons/flags/ic-flag-en.svg new file mode 100644 index 000000000..485ad5c34 --- /dev/null +++ b/frontend/public/assets/icons/flags/ic-flag-en.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/flags/ic-flag-fr.svg b/frontend/public/assets/icons/flags/ic-flag-fr.svg new file mode 100644 index 000000000..2ae63a139 --- /dev/null +++ b/frontend/public/assets/icons/flags/ic-flag-fr.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/glass/ic-glass-bag.svg b/frontend/public/assets/icons/glass/ic-glass-bag.svg new file mode 100644 index 000000000..5875b6f39 --- /dev/null +++ b/frontend/public/assets/icons/glass/ic-glass-bag.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/assets/icons/glass/ic-glass-buy.svg b/frontend/public/assets/icons/glass/ic-glass-buy.svg new file mode 100644 index 000000000..07577a653 --- /dev/null +++ b/frontend/public/assets/icons/glass/ic-glass-buy.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/assets/icons/glass/ic-glass-message.svg b/frontend/public/assets/icons/glass/ic-glass-message.svg new file mode 100644 index 000000000..e82d8d86e --- /dev/null +++ b/frontend/public/assets/icons/glass/ic-glass-message.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/assets/icons/glass/ic-glass-users.svg b/frontend/public/assets/icons/glass/ic-glass-users.svg new file mode 100644 index 000000000..d69a579e3 --- /dev/null +++ b/frontend/public/assets/icons/glass/ic-glass-users.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/assets/icons/navbar/ic-analytics.svg b/frontend/public/assets/icons/navbar/ic-analytics.svg new file mode 100644 index 000000000..2cf74af5e --- /dev/null +++ b/frontend/public/assets/icons/navbar/ic-analytics.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/frontend/public/assets/icons/navbar/ic-blog.svg b/frontend/public/assets/icons/navbar/ic-blog.svg new file mode 100644 index 000000000..6f8f006fe --- /dev/null +++ b/frontend/public/assets/icons/navbar/ic-blog.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/public/assets/icons/navbar/ic-cart.svg b/frontend/public/assets/icons/navbar/ic-cart.svg new file mode 100644 index 000000000..bafbda953 --- /dev/null +++ b/frontend/public/assets/icons/navbar/ic-cart.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/frontend/public/assets/icons/navbar/ic-disabled.svg b/frontend/public/assets/icons/navbar/ic-disabled.svg new file mode 100644 index 000000000..5f7bda359 --- /dev/null +++ b/frontend/public/assets/icons/navbar/ic-disabled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/public/assets/icons/navbar/ic-lock.svg b/frontend/public/assets/icons/navbar/ic-lock.svg new file mode 100644 index 000000000..1545a1eb9 --- /dev/null +++ b/frontend/public/assets/icons/navbar/ic-lock.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/public/assets/icons/navbar/ic-user.svg b/frontend/public/assets/icons/navbar/ic-user.svg new file mode 100644 index 000000000..9f08419c3 --- /dev/null +++ b/frontend/public/assets/icons/navbar/ic-user.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/public/assets/icons/notification/ic-notification-chat.svg b/frontend/public/assets/icons/notification/ic-notification-chat.svg new file mode 100644 index 000000000..0fa6d651e --- /dev/null +++ b/frontend/public/assets/icons/notification/ic-notification-chat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/notification/ic-notification-mail.svg b/frontend/public/assets/icons/notification/ic-notification-mail.svg new file mode 100644 index 000000000..524fc75e3 --- /dev/null +++ b/frontend/public/assets/icons/notification/ic-notification-mail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/notification/ic-notification-package.svg b/frontend/public/assets/icons/notification/ic-notification-package.svg new file mode 100644 index 000000000..87f3b79bc --- /dev/null +++ b/frontend/public/assets/icons/notification/ic-notification-package.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/notification/ic-notification-shipping.svg b/frontend/public/assets/icons/notification/ic-notification-shipping.svg new file mode 100644 index 000000000..da3d5ad12 --- /dev/null +++ b/frontend/public/assets/icons/notification/ic-notification-shipping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/shape-avatar.svg b/frontend/public/assets/icons/shape-avatar.svg new file mode 100644 index 000000000..38aac7e27 --- /dev/null +++ b/frontend/public/assets/icons/shape-avatar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/public/assets/icons/workspaces/logo-1.webp b/frontend/public/assets/icons/workspaces/logo-1.webp new file mode 100644 index 000000000..daf350d57 Binary files /dev/null and b/frontend/public/assets/icons/workspaces/logo-1.webp differ diff --git a/frontend/public/assets/icons/workspaces/logo-2.webp b/frontend/public/assets/icons/workspaces/logo-2.webp new file mode 100644 index 000000000..3b629ef18 Binary files /dev/null and b/frontend/public/assets/icons/workspaces/logo-2.webp differ diff --git a/frontend/public/assets/icons/workspaces/logo-3.webp b/frontend/public/assets/icons/workspaces/logo-3.webp new file mode 100644 index 000000000..273fe0710 Binary files /dev/null and b/frontend/public/assets/icons/workspaces/logo-3.webp differ diff --git a/frontend/public/assets/illustrations/illustration-404.svg b/frontend/public/assets/illustrations/illustration-404.svg new file mode 100644 index 000000000..bd59d64ae --- /dev/null +++ b/frontend/public/assets/illustrations/illustration-404.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/assets/illustrations/illustration-dashboard.webp b/frontend/public/assets/illustrations/illustration-dashboard.webp new file mode 100644 index 000000000..3c1d1a3eb Binary files /dev/null and b/frontend/public/assets/illustrations/illustration-dashboard.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-1.webp b/frontend/public/assets/images/avatar/avatar-1.webp new file mode 100644 index 000000000..d0860df6b Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-1.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-10.webp b/frontend/public/assets/images/avatar/avatar-10.webp new file mode 100644 index 000000000..a523203ec Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-10.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-11.webp b/frontend/public/assets/images/avatar/avatar-11.webp new file mode 100644 index 000000000..7da3d8db7 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-11.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-12.webp b/frontend/public/assets/images/avatar/avatar-12.webp new file mode 100644 index 000000000..2ef56666b Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-12.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-13.webp b/frontend/public/assets/images/avatar/avatar-13.webp new file mode 100644 index 000000000..d03b48057 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-13.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-14.webp b/frontend/public/assets/images/avatar/avatar-14.webp new file mode 100644 index 000000000..80a8d2948 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-14.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-15.webp b/frontend/public/assets/images/avatar/avatar-15.webp new file mode 100644 index 000000000..9ac9816e5 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-15.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-16.webp b/frontend/public/assets/images/avatar/avatar-16.webp new file mode 100644 index 000000000..7251b747a Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-16.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-17.webp b/frontend/public/assets/images/avatar/avatar-17.webp new file mode 100644 index 000000000..5d5a465a9 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-17.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-18.webp b/frontend/public/assets/images/avatar/avatar-18.webp new file mode 100644 index 000000000..4c545e4ec Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-18.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-19.webp b/frontend/public/assets/images/avatar/avatar-19.webp new file mode 100644 index 000000000..6fc8ff3ce Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-19.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-2.webp b/frontend/public/assets/images/avatar/avatar-2.webp new file mode 100644 index 000000000..6af043adc Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-2.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-20.webp b/frontend/public/assets/images/avatar/avatar-20.webp new file mode 100644 index 000000000..8cb58ce31 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-20.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-21.webp b/frontend/public/assets/images/avatar/avatar-21.webp new file mode 100644 index 000000000..b88979b3b Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-21.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-22.webp b/frontend/public/assets/images/avatar/avatar-22.webp new file mode 100644 index 000000000..2fe2c6bd5 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-22.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-23.webp b/frontend/public/assets/images/avatar/avatar-23.webp new file mode 100644 index 000000000..5139e237f Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-23.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-24.webp b/frontend/public/assets/images/avatar/avatar-24.webp new file mode 100644 index 000000000..e6717200f Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-24.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-25.webp b/frontend/public/assets/images/avatar/avatar-25.webp new file mode 100644 index 000000000..e5bce1b60 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-25.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-3.webp b/frontend/public/assets/images/avatar/avatar-3.webp new file mode 100644 index 000000000..9e7e1618f Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-3.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-4.webp b/frontend/public/assets/images/avatar/avatar-4.webp new file mode 100644 index 000000000..acdd7d71f Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-4.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-5.webp b/frontend/public/assets/images/avatar/avatar-5.webp new file mode 100644 index 000000000..d02bbcee8 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-5.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-6.webp b/frontend/public/assets/images/avatar/avatar-6.webp new file mode 100644 index 000000000..951913871 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-6.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-7.webp b/frontend/public/assets/images/avatar/avatar-7.webp new file mode 100644 index 000000000..b1272cbcb Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-7.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-8.webp b/frontend/public/assets/images/avatar/avatar-8.webp new file mode 100644 index 000000000..35b9dfe32 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-8.webp differ diff --git a/frontend/public/assets/images/avatar/avatar-9.webp b/frontend/public/assets/images/avatar/avatar-9.webp new file mode 100644 index 000000000..b0a8158c0 Binary files /dev/null and b/frontend/public/assets/images/avatar/avatar-9.webp differ diff --git a/frontend/public/assets/images/cover/cover-1.webp b/frontend/public/assets/images/cover/cover-1.webp new file mode 100644 index 000000000..9fa25604f Binary files /dev/null and b/frontend/public/assets/images/cover/cover-1.webp differ diff --git a/frontend/public/assets/images/cover/cover-10.webp b/frontend/public/assets/images/cover/cover-10.webp new file mode 100644 index 000000000..82ca7901c Binary files /dev/null and b/frontend/public/assets/images/cover/cover-10.webp differ diff --git a/frontend/public/assets/images/cover/cover-11.webp b/frontend/public/assets/images/cover/cover-11.webp new file mode 100644 index 000000000..41ddd0070 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-11.webp differ diff --git a/frontend/public/assets/images/cover/cover-12.webp b/frontend/public/assets/images/cover/cover-12.webp new file mode 100644 index 000000000..a0ab39a79 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-12.webp differ diff --git a/frontend/public/assets/images/cover/cover-13.webp b/frontend/public/assets/images/cover/cover-13.webp new file mode 100644 index 000000000..f650eada5 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-13.webp differ diff --git a/frontend/public/assets/images/cover/cover-14.webp b/frontend/public/assets/images/cover/cover-14.webp new file mode 100644 index 000000000..cf7493d11 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-14.webp differ diff --git a/frontend/public/assets/images/cover/cover-15.webp b/frontend/public/assets/images/cover/cover-15.webp new file mode 100644 index 000000000..8a82b5dd3 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-15.webp differ diff --git a/frontend/public/assets/images/cover/cover-16.webp b/frontend/public/assets/images/cover/cover-16.webp new file mode 100644 index 000000000..50abb7282 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-16.webp differ diff --git a/frontend/public/assets/images/cover/cover-17.webp b/frontend/public/assets/images/cover/cover-17.webp new file mode 100644 index 000000000..30f36d003 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-17.webp differ diff --git a/frontend/public/assets/images/cover/cover-18.webp b/frontend/public/assets/images/cover/cover-18.webp new file mode 100644 index 000000000..ee64c4a75 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-18.webp differ diff --git a/frontend/public/assets/images/cover/cover-19.webp b/frontend/public/assets/images/cover/cover-19.webp new file mode 100644 index 000000000..4f1962ef2 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-19.webp differ diff --git a/frontend/public/assets/images/cover/cover-2.webp b/frontend/public/assets/images/cover/cover-2.webp new file mode 100644 index 000000000..5a5d2100c Binary files /dev/null and b/frontend/public/assets/images/cover/cover-2.webp differ diff --git a/frontend/public/assets/images/cover/cover-20.webp b/frontend/public/assets/images/cover/cover-20.webp new file mode 100644 index 000000000..6e26beb8a Binary files /dev/null and b/frontend/public/assets/images/cover/cover-20.webp differ diff --git a/frontend/public/assets/images/cover/cover-21.webp b/frontend/public/assets/images/cover/cover-21.webp new file mode 100644 index 000000000..7f9457506 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-21.webp differ diff --git a/frontend/public/assets/images/cover/cover-22.webp b/frontend/public/assets/images/cover/cover-22.webp new file mode 100644 index 000000000..fc88ae667 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-22.webp differ diff --git a/frontend/public/assets/images/cover/cover-23.webp b/frontend/public/assets/images/cover/cover-23.webp new file mode 100644 index 000000000..ab7006746 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-23.webp differ diff --git a/frontend/public/assets/images/cover/cover-24.webp b/frontend/public/assets/images/cover/cover-24.webp new file mode 100644 index 000000000..d6b9fb71c Binary files /dev/null and b/frontend/public/assets/images/cover/cover-24.webp differ diff --git a/frontend/public/assets/images/cover/cover-3.webp b/frontend/public/assets/images/cover/cover-3.webp new file mode 100644 index 000000000..5b023b863 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-3.webp differ diff --git a/frontend/public/assets/images/cover/cover-4.webp b/frontend/public/assets/images/cover/cover-4.webp new file mode 100644 index 000000000..0e9ecbf0d Binary files /dev/null and b/frontend/public/assets/images/cover/cover-4.webp differ diff --git a/frontend/public/assets/images/cover/cover-5.webp b/frontend/public/assets/images/cover/cover-5.webp new file mode 100644 index 000000000..8f1785f49 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-5.webp differ diff --git a/frontend/public/assets/images/cover/cover-6.webp b/frontend/public/assets/images/cover/cover-6.webp new file mode 100644 index 000000000..bb46a04c2 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-6.webp differ diff --git a/frontend/public/assets/images/cover/cover-7.webp b/frontend/public/assets/images/cover/cover-7.webp new file mode 100644 index 000000000..211355e04 Binary files /dev/null and b/frontend/public/assets/images/cover/cover-7.webp differ diff --git a/frontend/public/assets/images/cover/cover-8.webp b/frontend/public/assets/images/cover/cover-8.webp new file mode 100644 index 000000000..70cd3fb2b Binary files /dev/null and b/frontend/public/assets/images/cover/cover-8.webp differ diff --git a/frontend/public/assets/images/cover/cover-9.webp b/frontend/public/assets/images/cover/cover-9.webp new file mode 100644 index 000000000..7445854ac Binary files /dev/null and b/frontend/public/assets/images/cover/cover-9.webp differ diff --git a/frontend/public/assets/images/minimal-free-preview.jpg b/frontend/public/assets/images/minimal-free-preview.jpg new file mode 100644 index 000000000..91eb75612 Binary files /dev/null and b/frontend/public/assets/images/minimal-free-preview.jpg differ diff --git a/frontend/public/assets/images/product/product-1.webp b/frontend/public/assets/images/product/product-1.webp new file mode 100644 index 000000000..75659df3d Binary files /dev/null and b/frontend/public/assets/images/product/product-1.webp differ diff --git a/frontend/public/assets/images/product/product-10.webp b/frontend/public/assets/images/product/product-10.webp new file mode 100644 index 000000000..65e2c60e2 Binary files /dev/null and b/frontend/public/assets/images/product/product-10.webp differ diff --git a/frontend/public/assets/images/product/product-11.webp b/frontend/public/assets/images/product/product-11.webp new file mode 100644 index 000000000..17c3bc83d Binary files /dev/null and b/frontend/public/assets/images/product/product-11.webp differ diff --git a/frontend/public/assets/images/product/product-12.webp b/frontend/public/assets/images/product/product-12.webp new file mode 100644 index 000000000..2af581e95 Binary files /dev/null and b/frontend/public/assets/images/product/product-12.webp differ diff --git a/frontend/public/assets/images/product/product-13.webp b/frontend/public/assets/images/product/product-13.webp new file mode 100644 index 000000000..c1f403b89 Binary files /dev/null and b/frontend/public/assets/images/product/product-13.webp differ diff --git a/frontend/public/assets/images/product/product-14.webp b/frontend/public/assets/images/product/product-14.webp new file mode 100644 index 000000000..a5896f849 Binary files /dev/null and b/frontend/public/assets/images/product/product-14.webp differ diff --git a/frontend/public/assets/images/product/product-15.webp b/frontend/public/assets/images/product/product-15.webp new file mode 100644 index 000000000..475a7af54 Binary files /dev/null and b/frontend/public/assets/images/product/product-15.webp differ diff --git a/frontend/public/assets/images/product/product-16.webp b/frontend/public/assets/images/product/product-16.webp new file mode 100644 index 000000000..1b3b7ed61 Binary files /dev/null and b/frontend/public/assets/images/product/product-16.webp differ diff --git a/frontend/public/assets/images/product/product-17.webp b/frontend/public/assets/images/product/product-17.webp new file mode 100644 index 000000000..ddd8da034 Binary files /dev/null and b/frontend/public/assets/images/product/product-17.webp differ diff --git a/frontend/public/assets/images/product/product-18.webp b/frontend/public/assets/images/product/product-18.webp new file mode 100644 index 000000000..9ae8e26f9 Binary files /dev/null and b/frontend/public/assets/images/product/product-18.webp differ diff --git a/frontend/public/assets/images/product/product-19.webp b/frontend/public/assets/images/product/product-19.webp new file mode 100644 index 000000000..c5017f6c1 Binary files /dev/null and b/frontend/public/assets/images/product/product-19.webp differ diff --git a/frontend/public/assets/images/product/product-2.webp b/frontend/public/assets/images/product/product-2.webp new file mode 100644 index 000000000..65120df9d Binary files /dev/null and b/frontend/public/assets/images/product/product-2.webp differ diff --git a/frontend/public/assets/images/product/product-20.webp b/frontend/public/assets/images/product/product-20.webp new file mode 100644 index 000000000..893172055 Binary files /dev/null and b/frontend/public/assets/images/product/product-20.webp differ diff --git a/frontend/public/assets/images/product/product-21.webp b/frontend/public/assets/images/product/product-21.webp new file mode 100644 index 000000000..c7795b1df Binary files /dev/null and b/frontend/public/assets/images/product/product-21.webp differ diff --git a/frontend/public/assets/images/product/product-22.webp b/frontend/public/assets/images/product/product-22.webp new file mode 100644 index 000000000..b96c8091c Binary files /dev/null and b/frontend/public/assets/images/product/product-22.webp differ diff --git a/frontend/public/assets/images/product/product-23.webp b/frontend/public/assets/images/product/product-23.webp new file mode 100644 index 000000000..a38a73456 Binary files /dev/null and b/frontend/public/assets/images/product/product-23.webp differ diff --git a/frontend/public/assets/images/product/product-24.webp b/frontend/public/assets/images/product/product-24.webp new file mode 100644 index 000000000..643a1a654 Binary files /dev/null and b/frontend/public/assets/images/product/product-24.webp differ diff --git a/frontend/public/assets/images/product/product-3.webp b/frontend/public/assets/images/product/product-3.webp new file mode 100644 index 000000000..07b5312b7 Binary files /dev/null and b/frontend/public/assets/images/product/product-3.webp differ diff --git a/frontend/public/assets/images/product/product-4.webp b/frontend/public/assets/images/product/product-4.webp new file mode 100644 index 000000000..c18893e73 Binary files /dev/null and b/frontend/public/assets/images/product/product-4.webp differ diff --git a/frontend/public/assets/images/product/product-5.webp b/frontend/public/assets/images/product/product-5.webp new file mode 100644 index 000000000..014c146f9 Binary files /dev/null and b/frontend/public/assets/images/product/product-5.webp differ diff --git a/frontend/public/assets/images/product/product-6.webp b/frontend/public/assets/images/product/product-6.webp new file mode 100644 index 000000000..3ff7420e2 Binary files /dev/null and b/frontend/public/assets/images/product/product-6.webp differ diff --git a/frontend/public/assets/images/product/product-7.webp b/frontend/public/assets/images/product/product-7.webp new file mode 100644 index 000000000..6a0e9434e Binary files /dev/null and b/frontend/public/assets/images/product/product-7.webp differ diff --git a/frontend/public/assets/images/product/product-8.webp b/frontend/public/assets/images/product/product-8.webp new file mode 100644 index 000000000..0aae38af6 Binary files /dev/null and b/frontend/public/assets/images/product/product-8.webp differ diff --git a/frontend/public/assets/images/product/product-9.webp b/frontend/public/assets/images/product/product-9.webp new file mode 100644 index 000000000..2c86ff6fe Binary files /dev/null and b/frontend/public/assets/images/product/product-9.webp differ diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico new file mode 100644 index 000000000..5c435e6bb Binary files /dev/null and b/frontend/public/favicon.ico differ diff --git a/frontend/src/_mock/_data.ts b/frontend/src/_mock/_data.ts new file mode 100644 index 000000000..056177e20 --- /dev/null +++ b/frontend/src/_mock/_data.ts @@ -0,0 +1,210 @@ +import { + _id, + _price, + _times, + _company, + _boolean, + _fullName, + _taskNames, + _postTitles, + _description, + _productNames, +} from './_mock'; + +// ---------------------------------------------------------------------- + +export const _myAccount = { + displayName: 'Jaydon Frankie', + email: 'demo@minimals.cc', + photoURL: '/assets/images/avatar/avatar-25.webp', +}; + +// ---------------------------------------------------------------------- + +export const _users = [...Array(24)].map((_, index) => ({ + id: _id(index), + name: _fullName(index), + company: _company(index), + isVerified: _boolean(index), + avatarUrl: `/assets/images/avatar/avatar-${index + 1}.webp`, + status: index % 4 ? 'active' : 'banned', + role: + [ + 'Leader', + 'Hr Manager', + 'UI Designer', + 'UX Designer', + 'UI/UX Designer', + 'Project Manager', + 'Backend Developer', + 'Full Stack Designer', + 'Front End Developer', + 'Full Stack Developer', + ][index] || 'UI Designer', +})); + +// ---------------------------------------------------------------------- + +export const _posts = [...Array(23)].map((_, index) => ({ + id: _id(index), + title: _postTitles(index), + description: _description(index), + coverUrl: `/assets/images/cover/cover-${index + 1}.webp`, + totalViews: 8829, + totalComments: 7977, + totalShares: 8556, + totalFavorites: 8870, + postedAt: _times(index), + author: { + name: _fullName(index), + avatarUrl: `/assets/images/avatar/avatar-${index + 1}.webp`, + }, +})); + +// ---------------------------------------------------------------------- + +const COLORS = [ + '#00AB55', + '#000000', + '#FFFFFF', + '#FFC0CB', + '#FF4842', + '#1890FF', + '#94D82D', + '#FFC107', +]; + +export const _products = [...Array(24)].map((_, index) => { + const setIndex = index + 1; + + return { + id: _id(index), + price: _price(index), + name: _productNames(index), + priceSale: setIndex % 3 ? null : _price(index), + coverUrl: `/assets/images/product/product-${setIndex}.webp`, + colors: + (setIndex === 1 && COLORS.slice(0, 2)) || + (setIndex === 2 && COLORS.slice(1, 3)) || + (setIndex === 3 && COLORS.slice(2, 4)) || + (setIndex === 4 && COLORS.slice(3, 6)) || + (setIndex === 23 && COLORS.slice(4, 6)) || + (setIndex === 24 && COLORS.slice(5, 6)) || + COLORS, + status: + ([1, 3, 5].includes(setIndex) && 'sale') || ([4, 8, 12].includes(setIndex) && 'new') || '', + }; +}); + +// ---------------------------------------------------------------------- + +export const _langs = [ + { + value: 'en', + label: 'English', + icon: '/assets/icons/flags/ic-flag-en.svg', + }, + { + value: 'de', + label: 'German', + icon: '/assets/icons/flags/ic-flag-de.svg', + }, + { + value: 'fr', + label: 'French', + icon: '/assets/icons/flags/ic-flag-fr.svg', + }, +]; + +// ---------------------------------------------------------------------- + +export const _timeline = [...Array(5)].map((_, index) => ({ + id: _id(index), + title: [ + '1983, orders, $4220', + '12 Invoices have been paid', + 'Order #37745 from September', + 'New order placed #XF-2356', + 'New order placed #XF-2346', + ][index], + type: `order${index + 1}`, + time: _times(index), +})); + +export const _traffic = [ + { + value: 'facebook', + label: 'Facebook', + total: 19500, + }, + { + value: 'google', + label: 'Google', + total: 91200, + }, + { + value: 'linkedin', + label: 'Linkedin', + total: 69800, + }, + { + value: 'twitter', + label: 'Twitter', + total: 84900, + }, +]; + +export const _tasks = Array.from({ length: 5 }, (_, index) => ({ + id: _id(index), + name: _taskNames(index), +})); + +// ---------------------------------------------------------------------- + +export const _notifications = [ + { + id: _id(1), + title: 'Your order is placed', + description: 'waiting for shipping', + avatarUrl: null, + type: 'order-placed', + postedAt: _times(1), + isUnRead: true, + }, + { + id: _id(2), + title: _fullName(2), + description: 'answered to your comment on the Minimal', + avatarUrl: '/assets/images/avatar/avatar-2.webp', + type: 'friend-interactive', + postedAt: _times(2), + isUnRead: true, + }, + { + id: _id(3), + title: 'You have new message', + description: '5 unread messages', + avatarUrl: null, + type: 'chat-message', + postedAt: _times(3), + isUnRead: false, + }, + { + id: _id(4), + title: 'You have new mail', + description: 'sent from Guido Padberg', + avatarUrl: null, + type: 'mail', + postedAt: _times(4), + isUnRead: false, + }, + { + id: _id(5), + title: 'Delivery processing', + description: 'Your order is being shipped', + avatarUrl: null, + type: 'order-shipped', + postedAt: _times(5), + isUnRead: false, + }, +]; diff --git a/frontend/src/_mock/_mock.ts b/frontend/src/_mock/_mock.ts new file mode 100644 index 000000000..46f120bb1 --- /dev/null +++ b/frontend/src/_mock/_mock.ts @@ -0,0 +1,232 @@ +export const _id = (index: number) => `e99f09a7-dd88-49d5-b1c8-1daf80c2d7b${index}`; + +export const _times = (index: number) => + // 'MM/DD/YYYY' + [ + '11/08/2023', + '04/09/2024', + '09/12/2023', + '01/01/2024', + '04/23/2024', + '02/29/2024', + '05/14/2024', + '01/13/2024', + '06/22/2024', + '10/05/2023', + '07/11/2024', + '05/22/2024', + '03/29/2024', + '08/29/2023', + '11/19/2023', + '10/24/2023', + '12/02/2023', + '02/13/2024', + '09/19/2023', + '04/17/2024', + '12/18/2023', + '06/27/2024', + '10/19/2023', + '08/09/2024', + ][index]; + +export const _fullName = (index: number) => + [ + 'Billy Stoltenberg', + 'Eloise Ebert', + 'Teresa Luettgen', + 'Salvador Mayert', + 'Dr. Guadalupe Rath', + 'Kelvin Pouros', + 'Thelma Langworth', + 'Kristen Wunsch', + 'Steve Welch', + 'Brian Jacobs', + 'Lillie Schultz', + 'Mr. Conrad Spinka', + 'Charlene Krajcik', + 'Kerry Kuhlman', + 'Betty Hammes', + 'Tony Paucek PhD', + 'Sherri Davis', + 'Angel Rolfson-Kulas', + 'Dr. Lee Doyle-Grant', + 'Cheryl Romaguera', + 'Billy Braun', + 'Adam Trantow', + 'Brandon Von', + 'Willis Ankunding', + ][index]; + +export const _price = (index: number) => + [ + 35.17, 57.22, 64.78, 50.79, 9.57, 61.46, 96.73, 63.04, 33.18, 36.3, 54.42, 20.52, 62.82, 19.96, + 25.93, 70.39, 23.11, 67.23, 14.31, 31.5, 26.72, 44.8, 37.87, 75.53, + ][index]; + +export const _company = (index: number) => + [ + 'Medhurst, Moore and Franey', + 'Hahn, Homenick and Lind', + 'Larkin LLC', + 'Stamm, Larson and Mertz', + 'Spencer, Raynor and Langosh', + 'Lehner - Feeney', + 'Leuschke, Harris and Kuhlman', + 'Gutmann - Kassulke', + 'Turcotte - Runolfsson', + 'Howe - Anderson', + 'Sipes - Yost', + 'Johns - Aufderhar', + 'Schmidt LLC', + 'Smitham - Gerlach', + 'Waelchi - VonRueden', + 'Padberg - Macejkovic', + 'Lemke - Ferry', + 'Koch and Sons', + 'Klein - Rolfson', + 'Weimann LLC', + 'White, Cassin and Goldner', + 'Mohr, Langworth and Hills', + 'Mitchell, Volkman and Prosacco', + 'Streich Group', + ][index]; + +export const _boolean = (index: number) => + [ + true, + false, + true, + false, + true, + true, + true, + false, + false, + true, + false, + true, + true, + false, + true, + false, + false, + true, + false, + false, + false, + true, + true, + false, + ][index]; + +export const _postTitles = (index: number) => + [ + 'Whiteboard Templates By Industry Leaders', + 'Tesla Cybertruck-inspired camper trailer for Tesla fans who can’t just wait for the truck!', + 'Designify Agency Landing Page Design', + '✹What is Done is Done ✹', + 'Fresh Prince', + 'Six Socks Studio', + 'vincenzo de cotiis’ crossing over showcases a research on contamination', + 'Simple, Great Looking Animations in Your Project | Video Tutorial', + '40 Free Serif Fonts for Digital Designers', + 'Examining the Evolution of the Typical Web Design Client', + 'Katie Griffin loves making that homey art', + 'The American Dream retold through mid-century railroad graphics', + 'Illustration System Design', + 'CarZio-Delivery Driver App SignIn/SignUp', + 'How to create a client-serverless Jamstack app using Netlify, Gatsby and Fauna', + 'Tylko Organise effortlessly -3D & Motion Design', + 'RAYO ?? A expanded visual arts festival identity', + 'Anthony Burrill and Wired mag’s Andrew Diprose discuss how they made January’s Change Everything cover', + 'Inside the Mind of Samuel Day', + 'Portfolio Review: Is This Portfolio Too Creative?', + 'Akkers van Margraten', + 'Gradient Ticket icon', + 'Here’s a Dyson motorcycle concept that doesn’t ‘suck’!', + 'How to Animate a SVG with border-image', + ][index]; + +export const _description = (index: number) => + [ + 'The Nagasaki Lander is the trademarked name of several series of Nagasaki sport bikes, that started with the 1984 ABC800J', + 'New range of formal shirts are designed keeping you in mind. With fits and styling that will make you stand apart', + 'Andy shoes are designed to keeping in mind durability as well as trends, the most stylish range of shoes & sandals', + 'The Football Is Good For Training And Recreational Purposes', + 'New ABC 13 9370, 13.3, 5th Gen CoreA5-8250U, 8GB RAM, 256GB SSD, power UHD Graphics, OS 10 Home, OS Office A & J 2016', + 'Andy shoes are designed to keeping in mind durability as well as trends, the most stylish range of shoes & sandals', + 'Carbonite web goalkeeper gloves are ergonomically designed to give easy fit', + 'The Apollotech B340 is an affordable wireless mouse with reliable connectivity, 12 months battery life and modern design', + 'The Nagasaki Lander is the trademarked name of several series of Nagasaki sport bikes, that started with the 1984 ABC800J', + 'The automobile layout consists of a front-engine design, with transaxle-type transmissions mounted at the rear of the engine and four wheel drive', + 'The automobile layout consists of a front-engine design, with transaxle-type transmissions mounted at the rear of the engine and four wheel drive', + 'The Apollotech B340 is an affordable wireless mouse with reliable connectivity, 12 months battery life and modern design', + 'New range of formal shirts are designed keeping you in mind. With fits and styling that will make you stand apart', + "Boston's most advanced compression wear technology increases muscle oxygenation, stabilizes active muscles", + 'New range of formal shirts are designed keeping you in mind. With fits and styling that will make you stand apart', + 'Andy shoes are designed to keeping in mind durability as well as trends, the most stylish range of shoes & sandals', + 'Andy shoes are designed to keeping in mind durability as well as trends, the most stylish range of shoes & sandals', + 'The beautiful range of Apple NaturalĂ© that has an exciting mix of natural ingredients. With the Goodness of 100% Natural Ingredients', + "Boston's most advanced compression wear technology increases muscle oxygenation, stabilizes active muscles", + 'New ABC 13 9370, 13.3, 5th Gen CoreA5-8250U, 8GB RAM, 256GB SSD, power UHD Graphics, OS 10 Home, OS Office A & J 2016', + 'The Nagasaki Lander is the trademarked name of several series of Nagasaki sport bikes, that started with the 1984 ABC800J', + 'Ergonomic executive chair upholstered in bonded black leather and PVC padded seat and back for all-day comfort and support', + 'The Football Is Good For Training And Recreational Purposes', + 'The automobile layout consists of a front-engine design, with transaxle-type transmissions mounted at the rear of the engine and four wheel drive', + ][index]; + +export const _taskNames = (index: number) => + [ + `Prepare Monthly Financial Report`, + `Design New Marketing Campaign`, + `Analyze Customer Feedback`, + `Update Website Content`, + `Conduct Market Research`, + `Develop Software Application`, + `Organize Team Meeting`, + `Create Social Media Posts`, + `Review Project Plan`, + `Implement Security Protocols`, + `Write Technical Documentation`, + `Test New Product Features`, + `Manage Client Inquiries`, + `Train New Employees`, + `Coordinate Logistics`, + `Monitor Network Performance`, + `Develop Training Materials`, + `Draft Press Release`, + `Prepare Budget Proposal`, + `Evaluate Vendor Proposals`, + `Perform Data Analysis`, + `Conduct Quality Assurance`, + `Plan Event Logistics`, + `Optimize SEO Strategies`, + ][index]; + +export const _productNames = (index: number) => + [ + 'Nike Air Force 1 NDESTRUKT', + 'Nike Space Hippie 04', + 'Nike Air Zoom Pegasus 37 A.I.R. Chaz Bear', + 'Nike Blazer Low 77 Vintage', + 'Nike ZoomX SuperRep Surge', + 'Zoom Freak 2', + 'Nike Air Max Zephyr', + 'Jordan Delta', + 'Air Jordan XXXV PF', + 'Nike Waffle Racer Crater', + 'Kyrie 7 EP Sisterhood', + 'Nike Air Zoom BB NXT', + 'Nike Air Force 1 07 LX', + 'Nike Air Force 1 Shadow SE', + 'Nike Air Zoom Tempo NEXT%', + 'Nike DBreak-Type', + 'Nike Air Max Up', + 'Nike Air Max 270 React ENG', + 'NikeCourt Royale', + 'Nike Air Zoom Pegasus 37 Premium', + 'Nike Air Zoom SuperRep', + 'NikeCourt Royale', + 'Nike React Art3mis', + 'Nike React Infinity Run Flyknit A.I.R. Chaz Bear', + ][index]; diff --git a/frontend/src/_mock/index.ts b/frontend/src/_mock/index.ts new file mode 100644 index 000000000..6a726d939 --- /dev/null +++ b/frontend/src/_mock/index.ts @@ -0,0 +1,2 @@ +export * from './_mock'; +export * from './_data'; diff --git a/frontend/src/api/admin.ts b/frontend/src/api/admin.ts new file mode 100644 index 000000000..9d28904c3 --- /dev/null +++ b/frontend/src/api/admin.ts @@ -0,0 +1,62 @@ +import { axiosClient } from "src/lib/axios"; + +import type { PaginationFilter } from "./types/common"; +import type { ListUserResponse } from "./types/user.typs"; +import type { VenueListResponse } from "./types/venue.type"; + + +export class AdminApiService { + + /** + * Get list of users with pagination + */ + static async listUsers({ page, limit, search }: PaginationFilter) { + const response = + await axiosClient.get( + '/users', + { + params: { offset: page * limit, limit, search }, + } + ); + return response.data as ListUserResponse + } + + /** + * Get list of users with pagination + */ + static async listVenues(page: number = 1, limit: number = 10) { + const response = + await axiosClient.get( + '/admin/venues', + { + params: { page, limit }, + } + ); + return response.data as VenueListResponse + } + + /** + * Approve Venue + */ + static async approveVenue(venueId: string) { + const response = await axiosClient.post(`/admin/venues/${venueId}/approve`); + return response.data as VenueListResponse + } + + /** + * Reject Venue + */ + static async rejectVenue(venueId: string) { + const response = await axiosClient.post(`/admin/venues/${venueId}/reject`); + return response.data as VenueListResponse + } + + /** + * Create New User + */ + static async createUser(data: any) { + const response = await axiosClient.post(`/admin/users`, data); + return response.data as VenueListResponse + } + +} \ No newline at end of file diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts new file mode 100644 index 000000000..5470746e6 --- /dev/null +++ b/frontend/src/api/auth.ts @@ -0,0 +1,127 @@ + +import { axiosClient } from 'src/lib/axios'; + +import type { + AuthResponse, + LoginRequest, + RegisterRequest, +} from './types/auth.type'; + +export class AuthApiService { + /** + * Login + */ + static async login( + payload: LoginRequest, + ): Promise { + const response = + await axiosClient.post( + '/auth/login', + payload, + ); + + return response.data; + } + + /** + * Register + */ + static async register( + payload: RegisterRequest, + ): Promise { + const response = + await axiosClient.post( + '/auth/register', + payload, + ); + + return response.data; + } + + /** + * Current User + */ + static async me() { + const response = + await axiosClient.get('/auth/me'); + + return response.data; + } + + /** + * Logout + */ + static async logout() { + await axiosClient.post('/auth/logout'); + } + + /** + * Refresh Token + */ + static async refreshToken( + refreshToken: string, + ) { + const response = + await axiosClient.post( + '/auth/refresh', + { + refreshToken, + }, + ); + + return response.data; + } + + /** + * Forgot Password + */ + static async forgotPassword( + email: string, + ) { + const response = + await axiosClient.post( + '/auth/forgot-password', + { + email, + }, + ); + + return response.data; + } + + /** + * Reset Password + */ + static async resetPassword( + token: string, + password: string, + ) { + const response = + await axiosClient.post( + '/auth/reset-password', + { + token, + password, + }, + ); + + return response.data; + } + + /** + * Verify Email + */ + static async verifyEmail( + token: string, + ) { + const response = + await axiosClient.post( + '/auth/verify-email', + { + token, + }, + ); + + return response.data; + } +} \ No newline at end of file diff --git a/frontend/src/api/booking.ts b/frontend/src/api/booking.ts new file mode 100644 index 000000000..a1f53f880 --- /dev/null +++ b/frontend/src/api/booking.ts @@ -0,0 +1,23 @@ +import { axiosClient } from "src/lib/axios"; + + +export class BookingApiService { + + /** + * Get list of users with pagination + */ + static async getAllBookingsForOwner() { + const response = await axiosClient.get('/bookings/owner/all-bookings'); + return response.data + } + + /** + * Get list of users with pagination + */ + static async getBookingDetailsForOwner(bookingId: string) { + const response = await axiosClient.get('/bookings/' + bookingId); + return response.data + } + + +} \ No newline at end of file diff --git a/frontend/src/api/dashboard.ts b/frontend/src/api/dashboard.ts new file mode 100644 index 000000000..80e201155 --- /dev/null +++ b/frontend/src/api/dashboard.ts @@ -0,0 +1,41 @@ +import { axiosClient } from 'src/lib/axios'; + +export interface AdminDashboardDto { + totalUsers: number; + totalOwners: number; + totalVenues: number; + venueStatusSummary: { status: string; count: number }[]; + approvalPendingVenues: { + id: string; + title: string; + addressLine1: string; + venueType: string; + capacity: number; + }[]; +} + +export interface OwnerDashboardDto { + venueCount: number; + bookingCount: number; + totalRevenue: number; + recentBookings: { + id: string; + venueName: string; + startDate: string; + endDate: string; + guestsCount: number; + amount: number; + }[]; +} + +export class DashboardApiService { + static async getAdminDashboard(): Promise { + const response = await axiosClient.get('/dashboard/admin'); + return response.data; + } + + static async getOwnerDashboard(): Promise { + const response = await axiosClient.get('/dashboard/owner'); + return response.data; + } +} diff --git a/frontend/src/api/payment.ts b/frontend/src/api/payment.ts new file mode 100644 index 000000000..f639d2ad2 --- /dev/null +++ b/frontend/src/api/payment.ts @@ -0,0 +1,20 @@ +import { axiosClient } from 'src/lib/axios'; + +import type { + VerifyPaymentRequest, + VerifyPaymentResponse, + InitiatePaymentRequest, + InitiatePaymentResponse, +} from './types/payment.type'; + +export class PaymentApiService { + static async initiatePayment(data: InitiatePaymentRequest): Promise { + const response = await axiosClient.post('/payment/initiate', data); + return response.data; + } + + static async verifyPayment(data: VerifyPaymentRequest): Promise { + const response = await axiosClient.post('/payment/verify', data); + return response.data; + } +} diff --git a/frontend/src/api/types/auth.type.ts b/frontend/src/api/types/auth.type.ts new file mode 100644 index 000000000..001852d91 --- /dev/null +++ b/frontend/src/api/types/auth.type.ts @@ -0,0 +1,35 @@ +export enum UserRole { + USER = 'USER', + VENUE_OWNER = 'VENUE_OWNER', + ADMIN = 'ADMIN', +} + +export interface User { + id: string; + email: string; + firstName: string; + lastName: string; + role: UserRole; +} + +export interface Tokens { + accessToken: string; + refreshToken: string; +} + +export interface AuthResponse { + user: User; + accessToken: string; + refreshToken: string; +} + +export interface LoginRequest { + email: string; + password: string; +} + +export interface RegisterRequest { + name: string; + email: string; + password: string; +} \ No newline at end of file diff --git a/frontend/src/api/types/common.ts b/frontend/src/api/types/common.ts new file mode 100644 index 000000000..c1d7f443a --- /dev/null +++ b/frontend/src/api/types/common.ts @@ -0,0 +1,15 @@ +export interface Pagination { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; + hasNext: boolean; + hasPrevious: boolean; +} + +export interface PaginationFilter { + search?: string, + limit: number, + page: number +} \ No newline at end of file diff --git a/frontend/src/api/types/payment.type.ts b/frontend/src/api/types/payment.type.ts new file mode 100644 index 000000000..921ac7d2f --- /dev/null +++ b/frontend/src/api/types/payment.type.ts @@ -0,0 +1,38 @@ +export enum PaymentStatus { + PENDING = 'PENDING', + INITIATED = 'INITIATED', + PAID = 'PAID', + FAILED = 'FAILED', + REFUNDED = 'REFUNDED', +} + +export interface InitiatePaymentRequest { + bookingId: string; + customerPhone: string; +} + +export interface RazorpayCheckoutData { + key: string; + orderId: string; + amount: number; + currency: string; +} + +export interface InitiatePaymentResponse { + paymentId: string; + providerOrderId: string; + checkoutData: RazorpayCheckoutData; +} + +export interface VerifyPaymentRequest { + providerOrderId: string; + providerPaymentId: string; + signature: string; +} + +export interface VerifyPaymentResponse { + paymentId: string; + bookingId: string; + status: PaymentStatus | string; + paidAt: string; +} diff --git a/frontend/src/api/types/user.typs.ts b/frontend/src/api/types/user.typs.ts new file mode 100644 index 000000000..5f613b6f6 --- /dev/null +++ b/frontend/src/api/types/user.typs.ts @@ -0,0 +1,16 @@ +import type { Pagination } from "./common"; +import type { UserRole } from "./auth.type"; + +interface User { + id: string; + email: string; + firstName: string; + lastName: string; + phone: string | null | undefined; + status: "ACTIVE" | "INACTIVE"; + role: UserRole; + createdAt: string; +} + + +export interface ListUserResponse extends Pagination { } \ No newline at end of file diff --git a/frontend/src/api/types/venue.type.ts b/frontend/src/api/types/venue.type.ts new file mode 100644 index 000000000..eeb0c17ed --- /dev/null +++ b/frontend/src/api/types/venue.type.ts @@ -0,0 +1,321 @@ +// ====================================================== +// BOOK MY VENUE - FRONTEND TYPES +// ====================================================== + +import type { Pagination } from "./common"; +import type { PaymentStatus } from "./payment.type"; + +export enum VenueStatus { + PENDING = "PENDING", + APPROVED = "APPROVED", + REJECTED = "REJECTED", + SUSPENDED = "SUSPENDED", +} + +export enum VenueType { + AUDITORIUM = "AUDITORIUM", + BANQUET_HALL = "BANQUET_HALL", + CONFERENCE_ROOM = "CONFERENCE_ROOM", + MEETING_ROOM = "MEETING_ROOM", + CAFE = "CAFE", + RESTAURANT = "RESTAURANT", + HOTEL = "HOTEL", + RESORT = "RESORT", + PARTY_HALL = "PARTY_HALL", + EVENT_SPACE = "EVENT_SPACE", + OTHER = "OTHER", +} + +// ====================================================== +// COMMON +// ====================================================== + +export interface Coordinates { + latitude: number; + longitude: number; +} + +export interface Address { + addressLine1: string; + addressLine2?: string; + city: string; + state: string; + country: string; + postalCode: string; +} + +// ====================================================== +// USER +// ====================================================== + +export interface UserSummary { + id: string; + firstName: string; + lastName?: string; + email?: string; + avatar?: string; +} + +// ====================================================== +// OWNER +// ====================================================== + +export interface VenueOwner { + id: string; + firstName: string; + lastName?: string; + email: string; + phone?: string; +} + +// ====================================================== +// AMENITIES +// ====================================================== + +export interface Amenity { + id: string; + name: string; + description?: string; + icon?: string; +} + +// ====================================================== +// IMAGES +// ====================================================== + +export interface VenueImage { + id: string; + imageUrl: string; + sortOrder: number; +} + +// ====================================================== +// REVIEWS +// ====================================================== + +export interface VenueReview { + id: string; + rating: number; + comment?: string; + createdAt: string; + user: UserSummary; +} + + +// ====================================================== +// VENUE LIST CARD +// ====================================================== + +export interface VenueCard { + id: string; + title: string; + description?: string; + venueType: VenueType | string; + city: string; + state: string; + country: string; + capacity: number; + pricePerDay: number; + thumbnail?: string; + images?: string[]; + averageRating?: number; + reviewCount?: number; + isSaved?: boolean; + status?: string; + amenities?: string[]; +} + +// ====================================================== +// VENUE DETAILS +// ====================================================== + +export interface VenueDetails { + id: string; + ownerId?: string; + title: string; + description: string; + venueType: VenueType | string; + status: string; + // flat address fields returned by API + addressLine1?: string; + addressLine2?: string; + city?: string; + state?: string; + country?: string; + postalCode?: string; + latitude?: number; + longitude?: number; + // nested address (optional, for backward compat) + address?: Address; + location?: Coordinates; + capacity: number; + pricePerDay: number; + owner?: VenueOwner; + amenities: string[]; + images: string[]; + averageRating?: number; + reviewCount?: number; + createdAt: string; + updatedAt?: string; +} + +// ====================================================== +// VENUE SEARCH +// ====================================================== + +export interface VenueSearchFilters { + query?: string; + city?: string; + state?: string; + venueType?: string; + minPrice?: number; + maxPrice?: number; + minCapacity?: number; + maxCapacity?: number; + amenities?: string[]; + latitude?: number; + longitude?: number; + radiusKm?: number; + page?: number; + limit?: number; + sortBy?: + | "price_asc" + | "price_desc" + | "rating_desc" + | "newest"; +} + + +// ====================================================== +// AVAILABILITY +// ====================================================== + +export interface VenueAvailability { + venueId: string; + date: string; + available: boolean; +} + +export interface VenueAvailabilityRange { + venueId: string; + startDate: string; + endDate: string; + unavailableDates: string[]; +} + +// ====================================================== +// SAVED VENUES +// ====================================================== + +export interface SavedVenue { + id: string; + createdAt: string; + venue: VenueCard; +} + +// ====================================================== +// BOOKINGS +// ====================================================== + +export enum BookingStatus { + BOOKED = "BOOKED", + CANCELLED = "CANCELLED", +} + +export interface BookingSummary { + id: string; + venueName: string; + startDate: string; + endDate: string; + totalAmount: number; + status: BookingStatus; + paymentStatus: PaymentStatus + createdAt: string; + venue: VenueCard; +} + +// ====================================================== +// OWNER DASHBOARD +// ====================================================== + +export interface VenueAnalytics { + venueId: string; + totalBookings: number; + totalRevenue: number; + averageRating: number; + reviewCount: number; + occupancyRate: number; +} + +export interface OwnerVenue { + id: string; + title: string; + venueType: string; + status: VenueStatus; + capacity: number; + pricePerDay: number; + totalBookings: number; + totalRevenue: number; + createdAt: string; +} + +// ====================================================== +// CREATE VENUE +// ====================================================== + +export interface CreateVenueRequest { + title: string; + description: string; + venueType: string; + addressLine1: string; + addressLine2?: string; + city: string; + state: string; + country: string; + postalCode: string; + latitude?: number; + longitude?: number; + capacity: number; + pricePerDay: number; + amenityIds: string[]; + imageUrls: string[]; +} + +// ====================================================== +// UPDATE VENUE +// ====================================================== + +export interface UpdateVenueRequest { + title?: string; + description?: string; + venueType?: string; + addressLine1?: string; + addressLine2?: string; + city?: string; + state?: string; + country?: string; + postalCode?: string; + latitude?: number; + longitude?: number; + capacity?: number; + pricePerDay?: number; + amenityIds?: string[]; + imageUrls?: string[]; +} + +// ====================================================== +// API RESPONSES +// ====================================================== + +export interface VenueListResponse extends Pagination { } + +export interface VenueDetailsResponse { + data: VenueDetails; +} + +export interface VenueAnalyticsResponse { + data: VenueAnalytics; +} + + +export interface BookingHistoryResponse extends Pagination { } \ No newline at end of file diff --git a/frontend/src/api/user-booking.ts b/frontend/src/api/user-booking.ts new file mode 100644 index 000000000..b02d3de99 --- /dev/null +++ b/frontend/src/api/user-booking.ts @@ -0,0 +1,101 @@ +import { axiosClient } from 'src/lib/axios'; + +import type { PaymentStatus } from './types/payment.type'; +import type { BookingStatus, BookingSummary } from './types/venue.type'; + +interface Pagination { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; + hasNext: boolean; + hasPrevious: boolean; +} + +export interface BookingDetails { + id?: string; + bookingId?: string; + venueId?: string; + venueName?: string; + venueCity?: string; + venueState?: string; + venueThumbnail?: string; + venue?: { + id: string; + title: string; + address?: string; + images?: string[]; + }; + user?: { + id: string; + firstName: string; + lastName?: string; + email: string; + phone?: string | null; + }; + startDate: string; + endDate: string; + guestsCount: number; + totalAmount: number; + status: BookingStatus; + paymentStatus?: PaymentStatus; + specialRequests?: string; + createdAt: string; + updatedAt?: string; +} + +export interface CreateBookingRequest { + venueId: string; + startDate: string; + endDate: string; + guestsCount: number; + specialRequests?: string; +} + +export interface BookingPriceBreakdown { + baseAmount: number; + days: number; + pricePerDay: number; + serviceFee: number; + totalAmount: number; +} + +export class UserBookingApiService { + static async createBooking(data: CreateBookingRequest): Promise { + const response = await axiosClient.post('/bookings', data); + return response.data; + } + + static async getMyBookings( + page: number = 1, + limit: number = 10, + status?: BookingStatus, + ): Promise> { + const response = await axiosClient.get('/bookings/my-bookings', { + params: { page, limit, ...(status ? { status } : {}) }, + }); + return response.data; + } + + static async getBookingDetails(bookingId: string): Promise { + const response = await axiosClient.get(`/bookings/${bookingId}`); + return response.data?.data ?? response.data; + } + + static async cancelBooking(bookingId: string): Promise { + const response = await axiosClient.post(`/bookings/${bookingId}/cancel`); + return response.data; + } + + static async calculatePrice( + venueId: string, + startDate: string, + endDate: string, + ): Promise { + const response = await axiosClient.get(`/bookings/calculate-price`, { + params: { venueId, startDate, endDate }, + }); + return response.data; + } +} diff --git a/frontend/src/api/user-favorites.ts b/frontend/src/api/user-favorites.ts new file mode 100644 index 000000000..d665ded9a --- /dev/null +++ b/frontend/src/api/user-favorites.ts @@ -0,0 +1,33 @@ +import { axiosClient } from 'src/lib/axios'; + +import type { SavedVenue } from './types/venue.type'; + +interface Pagination { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; + hasNext: boolean; + hasPrevious: boolean; +} + +export class UserFavoritesApiService { + static async getSavedVenues( + page: number = 1, + limit: number = 12, + ): Promise> { + const response = await axiosClient.get('/saved-venues', { + params: { page, limit }, + }); + return response.data; + } + + static async saveVenue(venueId: string): Promise { + await axiosClient.post(`/saved-venues/${venueId}`); + } + + static async unsaveVenue(venueId: string): Promise { + await axiosClient.delete(`/saved-venues/${venueId}`); + } +} diff --git a/frontend/src/api/user.ts b/frontend/src/api/user.ts new file mode 100644 index 000000000..882feed1b --- /dev/null +++ b/frontend/src/api/user.ts @@ -0,0 +1,31 @@ +import { axiosClient } from "src/lib/axios"; + +import type { ListUserResponse } from "./types/user.typs"; + + +export class UserApiService { + /** + * Get current user profile + */ + static async me() { + const response = + await axiosClient.get( + '/users/me', + ); + return response.data; + } + + /** + * Get list of users with pagination + */ + static async listUsers(page: number = 1, limit: number = 10) { + const response = + await axiosClient.get( + '/users', + { + params: { page, limit }, + } + ); + return response.data as ListUserResponse + } +} \ No newline at end of file diff --git a/frontend/src/api/venue-public.ts b/frontend/src/api/venue-public.ts new file mode 100644 index 000000000..f9b8e02f3 --- /dev/null +++ b/frontend/src/api/venue-public.ts @@ -0,0 +1,66 @@ +import { axiosClient } from 'src/lib/axios'; + +import type { + VenueReview, + VenueDetails, + VenueListResponse, + VenueSearchFilters, + VenueAvailabilityRange, +} from './types/venue.type'; + +interface Pagination { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; + hasNext: boolean; + hasPrevious: boolean; +} + +export class VenuePublicApiService { + static async searchVenues(filters: VenueSearchFilters): Promise { + const response = await axiosClient.get('/venues', { params: filters }); + return response.data; + } + + static async getFeaturedVenues(): Promise { + const response = await axiosClient.get('/venues', { params: { limit: 6 } }); + return response.data; + } + + static async getVenueDetails(id: string): Promise { + const response = await axiosClient.get(`/venues/${id}`); + return response.data?.data ?? response.data; + } + + static async getVenueAvailability( + id: string, + startDate: string, + endDate: string, + ): Promise { + const response = await axiosClient.get(`/venues/${id}/availability`, { + params: { startDate, endDate }, + }); + return response.data; + } + + static async getVenueReviews( + id: string, + page: number = 1, + limit: number = 10, + ): Promise> { + const response = await axiosClient.get(`/venues/${id}/reviews`, { + params: { page, limit }, + }); + return response.data; + } + + static async saveVenue(venueId: string): Promise { + await axiosClient.post(`/saved-venues/${venueId}`); + } + + static async unsaveVenue(venueId: string): Promise { + await axiosClient.delete(`/saved-venues/${venueId}`); + } +} diff --git a/frontend/src/api/venue.ts b/frontend/src/api/venue.ts new file mode 100644 index 000000000..5f948b5c1 --- /dev/null +++ b/frontend/src/api/venue.ts @@ -0,0 +1,51 @@ +import { axiosClient } from "src/lib/axios"; + +import type { VenueCard } from "./types/venue.type"; +import type { Pagination, PaginationFilter } from "./types/common"; + +export interface CreateVenueResponse { + venueId: string; +} + +export interface UploadVenueImagesResponse { + message: string; +} + +export class VenueApiService { + + /** + * Get list of venues owned by the current user + */ + static async listMyVenues({ limit, page, search }: PaginationFilter) { + const response = await axiosClient.get('/venues/my-venues', { + params: { + offset: page * limit, + limit, + search + } + }); + return response.data as Pagination + } + + static async createVenue(data: Record) { + const response = await axiosClient.post('/venues', data); + return response.data as CreateVenueResponse; + } + + static async uploadVenueImages(venueId: string, files: File[]) { + const formData = new FormData(); + files.forEach((file) => formData.append('files', file)); + + const response = await axiosClient.post( + `/venues/${venueId}/images`, + formData, + { + headers: { + 'Content-Type': 'multipart/form-data', + }, + }, + ); + return response.data; + } + +} \ No newline at end of file diff --git a/frontend/src/app.tsx b/frontend/src/app.tsx new file mode 100644 index 000000000..a8b557a03 --- /dev/null +++ b/frontend/src/app.tsx @@ -0,0 +1,51 @@ +import 'src/global.css'; + +import { useEffect } from 'react'; +import { + QueryClient, + QueryClientProvider, +} from '@tanstack/react-query' + +import { usePathname } from 'src/routes/hooks'; + +import { ThemeProvider } from 'src/theme/theme-provider'; + +import { NovuProvider } from 'src/components/novu/novu-provider'; + +import { AuthProvider } from './context/auth/auth-provider'; + +// ---------------------------------------------------------------------- + +const queryClient = new QueryClient() + +type AppProps = { + children: React.ReactNode; +}; + +export default function App({ children }: AppProps) { + useScrollToTop(); + + return ( + + + + + {children} + + + + + ); +} + +// ---------------------------------------------------------------------- + +function useScrollToTop() { + const pathname = usePathname(); + + useEffect(() => { + window.scrollTo(0, 0); + }, [pathname]); + + return null; +} diff --git a/frontend/src/components/buttons/blue-button.tsx b/frontend/src/components/buttons/blue-button.tsx new file mode 100644 index 000000000..e4d500dcc --- /dev/null +++ b/frontend/src/components/buttons/blue-button.tsx @@ -0,0 +1,49 @@ +import { Link } from "react-router-dom"; + +import { Button } from "@mui/material"; + +import { Iconify } from "../iconify"; + +type ButtonProps = { + onClick?: React.MouseEventHandler + href?: string + label: string +} + +export function BlueButton({ href, onClick, label }: ButtonProps) { + + if (href) { + + return ( + + + + ) + } + + return ( + + ) +} \ No newline at end of file diff --git a/frontend/src/components/chart/chart.tsx b/frontend/src/components/chart/chart.tsx new file mode 100644 index 000000000..1d78f38b8 --- /dev/null +++ b/frontend/src/components/chart/chart.tsx @@ -0,0 +1,48 @@ +import { lazy, Suspense } from 'react'; +import { useIsClient } from 'minimal-shared/hooks'; +import { mergeClasses } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; + +import { chartClasses } from './classes'; +import { ChartLoading } from './components'; + +import type { ChartProps } from './types'; + +// ---------------------------------------------------------------------- + +const LazyChart = lazy(() => + import('react-apexcharts').then((module) => ({ default: module.default })) +); + +export function Chart({ type, series, options, slotProps, className, sx, ...other }: ChartProps) { + const isClient = useIsClient(); + + const renderFallback = () => ; + + return ( + + {isClient ? ( + + + + ) : ( + renderFallback() + )} + + ); +} + +// ---------------------------------------------------------------------- + +const ChartRoot = styled('div')(({ theme }) => ({ + width: '100%', + flexShrink: 0, + position: 'relative', + borderRadius: theme.shape.borderRadius * 1.5, +})); diff --git a/frontend/src/components/chart/classes.ts b/frontend/src/components/chart/classes.ts new file mode 100644 index 000000000..5557a5902 --- /dev/null +++ b/frontend/src/components/chart/classes.ts @@ -0,0 +1,19 @@ +import { createClasses } from 'src/theme/create-classes'; + +// ---------------------------------------------------------------------- + +export const chartClasses = { + root: createClasses('chart__root'), + loading: createClasses('chart__loading'), + legends: { + root: createClasses('chart__legends__root'), + item: { + wrap: createClasses('chart__legends__item__wrap'), + root: createClasses('chart__legends__item__root'), + dot: createClasses('chart__legends__item__dot'), + icon: createClasses('chart__legends__item__icon'), + label: createClasses('chart__legends__item__label'), + value: createClasses('chart__legends__item__value'), + }, + }, +}; diff --git a/frontend/src/components/chart/components/chart-legends.tsx b/frontend/src/components/chart/components/chart-legends.tsx new file mode 100644 index 000000000..ec7c11304 --- /dev/null +++ b/frontend/src/components/chart/components/chart-legends.tsx @@ -0,0 +1,128 @@ +import { mergeClasses } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; + +import { chartClasses } from '../classes'; + +// ---------------------------------------------------------------------- + +export type ChartLegendsProps = React.ComponentProps & { + labels?: string[]; + colors?: string[]; + values?: string[]; + sublabels?: string[]; + icons?: React.ReactNode[]; + slotProps?: { + wrapper?: React.ComponentProps; + root?: React.ComponentProps; + dot?: React.ComponentProps; + icon?: React.ComponentProps; + value?: React.ComponentProps; + label?: React.ComponentProps; + }; +}; + +export function ChartLegends({ + sx, + className, + slotProps, + icons = [], + values = [], + labels = [], + colors = [], + sublabels = [], + ...other +}: ChartLegendsProps) { + return ( + + {labels.map((series, index) => ( + + + {icons.length ? ( + + {icons[index]} + + ) : ( + + )} + + + {series} + {!!sublabels.length && <> {` (${sublabels[index]})`}} + + + + {values && ( + + {values[index]} + + )} + + ))} + + ); +} + +// ---------------------------------------------------------------------- + +const ListRoot = styled('ul')(({ theme }) => ({ + display: 'flex', + flexWrap: 'wrap', + gap: theme.spacing(2), +})); + +const ItemWrap = styled('li')(() => ({ + display: 'inline-flex', + flexDirection: 'column', +})); + +const ItemRoot = styled('div')(({ theme }) => ({ + gap: 6, + alignItems: 'center', + display: 'inline-flex', + justifyContent: 'flex-start', + fontSize: theme.typography.pxToRem(13), + fontWeight: theme.typography.fontWeightMedium, +})); + +const ItemIcon = styled('span')({ + display: 'inline-flex', + color: 'var(--icon-color)', + /** + * As ':first-child' for ssr + * https://github.com/emotion-js/emotion/issues/1105#issuecomment-1126025608 + */ + '& > :first-of-type:not(style):not(:first-of-type ~ *), & > style + *': { width: 20, height: 20 }, +}); + +const ItemDot = styled('span')({ + width: 12, + height: 12, + flexShrink: 0, + display: 'flex', + borderRadius: '50%', + position: 'relative', + alignItems: 'center', + justifyContent: 'center', + color: 'var(--icon-color)', + backgroundColor: 'currentColor', +}); + +const ItemLabel = styled('span')({ flexShrink: 0 }); + +const ItemValue = styled('span')(({ theme }) => ({ + ...theme.typography.h6, + marginTop: theme.spacing(1), +})); diff --git a/frontend/src/components/chart/components/chart-loading.tsx b/frontend/src/components/chart/components/chart-loading.tsx new file mode 100644 index 000000000..f4e031ee2 --- /dev/null +++ b/frontend/src/components/chart/components/chart-loading.tsx @@ -0,0 +1,51 @@ +import type { BoxProps } from '@mui/material/Box'; + +import { mergeClasses } from 'minimal-shared/utils'; + +import Box from '@mui/material/Box'; +import Skeleton from '@mui/material/Skeleton'; + +import { chartClasses } from '../classes'; + +import type { ChartProps } from '../types'; + +// ---------------------------------------------------------------------- + +export type ChartLoadingProps = BoxProps & Pick; + +export function ChartLoading({ sx, className, type, ...other }: ChartLoadingProps) { + const circularTypes: ChartProps['type'][] = ['donut', 'radialBar', 'pie', 'polarArea']; + + return ( + ({ + top: 0, + left: 0, + width: 1, + zIndex: 9, + height: 1, + p: 'inherit', + overflow: 'hidden', + alignItems: 'center', + position: 'absolute', + borderRadius: 'inherit', + justifyContent: 'center', + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + + + ); +} diff --git a/frontend/src/components/chart/components/index.ts b/frontend/src/components/chart/components/index.ts new file mode 100644 index 000000000..748900a77 --- /dev/null +++ b/frontend/src/components/chart/components/index.ts @@ -0,0 +1,3 @@ +export * from './chart-legends'; + +export * from './chart-loading'; diff --git a/frontend/src/components/chart/index.ts b/frontend/src/components/chart/index.ts new file mode 100644 index 000000000..9765b2bef --- /dev/null +++ b/frontend/src/components/chart/index.ts @@ -0,0 +1,7 @@ +export * from './chart'; + +export * from './use-chart'; + +export * from './components'; + +export type * from './types'; diff --git a/frontend/src/components/chart/styles.css b/frontend/src/components/chart/styles.css new file mode 100644 index 000000000..4f16c93b0 --- /dev/null +++ b/frontend/src/components/chart/styles.css @@ -0,0 +1,56 @@ +.apexcharts-canvas { + /** + * Tooltip + */ + .apexcharts-tooltip { + min-width: 80px; + border-radius: 10px; + backdrop-filter: blur(6px); + color: var(--palette-text-primary); + box-shadow: var(--customShadows-dropdown); + background-color: rgba(var(--palette-background-defaultChannel) / 0.9); + } + .apexcharts-xaxistooltip { + border-radius: 10px; + border-color: transparent; + backdrop-filter: blur(6px); + color: var(--palette-text-primary); + box-shadow: var(--customShadows-dropdown); + background-color: rgba(var(--palette-background-defaultChannel) / 0.9); + &::before { + border-bottom-color: rgba(var(--palette-grey-500Channel) / 0.16); + } + &::after { + border-bottom-color: rgba(var(--palette-background-defaultChannel) / 0.9); + } + } + .apexcharts-tooltip-title { + font-weight: 700; + text-align: center; + color: var(--palette-text-secondary); + background-color: var(--palette-background-neutral); + } + /** + * Tooltip: group + */ + .apexcharts-tooltip-series-group { + padding: 4px 12px; + } + .apexcharts-tooltip-marker { + margin-right: 8px; + } + /** + * Legend + */ + .apexcharts-legend { + padding: 0; + } + .apexcharts-legend-marker { + margin-right: 6px; + } + .apexcharts-legend-text { + margin-left: 0; + padding-left: 0; + line-height: 18px; + } +} diff --git a/frontend/src/components/chart/types.ts b/frontend/src/components/chart/types.ts new file mode 100644 index 000000000..0e3922a86 --- /dev/null +++ b/frontend/src/components/chart/types.ts @@ -0,0 +1,14 @@ +import type { Theme, SxProps } from '@mui/material/styles'; +import type { Props as ApexProps } from 'react-apexcharts'; + +// ---------------------------------------------------------------------- + +export type ChartOptions = ApexProps['options']; + +export type ChartProps = React.ComponentProps<'div'> & + Pick & { + sx?: SxProps; + slotProps?: { + loading?: SxProps; + }; + }; diff --git a/frontend/src/components/chart/use-chart.ts b/frontend/src/components/chart/use-chart.ts new file mode 100644 index 000000000..2deca7663 --- /dev/null +++ b/frontend/src/components/chart/use-chart.ts @@ -0,0 +1,227 @@ +import type { Theme } from '@mui/material/styles'; + +import { merge } from 'es-toolkit'; +import { varAlpha } from 'minimal-shared/utils'; + +import { useTheme } from '@mui/material/styles'; + +import type { ChartOptions } from './types'; + +// ---------------------------------------------------------------------- + +export function useChart(updatedOptions?: ChartOptions): ChartOptions { + const theme = useTheme(); + + const baseOptions = baseChartOptions(theme) ?? {}; + + return merge(baseOptions, updatedOptions ?? {}); +} + +// ---------------------------------------------------------------------- + +const baseChartOptions = (theme: Theme): ChartOptions => { + const LABEL_TOTAL = { + show: true, + label: 'Total', + color: theme.vars.palette.text.secondary, + fontSize: theme.typography.subtitle2.fontSize as string, + fontWeight: theme.typography.subtitle2.fontWeight, + }; + + const LABEL_VALUE = { + offsetY: 8, + color: theme.vars.palette.text.primary, + fontSize: theme.typography.h4.fontSize as string, + fontWeight: theme.typography.h4.fontWeight, + }; + + return { + /** ************************************** + * Chart + * https://apexcharts.com/docs/options/chart/animations/ + *************************************** */ + chart: { + toolbar: { show: false }, + zoom: { enabled: false }, + parentHeightOffset: 0, + fontFamily: theme.typography.fontFamily, + foreColor: theme.vars.palette.text.disabled, + animations: { + enabled: true, + speed: 360, + animateGradually: { enabled: true, delay: 120 }, + dynamicAnimation: { enabled: true, speed: 360 }, + }, + }, + + /** ************************************** + * Colors + * https://apexcharts.com/docs/options/colors/ + *************************************** */ + colors: [ + theme.palette.primary.main, + theme.palette.warning.main, + theme.palette.info.main, + theme.palette.error.main, + theme.palette.success.main, + theme.palette.warning.dark, + theme.palette.success.darker, + theme.palette.info.dark, + theme.palette.info.darker, + ], + + /** ************************************** + * States + * https://apexcharts.com/docs/options/states/ + *************************************** */ + states: { + hover: { filter: { type: 'darken' } }, + active: { filter: { type: 'darken' } }, + }, + + /** ************************************** + * Fill + * https://apexcharts.com/docs/options/fill/ + *************************************** */ + fill: { + opacity: 1, + gradient: { + type: 'vertical', + shadeIntensity: 0, + opacityFrom: 0.4, + opacityTo: 0, + stops: [0, 100], + }, + }, + + /** ************************************** + * Data labels + * https://apexcharts.com/docs/options/datalabels/ + *************************************** */ + dataLabels: { enabled: false }, + + /** ************************************** + * Stroke + * https://apexcharts.com/docs/options/stroke/ + *************************************** */ + stroke: { width: 2.5, curve: 'smooth', lineCap: 'round' }, + + /** ************************************** + * Grid + * https://apexcharts.com/docs/options/grid/ + *************************************** */ + grid: { + strokeDashArray: 3, + borderColor: theme.vars.palette.divider, + padding: { top: 0, right: 0, bottom: 0 }, + xaxis: { lines: { show: false } }, + }, + + /** ************************************** + * Axis + * https://apexcharts.com/docs/options/xaxis/ + * https://apexcharts.com/docs/options/yaxis/ + *************************************** */ + xaxis: { axisBorder: { show: false }, axisTicks: { show: false } }, + yaxis: { tickAmount: 5 }, + + /** ************************************** + * Markers + * https://apexcharts.com/docs/options/markers/ + *************************************** */ + markers: { + size: 0, + strokeColors: theme.vars.palette.background.paper, + }, + + /** ************************************** + * Tooltip + *************************************** */ + tooltip: { theme: 'false', fillSeriesColor: false, x: { show: true } }, + + /** ************************************** + * Legend + * https://apexcharts.com/docs/options/legend/ + *************************************** */ + legend: { + show: false, + position: 'top', + fontWeight: 500, + fontSize: '13px', + horizontalAlign: 'right', + markers: { shape: 'circle' }, + labels: { colors: theme.vars.palette.text.primary }, + itemMargin: { horizontal: 8, vertical: 8 }, + }, + + /** ************************************** + * plotOptions + *************************************** */ + plotOptions: { + /** + * bar + * https://apexcharts.com/docs/options/plotoptions/bar/ + */ + bar: { borderRadius: 4, columnWidth: '48%', borderRadiusApplication: 'end' }, + /** + * pie + donut + * https://apexcharts.com/docs/options/plotoptions/pie/ + */ + pie: { + donut: { labels: { show: true, value: { ...LABEL_VALUE }, total: { ...LABEL_TOTAL } } }, + }, + /** + * radialBar + * https://apexcharts.com/docs/options/plotoptions/radialbar/ + */ + radialBar: { + hollow: { margin: -8, size: '100%' }, + track: { + margin: -8, + strokeWidth: '50%', + background: varAlpha(theme.vars.palette.grey['500Channel'], 0.16), + }, + dataLabels: { value: { ...LABEL_VALUE }, total: { ...LABEL_TOTAL } }, + }, + /** + * radar + * https://apexcharts.com/docs/options/plotoptions/radar/ + */ + radar: { + polygons: { + fill: { colors: ['transparent'] }, + strokeColors: theme.vars.palette.divider, + connectorColors: theme.vars.palette.divider, + }, + }, + /** + * polarArea + * https://apexcharts.com/docs/options/plotoptions/polararea/ + */ + polarArea: { + rings: { strokeColor: theme.vars.palette.divider }, + spokes: { connectorColors: theme.vars.palette.divider }, + }, + /** + * heatmap + * https://apexcharts.com/docs/options/plotoptions/heatmap/ + */ + heatmap: { distributed: true }, + }, + + /** ************************************** + * Responsive + * https://apexcharts.com/docs/options/responsive/ + *************************************** */ + responsive: [ + { + breakpoint: theme.breakpoints.values.sm, // sm ~ 600 + options: { plotOptions: { bar: { borderRadius: 3, columnWidth: '80%' } } }, + }, + { + breakpoint: theme.breakpoints.values.md, // md ~ 900 + options: { plotOptions: { bar: { columnWidth: '60%' } } }, + }, + ], + }; +}; diff --git a/frontend/src/components/color-utils/classes.ts b/frontend/src/components/color-utils/classes.ts new file mode 100644 index 000000000..9bf4bbdc7 --- /dev/null +++ b/frontend/src/components/color-utils/classes.ts @@ -0,0 +1,18 @@ +import { createClasses } from 'src/theme/create-classes'; + +// ---------------------------------------------------------------------- + +export const colorPreviewClasses = { + root: createClasses('color__preview__root'), + item: createClasses('color__preview__item'), + label: createClasses('color__preview__label'), +}; + +export const colorPickerClasses = { + root: createClasses('color__picker__root'), + item: { + root: createClasses('color__picker__item__root'), + container: createClasses('color__picker__item__container'), + icon: createClasses('color__picker__item__icon'), + }, +}; diff --git a/frontend/src/components/color-utils/color-picker.tsx b/frontend/src/components/color-utils/color-picker.tsx new file mode 100644 index 000000000..2dc3efecc --- /dev/null +++ b/frontend/src/components/color-utils/color-picker.tsx @@ -0,0 +1,179 @@ +import type { Theme, SxProps } from '@mui/material/styles'; + +import { useCallback } from 'react'; +import { varAlpha, mergeClasses } from 'minimal-shared/utils'; + +import ButtonBase from '@mui/material/ButtonBase'; +import { styled, alpha as hexAlpha } from '@mui/material/styles'; + +import { Iconify } from '../iconify'; +import { colorPickerClasses } from './classes'; + +// ---------------------------------------------------------------------- + +export type ColorPickerSlotProps = { + item?: React.ComponentProps; + itemContainer?: React.ComponentProps; + icon?: React.ComponentProps; +}; + +export type ColorPickerProps = Omit, 'onChange'> & { + sx?: SxProps; + size?: number; + options?: string[]; + limit?: 'auto' | number; + value?: string | string[]; + variant?: 'circular' | 'rounded' | 'square'; + onChange?: (value: string | string[]) => void; + slotProps?: ColorPickerSlotProps; +}; + +export function ColorPicker({ + sx, + value, + onChange, + slotProps, + className, + size = 36, + options = [], + limit = 'auto', + variant = 'circular', + ...other +}: ColorPickerProps) { + const isSingleSelect = typeof value === 'string'; + + const handleSelect = useCallback( + (color: string) => { + if (isSingleSelect) { + if (color !== value) { + onChange?.(color); + } + } else { + const selected = value as string[]; + + const newSelected = selected.includes(color) + ? selected.filter((currentColor) => currentColor !== color) + : [...selected, color]; + + onChange?.(newSelected); + } + }, + [onChange, value, isSingleSelect] + ); + + return ( + + {options.map((color) => { + const hasSelected = isSingleSelect ? value === color : (value as string[]).includes(color); + + return ( +
  • + handleSelect(color)} + className={colorPickerClasses.item.root} + {...slotProps?.item} + > + + + + +
  • + ); + })} +
    + ); +} + +// ---------------------------------------------------------------------- + +const ColorPickerRoot = styled('ul', { + shouldForwardProp: (prop: string) => !['limit', 'sx'].includes(prop), +})>(({ limit }) => ({ + flexWrap: 'wrap', + flexDirection: 'row', + display: 'inline-flex', + '& > li': { display: 'inline-flex' }, + ...(typeof limit === 'number' && { + justifyContent: 'flex-end', + width: `calc(var(--item-size) * ${limit})`, + }), +})); + +const ItemRoot = styled(ButtonBase)(() => ({ + width: 'var(--item-size)', + height: 'var(--item-size)', + borderRadius: 'var(--item-radius)', +})); + +const ItemContainer = styled('span', { + shouldForwardProp: (prop: string) => !['color', 'hasSelected', 'sx'].includes(prop), +})<{ color: string; hasSelected: boolean }>(({ color, theme }) => ({ + alignItems: 'center', + display: 'inline-flex', + borderRadius: 'inherit', + justifyContent: 'center', + backgroundColor: color, + width: 'calc(var(--item-size) - 16px)', + height: 'calc(var(--item-size) - 16px)', + border: `solid 1px ${varAlpha(theme.vars.palette.grey['500Channel'], 0.16)}`, + transition: theme.transitions.create(['all'], { + duration: theme.transitions.duration.shortest, + }), + variants: [ + { + props: { hasSelected: true }, + style: { + width: 'calc(var(--item-size) - 8px)', + height: 'calc(var(--item-size) - 8px)', + outline: `solid 2px ${hexAlpha(color, 0.08)}`, + boxShadow: `4px 4px 8px 0 ${hexAlpha(color, 0.48)}`, + }, + }, + ], +})); + +const ItemIcon = styled(Iconify, { + shouldForwardProp: (prop: string) => !['color', 'hasSelected', 'sx'].includes(prop), +})<{ color: string; hasSelected: boolean }>(({ color, theme }) => ({ + width: 0, + height: 0, + color: theme.palette.getContrastText(color), + transition: theme.transitions.create(['all'], { + duration: theme.transitions.duration.shortest, + }), + variants: [ + { + props: { hasSelected: true }, + style: { + width: 'calc(var(--item-size) / 2.4)', + height: 'calc(var(--item-size) / 2.4)', + }, + }, + ], +})); diff --git a/frontend/src/components/color-utils/color-preview.tsx b/frontend/src/components/color-utils/color-preview.tsx new file mode 100644 index 000000000..f485ad208 --- /dev/null +++ b/frontend/src/components/color-utils/color-preview.tsx @@ -0,0 +1,90 @@ +import { varAlpha, mergeClasses } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; + +import { colorPreviewClasses } from './classes'; + +// ---------------------------------------------------------------------- + +export type ColorPreviewSlotProps = { + item?: React.ComponentProps; + label?: React.ComponentProps; +}; + +export type ColorPreviewProps = React.ComponentProps & { + limit?: number; + size?: number; + gap?: number; + colors: string[]; + slotProps?: ColorPreviewSlotProps; +}; + +export function ColorPreview({ + sx, + colors, + className, + slotProps, + gap = 6, + limit = 3, + size = 16, + ...other +}: ColorPreviewProps) { + const colorsRange = colors.slice(0, limit); + const remainingColorCount = colors.length - limit; + + return ( + + {colorsRange.map((color, index) => ( + + ))} + + {colors.length > limit && ( + {`+${remainingColorCount}`} + )} + + ); +} + +// ---------------------------------------------------------------------- + +const ColorPreviewRoot = styled('ul')(() => ({ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-end', +})); + +const ItemRoot = styled('li')(({ theme }) => ({ + borderRadius: '50%', + width: 'var(--item-size)', + height: 'var(--item-size)', + marginLeft: 'var(--item-gap)', + backgroundColor: 'var(--item-color)', + border: `solid 2px ${theme.vars.palette.background.paper}`, + boxShadow: `inset -1px 1px 2px ${varAlpha(theme.vars.palette.common.blackChannel, 0.24)}`, +})); + +const ItemLabel = styled('li')(({ theme }) => ({ + ...theme.typography.subtitle2, +})); diff --git a/frontend/src/components/color-utils/index.ts b/frontend/src/components/color-utils/index.ts new file mode 100644 index 000000000..efdd9796f --- /dev/null +++ b/frontend/src/components/color-utils/index.ts @@ -0,0 +1,5 @@ +export * from './classes'; + +export * from './color-picker'; + +export * from './color-preview'; diff --git a/frontend/src/components/data-table/index.tsx b/frontend/src/components/data-table/index.tsx new file mode 100644 index 000000000..ede11fddf --- /dev/null +++ b/frontend/src/components/data-table/index.tsx @@ -0,0 +1,128 @@ +import type { Pagination } from 'src/api/types/common'; + +import { useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; + +import Box from '@mui/material/Box'; +import Card from '@mui/material/Card'; +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; +import Typography from '@mui/material/Typography'; +import TableContainer from '@mui/material/TableContainer'; +import TablePagination from '@mui/material/TablePagination'; +import { TableRow, TableCell, TableHead, type TableCellProps } from '@mui/material'; + +import { DashboardContent } from 'src/layouts/dashboard'; + +import { Scrollbar } from 'src/components/scrollbar'; + +import { TableToolbar } from './table-toolbar'; +import { BlueButton } from '../buttons/blue-button'; + + +// ---------------------------------------------------------------------- +export type DataTableProps = { + title: string + addBtn?: { + title: string + url: string + } + headings: { + id: string + label?: string + component?: (data: any) => React.JSX.Element + align?: TableCellProps['align'] + }[] + dataKey: string + fetchData: (query: { search?: string, page: number, limit: number }) => Promise> + searchPlaceHolder?: string +} + +export function DataTable({ + title, + addBtn, + headings, + dataKey, + searchPlaceHolder, + fetchData +}: DataTableProps) { + + const [search, setSearch] = useState(''); + const [page, setPage] = useState(0) + const [limit, setLimit] = useState(10) + const { data } = useQuery({ + queryKey: [dataKey, page, search, limit], + queryFn: () => fetchData({ search, page, limit }) + }) + + + return ( + + + + {title} + + { + addBtn && + + } + + + + ) => { + setSearch(event.target.value); + }} + searchPlaceHolder={searchPlaceHolder} + /> + + + + + + {headings.map((headCell) => ( + + {headCell.label} + + ))} + + + + {(data?.data || []).map((row: any) => ( + + { + headings.map(head => ( + + {head.component ? head.component(row) : row[head.id] || ''} + + )) + } + + ))} + +
    +
    +
    + setPage(p)} + rowsPerPageOptions={[5, 10, 25]} + onRowsPerPageChange={(e) => setLimit(parseInt(e.target.value || '10'))} + /> +
    +
    + ); +} diff --git a/frontend/src/components/data-table/table-empty-rows.tsx b/frontend/src/components/data-table/table-empty-rows.tsx new file mode 100644 index 000000000..6bc9ee0ba --- /dev/null +++ b/frontend/src/components/data-table/table-empty-rows.tsx @@ -0,0 +1,26 @@ +import type { TableRowProps } from '@mui/material/TableRow'; + +import TableRow from '@mui/material/TableRow'; +import TableCell from '@mui/material/TableCell'; + +// ---------------------------------------------------------------------- + +type TableEmptyRowsProps = TableRowProps & { + emptyRows: number; + height?: number; +}; + +export function TableEmptyRows({ emptyRows, height, sx, ...other }: TableEmptyRowsProps) { + if (!emptyRows) { + return null; + } + + return ( + + + + ); +} diff --git a/frontend/src/components/data-table/table-no-data.tsx b/frontend/src/components/data-table/table-no-data.tsx new file mode 100644 index 000000000..914e23f38 --- /dev/null +++ b/frontend/src/components/data-table/table-no-data.tsx @@ -0,0 +1,32 @@ +import type { TableRowProps } from '@mui/material/TableRow'; + +import Box from '@mui/material/Box'; +import TableRow from '@mui/material/TableRow'; +import TableCell from '@mui/material/TableCell'; +import Typography from '@mui/material/Typography'; + +// ---------------------------------------------------------------------- + +type TableNoDataProps = TableRowProps & { + searchQuery: string; +}; + +export function TableNoData({ searchQuery, ...other }: TableNoDataProps) { + return ( + + + + + Not found + + + + No results found for   + "{searchQuery}". +
    Try checking for typos or using complete words. +
    +
    +
    +
    + ); +} diff --git a/frontend/src/components/data-table/table-toolbar.tsx b/frontend/src/components/data-table/table-toolbar.tsx new file mode 100644 index 000000000..bbc541599 --- /dev/null +++ b/frontend/src/components/data-table/table-toolbar.tsx @@ -0,0 +1,46 @@ +import Tooltip from '@mui/material/Tooltip'; +import Toolbar from '@mui/material/Toolbar'; +import IconButton from '@mui/material/IconButton'; +import OutlinedInput from '@mui/material/OutlinedInput'; +import InputAdornment from '@mui/material/InputAdornment'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +type TableToolbarProps = { + searchValue: string; + onSearch: (event: React.ChangeEvent) => void; + searchPlaceHolder?: string +}; + +export function TableToolbar({ searchValue, onSearch, searchPlaceHolder }: TableToolbarProps) { + return ( + theme.spacing(0, 1, 0, 3), + }} + > + + + + } + sx={{ maxWidth: 320 }} + /> + + + + + + + ); +} diff --git a/frontend/src/components/iconify/classes.ts b/frontend/src/components/iconify/classes.ts new file mode 100644 index 000000000..6d4a46331 --- /dev/null +++ b/frontend/src/components/iconify/classes.ts @@ -0,0 +1,7 @@ +import { createClasses } from 'src/theme/create-classes'; + +// ---------------------------------------------------------------------- + +export const iconifyClasses = { + root: createClasses('iconify__root'), +}; diff --git a/frontend/src/components/iconify/icon-sets.ts b/frontend/src/components/iconify/icon-sets.ts new file mode 100644 index 000000000..9d33a60a0 --- /dev/null +++ b/frontend/src/components/iconify/icon-sets.ts @@ -0,0 +1,110 @@ +export default { + 'solar:pen-bold': { + body: '', + }, + 'solar:eye-bold': { + body: '', + }, + 'solar:share-bold': { + body: '', + }, + 'solar:cart-3-bold': { + body: '', + }, + 'solar:restart-bold': { + body: '', + }, + 'solar:eye-closed-bold': { + body: '', + }, + 'solar:check-circle-bold': { + body: '', + }, + 'solar:trash-bin-trash-bold': { + body: '', + }, + 'solar:chat-round-dots-bold': { + body: '', + }, + 'solar:clock-circle-outline': { + body: '', + }, + 'solar:bell-bing-bold-duotone': { + body: '', + }, + 'solar:hand-stars-bold-duotone': { + body: '', + }, + 'solar:calendar-mark-bold-duotone': { + body: '', + }, + 'solar:wallet-money-bold-duotone': { + body: '', + }, + 'solar:home-angle-bold-duotone': { + body: '', + }, + 'solar:settings-bold-duotone': { + body: '', + }, + 'solar:shield-keyhole-bold-duotone': { + body: '', + }, + 'eva:more-vertical-fill': { + body: '', + }, + 'eva:search-fill': { + body: '', + }, + 'eva:done-all-fill': { + body: '', + }, + 'eva:checkmark-fill': { + body: '', + }, + 'eva:trending-down-fill': { + body: '', + }, + 'eva:trending-up-fill': { + body: '', + }, + 'eva:arrow-ios-forward-fill': { + body: '', + }, + 'eva:arrow-ios-downward-fill': { + body: '', + }, + 'eva:arrow-ios-upward-fill': { + body: '', + }, + 'ic:round-filter-list': { + body: '', + }, + 'mingcute:add-line': { + body: '', + }, + 'mingcute:close-line': { + body: '', + }, + 'carbon:chevron-sort': { + body: '', + }, + 'socials:linkedin': { + body: '', + }, + 'socials:facebook': { + body: '', + }, + 'socials:github': { + body: '', + }, + 'socials:twitter': { + body: '', + }, + 'socials:google': { + body: ' ', + }, + 'custom:menu-duotone': { + body: ' ', + }, +}; diff --git a/frontend/src/components/iconify/iconify.tsx b/frontend/src/components/iconify/iconify.tsx new file mode 100644 index 000000000..5b8831fee --- /dev/null +++ b/frontend/src/components/iconify/iconify.tsx @@ -0,0 +1,58 @@ +import type { IconProps } from '@iconify/react'; + +import { useId } from 'react'; +import { Icon } from '@iconify/react'; +import { mergeClasses } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; + +import { iconifyClasses } from './classes'; +import { allIconNames, registerIcons } from './register-icons'; + + +// ---------------------------------------------------------------------- + +export type IconifyProps = React.ComponentProps & + Omit & { + icon: string; + }; + +export function Iconify({ className, icon, width = 20, height, sx, ...other }: IconifyProps) { + const id = useId(); + + // @ts-expect-error it is working + if (!allIconNames.includes(icon)) { + console.warn( + [ + `Icon "${icon}" is currently loaded online, which may cause flickering effects.`, + `To ensure a smoother experience, please register your icon collection for offline use.`, + `More information is available at: https://docs.minimals.cc/icons/`, + ].join('\n') + ); + } + + registerIcons(); + + return ( + + ); +} + +// ---------------------------------------------------------------------- + +const IconRoot = styled(Icon)``; diff --git a/frontend/src/components/iconify/index.ts b/frontend/src/components/iconify/index.ts new file mode 100644 index 000000000..72937f9d0 --- /dev/null +++ b/frontend/src/components/iconify/index.ts @@ -0,0 +1,5 @@ +export * from './classes'; + +export * from './iconify'; + +export * from './register-icons'; diff --git a/frontend/src/components/iconify/register-icons.ts b/frontend/src/components/iconify/register-icons.ts new file mode 100644 index 000000000..f00575be6 --- /dev/null +++ b/frontend/src/components/iconify/register-icons.ts @@ -0,0 +1,51 @@ +import type { IconifyJSON } from '@iconify/react'; + +import { addCollection } from '@iconify/react'; + +import allIcons from './icon-sets'; + +// ---------------------------------------------------------------------- + +export const iconSets = Object.entries(allIcons).reduce((acc, [key, value]) => { + const [prefix, iconName] = key.split(':'); + const existingPrefix = acc.find((item) => item.prefix === prefix); + + if (existingPrefix) { + existingPrefix.icons[iconName] = value; + } else { + acc.push({ + prefix, + icons: { + [iconName]: value, + }, + }); + } + + return acc; +}, [] as IconifyJSON[]); + +export const allIconNames = Object.keys(allIcons) as IconifyName[]; + +export type IconifyName = keyof typeof allIcons; + +// ---------------------------------------------------------------------- + +let areIconsRegistered = false; + +export function registerIcons() { + if (areIconsRegistered) { + return; + } + + iconSets.forEach((iconSet) => { + const iconSetConfig = { + ...iconSet, + width: (iconSet.prefix === 'carbon' && 32) || 24, + height: (iconSet.prefix === 'carbon' && 32) || 24, + }; + + addCollection(iconSetConfig); + }); + + areIconsRegistered = true; +} diff --git a/frontend/src/components/label/classes.ts b/frontend/src/components/label/classes.ts new file mode 100644 index 000000000..00420532b --- /dev/null +++ b/frontend/src/components/label/classes.ts @@ -0,0 +1,8 @@ +import { createClasses } from 'src/theme/create-classes'; + +// ---------------------------------------------------------------------- + +export const labelClasses = { + root: createClasses('label__root'), + icon: createClasses('label__icon'), +}; diff --git a/frontend/src/components/label/index.ts b/frontend/src/components/label/index.ts new file mode 100644 index 000000000..71f3c7e64 --- /dev/null +++ b/frontend/src/components/label/index.ts @@ -0,0 +1,7 @@ +export * from './label'; + +export * from './styles'; + +export * from './classes'; + +export type * from './types'; diff --git a/frontend/src/components/label/label.tsx b/frontend/src/components/label/label.tsx new file mode 100644 index 000000000..a2b07d65b --- /dev/null +++ b/frontend/src/components/label/label.tsx @@ -0,0 +1,38 @@ +import { upperFirst } from 'es-toolkit'; +import { mergeClasses } from 'minimal-shared/utils'; + +import { labelClasses } from './classes'; +import { LabelRoot, LabelIcon } from './styles'; + +import type { LabelProps } from './types'; + +// ---------------------------------------------------------------------- + +export function Label({ + sx, + endIcon, + children, + startIcon, + className, + disabled, + variant = 'soft', + color = 'default', + ...other +}: LabelProps) { + return ( + + {startIcon && {startIcon}} + + {typeof children === 'string' ? upperFirst(children) : children} + + {endIcon && {endIcon}} + + ); +} diff --git a/frontend/src/components/label/styles.tsx b/frontend/src/components/label/styles.tsx new file mode 100644 index 000000000..b2666997e --- /dev/null +++ b/frontend/src/components/label/styles.tsx @@ -0,0 +1,116 @@ +import type { CSSObject } from '@mui/material/styles'; + +import { varAlpha } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; + +import type { LabelProps } from './types'; + +// ---------------------------------------------------------------------- + +export const LabelRoot = styled('span', { + shouldForwardProp: (prop: string) => !['color', 'variant', 'disabled', 'sx'].includes(prop), +})(({ color, variant, disabled, theme }) => { + const defaultStyles: CSSObject = { + ...(color === 'default' && { + /** + * @variant filled + */ + ...(variant === 'filled' && { + color: theme.vars.palette.common.white, + backgroundColor: theme.vars.palette.text.primary, + ...theme.applyStyles('dark', { + color: theme.vars.palette.grey[800], + }), + }), + /** + * @variant outlined + */ + ...(variant === 'outlined' && { + backgroundColor: 'transparent', + color: theme.vars.palette.text.primary, + border: `2px solid ${theme.vars.palette.text.primary}`, + }), + /** + * @variant soft + */ + ...(variant === 'soft' && { + color: theme.vars.palette.text.secondary, + backgroundColor: varAlpha(theme.vars.palette.grey['500Channel'], 0.16), + }), + /** + * @variant inverted + */ + ...(variant === 'inverted' && { + color: theme.vars.palette.grey[800], + backgroundColor: theme.vars.palette.grey[300], + }), + }), + }; + + const colorStyles: CSSObject = { + ...(color && + color !== 'default' && { + /** + * @variant filled + */ + ...(variant === 'filled' && { + color: theme.vars.palette[color].contrastText, + backgroundColor: theme.vars.palette[color].main, + }), + /** + * @variant outlined + */ + ...(variant === 'outlined' && { + backgroundColor: 'transparent', + color: theme.vars.palette[color].main, + border: `2px solid ${theme.vars.palette[color].main}`, + }), + /** + * @variant soft + */ + ...(variant === 'soft' && { + color: theme.vars.palette[color].dark, + backgroundColor: varAlpha(theme.vars.palette[color].mainChannel, 0.16), + ...theme.applyStyles('dark', { + color: theme.vars.palette[color].light, + }), + }), + /** + * @variant inverted + */ + ...(variant === 'inverted' && { + color: theme.vars.palette[color].darker, + backgroundColor: theme.vars.palette[color].lighter, + }), + }), + }; + + return { + height: 24, + minWidth: 24, + lineHeight: 0, + flexShrink: 0, + cursor: 'default', + alignItems: 'center', + whiteSpace: 'nowrap', + display: 'inline-flex', + gap: theme.spacing(0.75), + justifyContent: 'center', + padding: theme.spacing(0, 0.75), + fontSize: theme.typography.pxToRem(12), + fontWeight: theme.typography.fontWeightBold, + borderRadius: theme.shape.borderRadius * 0.75, + transition: theme.transitions.create(['all'], { duration: theme.transitions.duration.shorter }), + ...defaultStyles, + ...colorStyles, + ...(disabled && { opacity: 0.48, pointerEvents: 'none' }), + }; +}); + +export const LabelIcon = styled('span')({ + width: 16, + height: 16, + flexShrink: 0, + '& svg, img': { width: '100%', height: '100%', objectFit: 'cover' }, +}); diff --git a/frontend/src/components/label/types.ts b/frontend/src/components/label/types.ts new file mode 100644 index 000000000..4db6635b7 --- /dev/null +++ b/frontend/src/components/label/types.ts @@ -0,0 +1,23 @@ +import type { Theme, SxProps } from '@mui/material/styles'; + +// ---------------------------------------------------------------------- + +export type LabelColor = + | 'default' + | 'primary' + | 'secondary' + | 'info' + | 'success' + | 'warning' + | 'error'; + +export type LabelVariant = 'filled' | 'outlined' | 'soft' | 'inverted'; + +export interface LabelProps extends React.ComponentProps<'span'> { + sx?: SxProps; + disabled?: boolean; + color?: LabelColor; + variant?: LabelVariant; + endIcon?: React.ReactNode; + startIcon?: React.ReactNode; +} diff --git a/frontend/src/components/logo/classes.ts b/frontend/src/components/logo/classes.ts new file mode 100644 index 000000000..380119952 --- /dev/null +++ b/frontend/src/components/logo/classes.ts @@ -0,0 +1,7 @@ +import { createClasses } from 'src/theme/create-classes'; + +// ---------------------------------------------------------------------- + +export const logoClasses = { + root: createClasses('logo__root'), +}; diff --git a/frontend/src/components/logo/index.ts b/frontend/src/components/logo/index.ts new file mode 100644 index 000000000..b86e7ad38 --- /dev/null +++ b/frontend/src/components/logo/index.ts @@ -0,0 +1,3 @@ +export * from './logo'; + +export * from './classes'; diff --git a/frontend/src/components/logo/logo.tsx b/frontend/src/components/logo/logo.tsx new file mode 100644 index 000000000..251b63e4c --- /dev/null +++ b/frontend/src/components/logo/logo.tsx @@ -0,0 +1,197 @@ +import type { LinkProps } from '@mui/material/Link'; + +import { useId } from 'react'; +import { mergeClasses } from 'minimal-shared/utils'; + +import Link from '@mui/material/Link'; +import { styled, useTheme } from '@mui/material/styles'; + +import { RouterLink } from 'src/routes/components'; + +import { logoClasses } from './classes'; + +// ---------------------------------------------------------------------- + +export type LogoProps = LinkProps & { + isSingle?: boolean; + disabled?: boolean; +}; + +export function Logo({ + sx, + disabled, + className, + href = '/', + isSingle = true, + ...other +}: LogoProps) { + const theme = useTheme(); + + const gradientId = useId(); + + const TEXT_PRIMARY = theme.vars.palette.text.primary; + const PRIMARY_LIGHT = theme.vars.palette.primary.light; + const PRIMARY_MAIN = theme.vars.palette.primary.main; + const PRIMARY_DARKER = theme.vars.palette.primary.dark; + + const singleLogo = ( + + + + + + + + + + + + + + + + + + + + ); + + const fullLogo = ( + + + + + + + + + + + + + + + + + + + + + ); + + return ( + + {isSingle ? singleLogo : fullLogo} + + ); +} + +// ---------------------------------------------------------------------- + +const LogoRoot = styled(Link)(() => ({ + flexShrink: 0, + color: 'transparent', + display: 'inline-flex', + verticalAlign: 'middle', +})); diff --git a/frontend/src/components/modal/confirm.tsx b/frontend/src/components/modal/confirm.tsx new file mode 100644 index 000000000..308f3f1fd --- /dev/null +++ b/frontend/src/components/modal/confirm.tsx @@ -0,0 +1,77 @@ +import React from "react"; + +import { + Dialog, + Button, + DialogTitle, + DialogContent, + DialogActions, + CircularProgress, + DialogContentText, +} from "@mui/material"; + +export interface ConfirmDialogProps { + open: boolean; + title?: string; + message: string; + confirmText?: string; + cancelText?: string; + loading?: boolean; + danger?: boolean; + onConfirm: () => void; + onClose: () => void; +} + +function ConfirmDialog({ + open, + title = "Confirmation", + message, + confirmText = "Confirm", + cancelText = "Cancel", + loading = false, + danger = false, + onConfirm, + onClose, +}: ConfirmDialogProps) { + + return ( + + {title} + + + {message} + + + + + + + + + ); +} + + +export default ConfirmDialog; \ No newline at end of file diff --git a/frontend/src/components/novu/novu-provider.tsx b/frontend/src/components/novu/novu-provider.tsx new file mode 100644 index 000000000..b2db75c29 --- /dev/null +++ b/frontend/src/components/novu/novu-provider.tsx @@ -0,0 +1,34 @@ +import type { ReactNode } from 'react'; + +import { NovuProvider as NovuReactProvider } from '@novu/react'; + +import { useAuth } from 'src/context/auth/use-auth'; + +// ---------------------------------------------------------------------- + +const NOVU_APPLICATION_IDENTIFIER = import.meta.env.VITE_NOVU_APPLICATION_IDENTIFIER; + +type NovuProviderProps = { + children: ReactNode; +}; + +/** + * Bridges the app's auth state with Novu's notification feed, keyed off the + * signed-in user's id as the Novu `subscriberId`. + */ +export function NovuProvider({ children }: NovuProviderProps) { + const { user, isAuthenticated } = useAuth(); + + if (!isAuthenticated || !user || !NOVU_APPLICATION_IDENTIFIER) { + return <>{children}; + } + + return ( + + {children} + + ); +} diff --git a/frontend/src/components/scrollbar/classes.ts b/frontend/src/components/scrollbar/classes.ts new file mode 100644 index 000000000..8cdeaccf6 --- /dev/null +++ b/frontend/src/components/scrollbar/classes.ts @@ -0,0 +1,7 @@ +import { createClasses } from 'src/theme/create-classes'; + +// ---------------------------------------------------------------------- + +export const scrollbarClasses = { + root: createClasses('scrollbar__root'), +}; diff --git a/frontend/src/components/scrollbar/index.ts b/frontend/src/components/scrollbar/index.ts new file mode 100644 index 000000000..a483df68b --- /dev/null +++ b/frontend/src/components/scrollbar/index.ts @@ -0,0 +1,5 @@ +export * from './classes'; + +export * from './scrollbar'; + +export type * from './types'; diff --git a/frontend/src/components/scrollbar/scrollbar.tsx b/frontend/src/components/scrollbar/scrollbar.tsx new file mode 100644 index 000000000..74c4ca33b --- /dev/null +++ b/frontend/src/components/scrollbar/scrollbar.tsx @@ -0,0 +1,60 @@ +import SimpleBar from 'simplebar-react'; +import { mergeClasses } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; + +import { scrollbarClasses } from './classes'; + +import type { ScrollbarProps } from './types'; + +// ---------------------------------------------------------------------- + +export function Scrollbar({ + sx, + ref, + children, + className, + slotProps, + fillContent = true, + ...other +}: ScrollbarProps) { + return ( + + {children} + + ); +} + +// ---------------------------------------------------------------------- + +const ScrollbarRoot = styled(SimpleBar, { + shouldForwardProp: (prop: string) => !['fillContent', 'sx'].includes(prop), +})>(({ fillContent }) => ({ + minWidth: 0, + minHeight: 0, + flexGrow: 1, + display: 'flex', + flexDirection: 'column', + ...(fillContent && { + '& .simplebar-content': { + display: 'flex', + flex: '1 1 auto', + minHeight: '100%', + flexDirection: 'column', + }, + }), +})); diff --git a/frontend/src/components/scrollbar/styles.css b/frontend/src/components/scrollbar/styles.css new file mode 100644 index 000000000..2fbf4d99d --- /dev/null +++ b/frontend/src/components/scrollbar/styles.css @@ -0,0 +1,8 @@ +@import 'simplebar-react/dist/simplebar.min.css'; + +.simplebar-scrollbar:before { + background-color: var(--palette-text-disabled); +} +.simplebar-scrollbar.simplebar-visible:before { + opacity: 0.48; +} diff --git a/frontend/src/components/scrollbar/types.ts b/frontend/src/components/scrollbar/types.ts new file mode 100644 index 000000000..c53cbb9f0 --- /dev/null +++ b/frontend/src/components/scrollbar/types.ts @@ -0,0 +1,15 @@ +import type { Theme, SxProps } from '@mui/material/styles'; +import type { Props as SimplebarProps } from 'simplebar-react'; + +// ---------------------------------------------------------------------- + +export type ScrollbarProps = SimplebarProps & + React.ComponentProps<'div'> & { + sx?: SxProps; + fillContent?: boolean; + slotProps?: { + wrapperSx?: SxProps; + contentSx?: SxProps; + contentWrapperSx?: SxProps; + }; + }; diff --git a/frontend/src/components/svg-color/classes.ts b/frontend/src/components/svg-color/classes.ts new file mode 100644 index 000000000..319b076fb --- /dev/null +++ b/frontend/src/components/svg-color/classes.ts @@ -0,0 +1,7 @@ +import { createClasses } from 'src/theme/create-classes'; + +// ---------------------------------------------------------------------- + +export const svgColorClasses = { + root: createClasses('svg__color__root'), +}; diff --git a/frontend/src/components/svg-color/index.ts b/frontend/src/components/svg-color/index.ts new file mode 100644 index 000000000..372c31dd5 --- /dev/null +++ b/frontend/src/components/svg-color/index.ts @@ -0,0 +1,5 @@ +export * from './classes'; + +export * from './svg-color'; + +export type * from './types'; diff --git a/frontend/src/components/svg-color/svg-color.tsx b/frontend/src/components/svg-color/svg-color.tsx new file mode 100644 index 000000000..023ab8a3c --- /dev/null +++ b/frontend/src/components/svg-color/svg-color.tsx @@ -0,0 +1,35 @@ +import { mergeClasses } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; + +import { svgColorClasses } from './classes'; + +import type { SvgColorProps } from './types'; + +// ---------------------------------------------------------------------- + +export function SvgColor({ src, className, sx, ...other }: SvgColorProps) { + return ( + + ); +} + +// ---------------------------------------------------------------------- + +const SvgRoot = styled('span')(() => ({ + width: 24, + height: 24, + flexShrink: 0, + display: 'inline-flex', + backgroundColor: 'currentColor', +})); diff --git a/frontend/src/components/svg-color/types.ts b/frontend/src/components/svg-color/types.ts new file mode 100644 index 000000000..c790c87e5 --- /dev/null +++ b/frontend/src/components/svg-color/types.ts @@ -0,0 +1,8 @@ +import type { Theme, SxProps } from '@mui/material/styles'; + +// ---------------------------------------------------------------------- + +export type SvgColorProps = React.ComponentProps<'span'> & { + src: string; + sx?: SxProps; +}; diff --git a/frontend/src/config-global.ts b/frontend/src/config-global.ts new file mode 100644 index 000000000..4955391d6 --- /dev/null +++ b/frontend/src/config-global.ts @@ -0,0 +1,13 @@ +import packageJson from '../package.json'; + +// ---------------------------------------------------------------------- + +export type ConfigValue = { + appName: string; + appVersion: string; +}; + +export const CONFIG: ConfigValue = { + appName: 'Book My Venue', + appVersion: packageJson.version, +}; diff --git a/frontend/src/context/auth/auth-context.tsx b/frontend/src/context/auth/auth-context.tsx new file mode 100644 index 000000000..3e642dd4a --- /dev/null +++ b/frontend/src/context/auth/auth-context.tsx @@ -0,0 +1,12 @@ +import { + createContext, +} from 'react'; + +import type { + AuthContextValue, +} from './auth.types'; + +export const AuthContext = + createContext( + null, + ); \ No newline at end of file diff --git a/frontend/src/context/auth/auth-provider.tsx b/frontend/src/context/auth/auth-provider.tsx new file mode 100644 index 000000000..8f9623b06 --- /dev/null +++ b/frontend/src/context/auth/auth-provider.tsx @@ -0,0 +1,134 @@ +import type { + PropsWithChildren, +} from 'react'; + +import { + useMemo, + useState, + useEffect, +} from 'react'; + +import { Box, LinearProgress, linearProgressClasses } from '@mui/material'; + +import { tokenStorage } from 'src/lib/token'; +import { UserApiService } from 'src/api/user'; + +import { + AuthContext, +} from './auth-context'; + +import type { + AuthUser, + UserRole, + AuthState, + AuthTokens, +} from './auth.types'; + +export function AuthProvider({ + children, +}: PropsWithChildren) { + const [state, setState] = + useState({ + isLoading: true, + isAuthenticated: false, + user: null, + tokens: null, + }); + + const login = ( + user: AuthUser, + tokens: AuthTokens, + ) => { + tokenStorage.setTokens(tokens.accessToken, tokens.refreshToken); + + setState({ + isLoading: false, + isAuthenticated: true, + user, + tokens, + }); + }; + + const logout = () => { + tokenStorage.clear(); + + setState({ + isLoading: false, + isAuthenticated: false, + user: null, + tokens: null, + }); + }; + + const hasRole = ( + ...roles: UserRole[] + ) => !!state.user && + roles.includes( + state.user.role, + ); + + const value = useMemo( + () => ({ + ...state, + login, + logout, + hasRole, + }), + [state], + ); + + const Loading = () => ( + + + + ); + + useEffect(() => { + + UserApiService.me() + .then((user) => { + setState({ + isLoading: false, + isAuthenticated: true, + user, + tokens: null, + }); + }) + .catch(() => { + setState({ + isLoading: false, + isAuthenticated: false, + user: null, + tokens: null, + }); + }); + }, []); + + return ( + + { + state.isLoading ? : children + } + + ); +} \ No newline at end of file diff --git a/frontend/src/context/auth/auth-storage.ts b/frontend/src/context/auth/auth-storage.ts new file mode 100644 index 000000000..54faa7c37 --- /dev/null +++ b/frontend/src/context/auth/auth-storage.ts @@ -0,0 +1,44 @@ +import type { + AuthUser, + AuthTokens, +} from './auth.types'; + +const USER_KEY = 'bmv_user'; +const TOKEN_KEY = 'bmv_tokens'; + +export const AuthStorage = { + save(user: AuthUser, tokens: AuthTokens) { + localStorage.setItem( + USER_KEY, + JSON.stringify(user), + ); + + localStorage.setItem( + TOKEN_KEY, + JSON.stringify(tokens), + ); + }, + + getUser(): AuthUser | null { + const value = + localStorage.getItem(USER_KEY); + + return value + ? JSON.parse(value) + : null; + }, + + getTokens(): AuthTokens | null { + const value = + localStorage.getItem(TOKEN_KEY); + + return value + ? JSON.parse(value) + : null; + }, + + clear() { + localStorage.removeItem(USER_KEY); + localStorage.removeItem(TOKEN_KEY); + }, +}; \ No newline at end of file diff --git a/frontend/src/context/auth/auth.types.ts b/frontend/src/context/auth/auth.types.ts new file mode 100644 index 000000000..b32f2a80c --- /dev/null +++ b/frontend/src/context/auth/auth.types.ts @@ -0,0 +1,37 @@ +export enum UserRole { + USER = 'USER', + VENUE_OWNER = 'VENUE_OWNER', + ADMIN = 'ADMIN', +} + +export interface AuthUser { + id: string; + email: string; + name: string; + role: UserRole; +} + +export interface AuthTokens { + accessToken: string; + refreshToken: string; +} + +export interface AuthState { + isLoading: boolean; + isAuthenticated: boolean; + user: AuthUser | null; + tokens: AuthTokens | null; +} + +export interface AuthContextValue extends AuthState { + login: ( + user: AuthUser, + tokens: AuthTokens, + ) => void; + + logout: () => void; + + hasRole: ( + ...roles: UserRole[] + ) => boolean; +} \ No newline at end of file diff --git a/frontend/src/context/auth/use-auth.ts b/frontend/src/context/auth/use-auth.ts new file mode 100644 index 000000000..ae5274dde --- /dev/null +++ b/frontend/src/context/auth/use-auth.ts @@ -0,0 +1,19 @@ +import { + useContext, +} from 'react'; + +import { AuthContext } from './auth-context'; + + +export function useAuth() { + const context = + useContext(AuthContext); + + if (!context) { + throw new Error( + 'useAuth must be used inside AuthProvider', + ); + } + + return context; +} \ No newline at end of file diff --git a/frontend/src/global.css b/frontend/src/global.css new file mode 100644 index 000000000..8bd8f44a8 --- /dev/null +++ b/frontend/src/global.css @@ -0,0 +1,56 @@ +/** ************************************** +* Fonts: app +*************************************** */ +@import '@fontsource-variable/dm-sans'; + +@import '@fontsource/barlow/400.css'; +@import '@fontsource/barlow/500.css'; +@import '@fontsource/barlow/600.css'; +@import '@fontsource/barlow/700.css'; +@import '@fontsource/barlow/800.css'; + +/** ************************************** +* Plugins +*************************************** */ +/* scrollbar */ +@import './components/scrollbar/styles.css'; + +/* chart */ +@import './components/chart/styles.css'; + +/** ************************************** +* Baseline +*************************************** */ +html { + height: 100%; + -webkit-overflow-scrolling: touch; +} +body, +#root, +#root__layout { + display: flex; + flex: 1 1 auto; + min-height: 100%; + flex-direction: column; +} +img { + max-width: 100%; + vertical-align: middle; +} +ul { + margin: 0; + padding: 0; + list-style-type: none; +} +input[type='number'] { + -moz-appearance: textfield; + appearance: none; +} +input[type='number']::-webkit-outer-spin-button { + margin: 0; + -webkit-appearance: none; +} +input[type='number']::-webkit-inner-spin-button { + margin: 0; + -webkit-appearance: none; +} diff --git a/frontend/src/guards/auth-guard.tsx b/frontend/src/guards/auth-guard.tsx new file mode 100644 index 000000000..5cbdbfc50 --- /dev/null +++ b/frontend/src/guards/auth-guard.tsx @@ -0,0 +1,13 @@ +import { Outlet, Navigate } from 'react-router-dom'; + +import { useAuth } from '../context/auth/use-auth'; + +export function AuthGuard() { + const { isAuthenticated } = useAuth(); + + if (!isAuthenticated) { + return ; + } + + return ; +} \ No newline at end of file diff --git a/frontend/src/guards/guest-guard.tsx b/frontend/src/guards/guest-guard.tsx new file mode 100644 index 000000000..84219c29d --- /dev/null +++ b/frontend/src/guards/guest-guard.tsx @@ -0,0 +1,16 @@ +import { Outlet, Navigate } from 'react-router-dom'; + +import { useAuth } from 'src/context/auth/use-auth'; +import { UserRole } from 'src/context/auth/auth.types'; + +export function GuestGuard() { + const { isAuthenticated, user } = useAuth(); + + if (isAuthenticated && user) { + if (user.role === UserRole.ADMIN) return ; + if (user.role === UserRole.VENUE_OWNER) return ; + return ; + } + + return ; +} diff --git a/frontend/src/guards/role.guard.tsx b/frontend/src/guards/role.guard.tsx new file mode 100644 index 000000000..964d82555 --- /dev/null +++ b/frontend/src/guards/role.guard.tsx @@ -0,0 +1,47 @@ +import type { UserRole } from 'src/context/auth/auth.types'; + +import { + Outlet, + Navigate, +} from 'react-router-dom'; + +import { useAuth } from 'src/context/auth/use-auth'; + + + +interface Props { + roles: UserRole[]; +} + +export function RoleGuard({ + roles, +}: Props) { + const { + user, + } = useAuth(); + + if (!user) { + return ( + + ); + } + + const allowed = + roles.includes( + user.role, + ); + + if (!allowed) { + return ( + + ); + } + + return ; +} \ No newline at end of file diff --git a/frontend/src/layouts/auth/content.tsx b/frontend/src/layouts/auth/content.tsx new file mode 100644 index 000000000..dafddefc9 --- /dev/null +++ b/frontend/src/layouts/auth/content.tsx @@ -0,0 +1,36 @@ +import type { BoxProps } from '@mui/material/Box'; + +import { mergeClasses } from 'minimal-shared/utils'; + +import Box from '@mui/material/Box'; + +import { layoutClasses } from '../core/classes'; + +// ---------------------------------------------------------------------- + +export type AuthContentProps = BoxProps; + +export function AuthContent({ sx, children, className, ...other }: AuthContentProps) { + return ( + ({ + py: 5, + px: 3, + width: 1, + zIndex: 2, + borderRadius: 2, + display: 'flex', + flexDirection: 'column', + maxWidth: 'var(--layout-auth-content-width)', + bgcolor: theme.vars.palette.background.default, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + {children} + + ); +} diff --git a/frontend/src/layouts/auth/index.ts b/frontend/src/layouts/auth/index.ts new file mode 100644 index 000000000..fa1aa0e77 --- /dev/null +++ b/frontend/src/layouts/auth/index.ts @@ -0,0 +1,3 @@ +export * from './layout'; + +export * from './content'; diff --git a/frontend/src/layouts/auth/layout.tsx b/frontend/src/layouts/auth/layout.tsx new file mode 100644 index 000000000..d73d71770 --- /dev/null +++ b/frontend/src/layouts/auth/layout.tsx @@ -0,0 +1,148 @@ +import type { CSSObject, Breakpoint } from '@mui/material/styles'; + +import { merge } from 'es-toolkit'; + +import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; +import Alert from '@mui/material/Alert'; + +import { RouterLink } from 'src/routes/components'; + +import { Logo } from 'src/components/logo'; + +import { AuthContent } from './content'; +import { MainSection } from '../core/main-section'; +import { LayoutSection } from '../core/layout-section'; +import { HeaderSection } from '../core/header-section'; + +import type { AuthContentProps } from './content'; +import type { MainSectionProps } from '../core/main-section'; +import type { HeaderSectionProps } from '../core/header-section'; +import type { LayoutSectionProps } from '../core/layout-section'; + +// ---------------------------------------------------------------------- + +type LayoutBaseProps = Pick; + +export type AuthLayoutProps = LayoutBaseProps & { + layoutQuery?: Breakpoint; + slotProps?: { + header?: HeaderSectionProps; + main?: MainSectionProps; + content?: AuthContentProps; + }; +}; + +export function AuthLayout({ + sx, + cssVars, + children, + slotProps, + layoutQuery = 'md', +}: AuthLayoutProps) { + const renderHeader = () => { + const headerSlotProps: HeaderSectionProps['slotProps'] = { container: { maxWidth: false } }; + + const headerSlots: HeaderSectionProps['slots'] = { + topArea: ( + + This is an info Alert. + + ), + leftArea: ( + <> + {/** @slot Logo */} + + + ), + rightArea: ( + + {/** @slot Help link */} + + Need help? + + + ), + }; + + return ( + + ); + }; + + const renderFooter = () => null; + + const renderMain = () => ( + ({ + alignItems: 'center', + p: theme.spacing(3, 2, 10, 2), + [theme.breakpoints.up(layoutQuery)]: { + justifyContent: 'center', + p: theme.spacing(10, 0, 10, 0), + }, + }), + ...(Array.isArray(slotProps?.main?.sx) + ? (slotProps?.main?.sx ?? []) + : [slotProps?.main?.sx]), + ]} + > + {children} + + ); + + return ( + ({ + position: 'relative', + '&::before': backgroundStyles(), + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + {renderMain()} + + ); +} + +// ---------------------------------------------------------------------- + +const backgroundStyles = (): CSSObject => ({ + zIndex: 1, + opacity: 0.24, + width: '100%', + height: '100%', + content: "''", + position: 'absolute', + backgroundSize: 'cover', + backgroundRepeat: 'no-repeat', + backgroundPosition: 'center center', + backgroundImage: 'url(/assets/background/overlay.jpg)', +}); diff --git a/frontend/src/layouts/components/account-popover.tsx b/frontend/src/layouts/components/account-popover.tsx new file mode 100644 index 000000000..781d01d3a --- /dev/null +++ b/frontend/src/layouts/components/account-popover.tsx @@ -0,0 +1,129 @@ +import type { IconButtonProps } from '@mui/material/IconButton'; + +import { useState, useCallback } from 'react'; + +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import Avatar from '@mui/material/Avatar'; +import Popover from '@mui/material/Popover'; +import Divider from '@mui/material/Divider'; +import Typography from '@mui/material/Typography'; +import IconButton from '@mui/material/IconButton'; + +import { _myAccount } from 'src/_mock'; +import { useAuth } from 'src/context/auth/use-auth'; + +// ---------------------------------------------------------------------- + +export type AccountPopoverProps = IconButtonProps & { + data?: { + label: string; + href: string; + icon?: React.ReactNode; + info?: React.ReactNode; + }[]; +}; + +export function AccountPopover({ data = [], sx, ...other }: AccountPopoverProps) { + const { user, logout } = useAuth() + + + const [openPopover, setOpenPopover] = useState(null); + + const handleOpenPopover = useCallback((event: React.MouseEvent) => { + setOpenPopover(event.currentTarget); + }, []); + + const handleClosePopover = useCallback(() => { + setOpenPopover(null); + }, []); + + return ( + <> + + `conic-gradient(${theme.vars.palette.primary.light}, ${theme.vars.palette.warning.light}, ${theme.vars.palette.primary.light})`, + ...sx, + }} + {...other} + > + + {_myAccount.displayName.charAt(0).toUpperCase()} + + + + + + + {user?.name} + + + + {user?.email} + + + + + + {/* + {data.map((option) => ( + handleClickItem(option.href)} + > + {option.icon} + {option.label} + + ))} + */} + + + + + + + + + ); +} diff --git a/frontend/src/layouts/components/language-popover.tsx b/frontend/src/layouts/components/language-popover.tsx new file mode 100644 index 000000000..1829e8b45 --- /dev/null +++ b/frontend/src/layouts/components/language-popover.tsx @@ -0,0 +1,109 @@ +import type { IconButtonProps } from '@mui/material/IconButton'; + +import { useState, useCallback } from 'react'; +import { usePopover } from 'minimal-shared/hooks'; + +import Box from '@mui/material/Box'; +import Popover from '@mui/material/Popover'; +import MenuList from '@mui/material/MenuList'; +import IconButton from '@mui/material/IconButton'; +import MenuItem, { menuItemClasses } from '@mui/material/MenuItem'; + +// ---------------------------------------------------------------------- + +export type LanguagePopoverProps = IconButtonProps & { + data?: { + value: string; + label: string; + icon: string; + }[]; +}; + +export function LanguagePopover({ data = [], sx, ...other }: LanguagePopoverProps) { + const { open, anchorEl, onClose, onOpen } = usePopover(); + + const [locale, setLocale] = useState(data[0].value); + + const handleChangeLang = useCallback( + (newLang: string) => { + setLocale(newLang); + onClose(); + }, + [onClose] + ); + + const currentLang = data.find((lang) => lang.value === locale); + + const renderFlag = (label?: string, icon?: string) => ( + + ); + + const renderMenuList = () => ( + + + {data?.map((option) => ( + handleChangeLang(option.value)} + > + {renderFlag(option.label, option.icon)} + {option.label} + + ))} + + + ); + + return ( + <> + ({ + p: 0, + width: 40, + height: 40, + ...(open && { bgcolor: theme.vars.palette.action.selected }), + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + {renderFlag(currentLang?.label, currentLang?.icon)} + + + {renderMenuList()} + + ); +} diff --git a/frontend/src/layouts/components/menu-button.tsx b/frontend/src/layouts/components/menu-button.tsx new file mode 100644 index 000000000..c1f226bf1 --- /dev/null +++ b/frontend/src/layouts/components/menu-button.tsx @@ -0,0 +1,15 @@ +import type { IconButtonProps } from '@mui/material/IconButton'; + +import IconButton from '@mui/material/IconButton'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +export function MenuButton({ sx, ...other }: IconButtonProps) { + return ( + + + + ); +} diff --git a/frontend/src/layouts/components/nav-upgrade.tsx b/frontend/src/layouts/components/nav-upgrade.tsx new file mode 100644 index 000000000..92861aaa3 --- /dev/null +++ b/frontend/src/layouts/components/nav-upgrade.tsx @@ -0,0 +1,64 @@ +import type { StackProps } from '@mui/material/Stack'; + +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import Typography from '@mui/material/Typography'; + +// ---------------------------------------------------------------------- + +export function NavUpgrade({ sx, ...other }: StackProps) { + return ( + + ({ + background: `linear-gradient(to right, ${theme.vars.palette.secondary.main}, ${theme.vars.palette.warning.main})`, + WebkitBackgroundClip: 'text', + WebkitTextFillColor: 'transparent', + backgroundClip: 'text', + textFillColor: 'transparent', + color: 'transparent', + }), + ]} + > + More features? + + + + {`From only `} + + $69 + + + + + + + + ); +} diff --git a/frontend/src/layouts/components/notifications-popover.tsx b/frontend/src/layouts/components/notifications-popover.tsx new file mode 100644 index 000000000..9ce008a1b --- /dev/null +++ b/frontend/src/layouts/components/notifications-popover.tsx @@ -0,0 +1,317 @@ +import type { IconButtonProps } from '@mui/material/IconButton'; +import type { Notification as NovuNotification } from '@novu/js'; + +import { useNotifications } from '@novu/react/hooks'; +import { useMemo, useState, useCallback } from 'react'; + +import Box from '@mui/material/Box'; +import List from '@mui/material/List'; +import Badge from '@mui/material/Badge'; +import Button from '@mui/material/Button'; +import Avatar from '@mui/material/Avatar'; +import Divider from '@mui/material/Divider'; +import Tooltip from '@mui/material/Tooltip'; +import Popover from '@mui/material/Popover'; +import Typography from '@mui/material/Typography'; +import IconButton from '@mui/material/IconButton'; +import ListItemText from '@mui/material/ListItemText'; +import ListSubheader from '@mui/material/ListSubheader'; +import ListItemAvatar from '@mui/material/ListItemAvatar'; +import ListItemButton from '@mui/material/ListItemButton'; +import CircularProgress from '@mui/material/CircularProgress'; + +import { useRouter } from 'src/routes/hooks'; + +import { fToNow } from 'src/utils/format-time'; + +import { Iconify } from 'src/components/iconify'; +import { Scrollbar } from 'src/components/scrollbar'; + +// ---------------------------------------------------------------------- + +export type NotificationsPopoverProps = IconButtonProps; + +export function NotificationsPopover({ sx, ...other }: NotificationsPopoverProps) { + const router = useRouter(); + + const { + notifications = [], + isLoading, + hasMore, + readAll, + fetchMore, + } = useNotifications({ limit: 20 }); + + const totalUnRead = useMemo( + () => notifications.filter((notification) => !notification.isRead).length, + [notifications] + ); + + const unreadNotifications = useMemo( + () => notifications.filter((notification) => !notification.isRead), + [notifications] + ); + + const readNotifications = useMemo( + () => notifications.filter((notification) => notification.isRead), + [notifications] + ); + + const [openPopover, setOpenPopover] = useState(null); + + const handleOpenPopover = useCallback((event: React.MouseEvent) => { + setOpenPopover(event.currentTarget); + }, []); + + const handleClosePopover = useCallback(() => { + setOpenPopover(null); + }, []); + + const handleMarkAllAsRead = useCallback(() => { + readAll(); + }, [readAll]); + + const handleClickNotification = useCallback( + (notification: NovuNotification) => { + if (!notification.isRead) { + notification.read(); + } + + handleClosePopover(); + + // const url = notification.redirect?.url; + // if (!url) return; + return + + // if (notification.redirect?.target === '_blank' || /^https?:\/\//i.test(url)) { + // window.open(url, notification.redirect?.target ?? '_blank'); + // } else { + // router.push(url); + // } + }, + [handleClosePopover, router] + ); + + return ( + <> + + + + + + + + + + Notifications + + You have {totalUnRead} unread messages + + + + {totalUnRead > 0 && ( + + + + + + )} + + + + + + {isLoading && notifications.length === 0 ? ( + + + + ) : notifications.length === 0 ? ( + + + You don't have any notifications yet + + + ) : ( + <> + {unreadNotifications.length > 0 && ( + + New + + } + > + {unreadNotifications.map((notification) => ( + + ))} + + )} + + {readNotifications.length > 0 && ( + + Before that + + } + > + {readNotifications.map((notification) => ( + + ))} + + )} + + )} + + + + + + + + + + ); +} + +// ---------------------------------------------------------------------- + +type NotificationItemProps = { + notification: NovuNotification; + onClick: (notification: NovuNotification) => void; +}; + +function getIcon(message: string) { + if (message.includes('welcome')) return 'mdi:human-welcome' + if (message.includes('booking') || message.includes('reservation')) return 'solar:calendar-mark-bold-duotone' + if (message.includes('payment')) return 'solar:wallet-money-bold-duotone' + return 'solar:bell-bing-bold-duotone' +} + +function NotificationItem({ notification, onClick }: NotificationItemProps) { + const { avatarUrl, title } = renderContent(notification); + + + return ( + onClick(notification)} + sx={{ + py: 1.5, + px: 2.5, + mt: '1px', + ...(!notification.isRead && { + bgcolor: 'action.selected', + }), + }} + > + + + + + + {fToNow(notification.createdAt)} + + } + /> + + ); +} + +// ---------------------------------------------------------------------- + +function getNotificationIcon(notification: NovuNotification) { + const text = `${notification.subject ?? ''} ${notification.body ?? ''}`.toLowerCase(); + + if (text.includes('welcome')) { + return 'solar:hand-stars-bold-duotone'; + } + if (text.includes('booking') || text.includes('reservation')) { + return 'solar:calendar-mark-bold-duotone'; + } + if (text.includes('payment') || text.includes('paid') || text.includes('refund') || text.includes('invoice')) { + return 'solar:wallet-money-bold-duotone'; + } + + return 'solar:bell-bing-bold-duotone'; +} + +function renderContent(notification: NovuNotification) { + const title = ( + + {notification.subject || notification.body} + {notification.subject && ( + +   {notification.body} + + )} + + ); + + return { + avatarUrl: notification.avatar ? null : ( + + ), + title, + }; +} diff --git a/frontend/src/layouts/components/searchbar.tsx b/frontend/src/layouts/components/searchbar.tsx new file mode 100644 index 000000000..31ac2036a --- /dev/null +++ b/frontend/src/layouts/components/searchbar.tsx @@ -0,0 +1,84 @@ +import type { BoxProps } from '@mui/material/Box'; + +import { useState, useCallback } from 'react'; +import { varAlpha } from 'minimal-shared/utils'; + +import Box from '@mui/material/Box'; +import Slide from '@mui/material/Slide'; +import Input from '@mui/material/Input'; +import Button from '@mui/material/Button'; +import { useTheme } from '@mui/material/styles'; +import IconButton from '@mui/material/IconButton'; +import InputAdornment from '@mui/material/InputAdornment'; +import ClickAwayListener from '@mui/material/ClickAwayListener'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +export function Searchbar({ sx, ...other }: BoxProps) { + const theme = useTheme(); + + const [open, setOpen] = useState(false); + + const handleOpen = useCallback(() => { + setOpen((prev) => !prev); + }, []); + + const handleClose = useCallback(() => { + setOpen(false); + }, []); + + return ( + +
    + {!open && ( + + + + )} + + + + + + + } + sx={{ fontWeight: 'fontWeightBold' }} + /> + + + +
    +
    + ); +} diff --git a/frontend/src/layouts/components/workspaces-popover.tsx b/frontend/src/layouts/components/workspaces-popover.tsx new file mode 100644 index 000000000..56b473c70 --- /dev/null +++ b/frontend/src/layouts/components/workspaces-popover.tsx @@ -0,0 +1,132 @@ +import type { ButtonBaseProps } from '@mui/material/ButtonBase'; + +import { useState, useCallback } from 'react'; +import { varAlpha } from 'minimal-shared/utils'; + +import Box from '@mui/material/Box'; +import Popover from '@mui/material/Popover'; +import MenuList from '@mui/material/MenuList'; +import ButtonBase from '@mui/material/ButtonBase'; +import MenuItem, { menuItemClasses } from '@mui/material/MenuItem'; + +import { Label } from 'src/components/label'; +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +export type WorkspacesPopoverProps = ButtonBaseProps & { + data?: { + id: string; + name: string; + logo: string; + plan: string; + }[]; +}; + +export function WorkspacesPopover({ data = [], sx, ...other }: WorkspacesPopoverProps) { + const [workspace, setWorkspace] = useState(data[0]); + + const [openPopover, setOpenPopover] = useState(null); + + const handleOpenPopover = useCallback((event: React.MouseEvent) => { + setOpenPopover(event.currentTarget); + }, []); + + const handleClosePopover = useCallback(() => { + setOpenPopover(null); + }, []); + + const handleChangeWorkspace = useCallback( + (newValue: (typeof data)[number]) => { + setWorkspace(newValue); + handleClosePopover(); + }, + [handleClosePopover] + ); + + const renderAvatar = (alt: string, src: string) => ( + + ); + + const renderLabel = (plan: string) => ( + + ); + + return ( + <> + varAlpha(theme.vars.palette.grey['500Channel'], 0.08), + ...sx, + }} + {...other} + > + {renderAvatar(workspace?.name, workspace?.logo)} + + + {workspace?.name} + {renderLabel(workspace?.plan)} + + + + + + + + {data.map((option) => ( + handleChangeWorkspace(option)} + > + {renderAvatar(option.name, option.logo)} + + + {option.name} + + + {renderLabel(option.plan)} + + ))} + + + + ); +} diff --git a/frontend/src/layouts/core/classes.ts b/frontend/src/layouts/core/classes.ts new file mode 100644 index 000000000..7058c094c --- /dev/null +++ b/frontend/src/layouts/core/classes.ts @@ -0,0 +1,17 @@ +import { createClasses } from 'src/theme/create-classes'; + +// ---------------------------------------------------------------------- + +export const layoutClasses = { + root: createClasses('layout__root'), + main: createClasses('layout__main'), + header: createClasses('layout__header'), + nav: { + root: createClasses('layout__nav__root'), + mobile: createClasses('layout__nav__mobile'), + vertical: createClasses('layout__nav__vertical'), + horizontal: createClasses('layout__nav__horizontal'), + }, + content: createClasses('layout__main__content'), + sidebarContainer: createClasses('layout__sidebar__container'), +}; diff --git a/frontend/src/layouts/core/css-vars.ts b/frontend/src/layouts/core/css-vars.ts new file mode 100644 index 000000000..2edd9c5fb --- /dev/null +++ b/frontend/src/layouts/core/css-vars.ts @@ -0,0 +1,14 @@ +import type { Theme } from '@mui/material/styles'; + +// ---------------------------------------------------------------------- + +export function layoutSectionVars(theme: Theme) { + return { + '--layout-nav-zIndex': theme.zIndex.drawer + 1, + '--layout-nav-mobile-width': '288px', + '--layout-header-blur': '8px', + '--layout-header-zIndex': theme.zIndex.appBar + 1, + '--layout-header-mobile-height': '64px', + '--layout-header-desktop-height': '72px', + }; +} diff --git a/frontend/src/layouts/core/header-section.tsx b/frontend/src/layouts/core/header-section.tsx new file mode 100644 index 000000000..336f00fa3 --- /dev/null +++ b/frontend/src/layouts/core/header-section.tsx @@ -0,0 +1,153 @@ +import type { AppBarProps } from '@mui/material/AppBar'; +import type { ContainerProps } from '@mui/material/Container'; +import type { Theme, SxProps, CSSObject, Breakpoint } from '@mui/material/styles'; + +import { useScrollOffsetTop } from 'minimal-shared/hooks'; +import { varAlpha, mergeClasses } from 'minimal-shared/utils'; + +import AppBar from '@mui/material/AppBar'; +import { styled } from '@mui/material/styles'; +import Container from '@mui/material/Container'; + +import { layoutClasses } from './classes'; + +// ---------------------------------------------------------------------- + +export type HeaderSectionProps = AppBarProps & { + layoutQuery?: Breakpoint; + disableOffset?: boolean; + disableElevation?: boolean; + slots?: { + leftArea?: React.ReactNode; + rightArea?: React.ReactNode; + topArea?: React.ReactNode; + centerArea?: React.ReactNode; + bottomArea?: React.ReactNode; + }; + slotProps?: { + container?: ContainerProps; + centerArea?: React.ComponentProps<'div'> & { sx?: SxProps }; + }; +}; + +export function HeaderSection({ + sx, + slots, + slotProps, + className, + disableOffset, + disableElevation, + layoutQuery = 'md', + ...other +}: HeaderSectionProps) { + const { offsetTop: isOffset } = useScrollOffsetTop(); + + return ( + ({ + ...(isOffset && { + '--color': `var(--offset-color, ${theme.vars.palette.text.primary})`, + }), + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + {slots?.topArea} + + + {slots?.leftArea} + + {slots?.centerArea} + + {slots?.rightArea} + + + {slots?.bottomArea} + + ); +} + +// ---------------------------------------------------------------------- + +type HeaderRootProps = Pick & { + isOffset: boolean; +}; + +const HeaderRoot = styled(AppBar, { + shouldForwardProp: (prop: string) => + !['isOffset', 'disableOffset', 'disableElevation', 'sx'].includes(prop), +})(({ isOffset, disableOffset, disableElevation, theme }) => { + const pauseZindex = { top: -1, bottom: -2 }; + + const pauseStyles: CSSObject = { + opacity: 0, + content: '""', + visibility: 'hidden', + position: 'absolute', + transition: theme.transitions.create(['opacity', 'visibility'], { + easing: theme.transitions.easing.easeInOut, + duration: theme.transitions.duration.shorter, + }), + }; + + const bgStyles: CSSObject = { + ...pauseStyles, + top: 0, + left: 0, + width: '100%', + height: '100%', + zIndex: pauseZindex.top, + backdropFilter: `blur(6px)`, + WebkitBackdropFilter: `blur(6px)`, + backgroundColor: varAlpha(theme.vars.palette.background.defaultChannel, 0.8), + ...(isOffset && { + opacity: 1, + visibility: 'visible', + }), + }; + + const shadowStyles: CSSObject = { + ...pauseStyles, + left: 0, + right: 0, + bottom: 0, + height: 24, + margin: 'auto', + borderRadius: '50%', + width: `calc(100% - 48px)`, + zIndex: pauseZindex.bottom, + boxShadow: theme.vars.customShadows.z8, + ...(isOffset && { opacity: 0.48, visibility: 'visible' }), + }; + + return { + boxShadow: 'none', + zIndex: 'var(--layout-header-zIndex)', + ...(!disableOffset && { '&::before': bgStyles }), + ...(!disableElevation && { '&::after': shadowStyles }), + }; +}); + +const HeaderContainer = styled(Container, { + shouldForwardProp: (prop: string) => !['layoutQuery', 'sx'].includes(prop), +})>(({ layoutQuery = 'md', theme }) => ({ + display: 'flex', + alignItems: 'center', + color: 'var(--color)', + height: 'var(--layout-header-mobile-height)', + [theme.breakpoints.up(layoutQuery)]: { height: 'var(--layout-header-desktop-height)' }, +})); + +const HeaderCenterArea = styled('div')(() => ({ + display: 'flex', + flex: '1 1 auto', + justifyContent: 'center', +})); diff --git a/frontend/src/layouts/core/index.ts b/frontend/src/layouts/core/index.ts new file mode 100644 index 000000000..c68992f62 --- /dev/null +++ b/frontend/src/layouts/core/index.ts @@ -0,0 +1,9 @@ +export * from './classes'; + +export * from './css-vars'; + +export * from './main-section'; + +export * from './layout-section'; + +export * from './header-section'; diff --git a/frontend/src/layouts/core/layout-section.tsx b/frontend/src/layouts/core/layout-section.tsx new file mode 100644 index 000000000..1789aa2df --- /dev/null +++ b/frontend/src/layouts/core/layout-section.tsx @@ -0,0 +1,75 @@ +import type { Theme, SxProps, CSSObject } from '@mui/material/styles'; + +import { mergeClasses } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; +import GlobalStyles from '@mui/material/GlobalStyles'; + +import { layoutClasses } from './classes'; +import { layoutSectionVars } from './css-vars'; + +// ---------------------------------------------------------------------- + +export type LayoutSectionProps = React.ComponentProps<'div'> & { + sx?: SxProps; + cssVars?: CSSObject; + children?: React.ReactNode; + footerSection?: React.ReactNode; + headerSection?: React.ReactNode; + sidebarSection?: React.ReactNode; +}; + +export function LayoutSection({ + sx, + cssVars, + children, + footerSection, + headerSection, + sidebarSection, + className, + ...other +}: LayoutSectionProps) { + const inputGlobalStyles = ( + ({ body: { ...layoutSectionVars(theme), ...cssVars } })} /> + ); + + return ( + <> + {inputGlobalStyles} + + + {sidebarSection ? ( + <> + {sidebarSection} + + {headerSection} + {children} + {footerSection} + + + ) : ( + <> + {headerSection} + {children} + {footerSection} + + )} + + + ); +} + +// ---------------------------------------------------------------------- + +const LayoutRoot = styled('div')``; + +const LayoutSidebarContainer = styled('div')(() => ({ + display: 'flex', + flex: '1 1 auto', + flexDirection: 'column', +})); diff --git a/frontend/src/layouts/core/main-section.tsx b/frontend/src/layouts/core/main-section.tsx new file mode 100644 index 000000000..1ac05c75e --- /dev/null +++ b/frontend/src/layouts/core/main-section.tsx @@ -0,0 +1,25 @@ +import { mergeClasses } from 'minimal-shared/utils'; + +import { styled } from '@mui/material/styles'; + +import { layoutClasses } from './classes'; + +// ---------------------------------------------------------------------- + +export type MainSectionProps = React.ComponentProps; + +export function MainSection({ children, className, sx, ...other }: MainSectionProps) { + return ( + + {children} + + ); +} + +// ---------------------------------------------------------------------- + +const MainRoot = styled('main')({ + display: 'flex', + flex: '1 1 auto', + flexDirection: 'column', +}); diff --git a/frontend/src/layouts/dashboard/content.tsx b/frontend/src/layouts/dashboard/content.tsx new file mode 100644 index 000000000..b007718b8 --- /dev/null +++ b/frontend/src/layouts/dashboard/content.tsx @@ -0,0 +1,57 @@ +import type { Breakpoint } from '@mui/material/styles'; +import type { ContainerProps } from '@mui/material/Container'; + +import { mergeClasses } from 'minimal-shared/utils'; + +import Container from '@mui/material/Container'; + +import { layoutClasses } from '../core/classes'; + +// ---------------------------------------------------------------------- + +export type DashboardContentProps = ContainerProps & { + layoutQuery?: Breakpoint; + disablePadding?: boolean; +}; + +export function DashboardContent({ + sx, + children, + className, + disablePadding, + maxWidth = 'lg', + layoutQuery = 'lg', + ...other +}: DashboardContentProps) { + return ( + ({ + display: 'flex', + flex: '1 1 auto', + flexDirection: 'column', + pt: 'var(--layout-dashboard-content-pt)', + pb: 'var(--layout-dashboard-content-pb)', + [theme.breakpoints.up(layoutQuery)]: { + px: 'var(--layout-dashboard-content-px)', + }, + ...(disablePadding && { + p: { + xs: 0, + sm: 0, + md: 0, + lg: 0, + xl: 0, + }, + }), + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + {children} + + ); +} diff --git a/frontend/src/layouts/dashboard/css-vars.ts b/frontend/src/layouts/dashboard/css-vars.ts new file mode 100644 index 000000000..d9220af8a --- /dev/null +++ b/frontend/src/layouts/dashboard/css-vars.ts @@ -0,0 +1,14 @@ +import type { Theme } from '@mui/material/styles'; + +// ---------------------------------------------------------------------- + +export function dashboardLayoutVars(theme: Theme) { + return { + '--layout-transition-easing': 'linear', + '--layout-transition-duration': '120ms', + '--layout-nav-vertical-width': '300px', + '--layout-dashboard-content-pt': theme.spacing(1), + '--layout-dashboard-content-pb': theme.spacing(8), + '--layout-dashboard-content-px': theme.spacing(5), + }; +} diff --git a/frontend/src/layouts/dashboard/index.ts b/frontend/src/layouts/dashboard/index.ts new file mode 100644 index 000000000..fa1aa0e77 --- /dev/null +++ b/frontend/src/layouts/dashboard/index.ts @@ -0,0 +1,3 @@ +export * from './layout'; + +export * from './content'; diff --git a/frontend/src/layouts/dashboard/layout.tsx b/frontend/src/layouts/dashboard/layout.tsx new file mode 100644 index 000000000..8b77792d9 --- /dev/null +++ b/frontend/src/layouts/dashboard/layout.tsx @@ -0,0 +1,152 @@ +import type { Breakpoint } from '@mui/material/styles'; + +import { merge } from 'es-toolkit'; +import { useBoolean } from 'minimal-shared/hooks'; + +import Box from '@mui/material/Box'; +import Alert from '@mui/material/Alert'; +import { useTheme } from '@mui/material/styles'; + +import { _langs } from 'src/_mock'; +import { useAuth } from 'src/context/auth/use-auth'; +import { UserRole } from 'src/context/auth/auth.types'; + +import { NavMobile, NavDesktop } from './nav'; +import { layoutClasses } from '../core/classes'; +import { _account } from '../nav-config-account'; +import { dashboardLayoutVars } from './css-vars'; +import { MainSection } from '../core/main-section'; +import { Searchbar } from '../components/searchbar'; +import { _workspaces } from '../nav-config-workspace'; +import { MenuButton } from '../components/menu-button'; +import { HeaderSection } from '../core/header-section'; +import { LayoutSection } from '../core/layout-section'; +import { AccountPopover } from '../components/account-popover'; +import { LanguagePopover } from '../components/language-popover'; +import { NotificationsPopover } from '../components/notifications-popover'; +import { navDataUser, navDataAdmin, navDataVenueOwner } from '../nav-config-dashboard'; + +import type { MainSectionProps } from '../core/main-section'; +import type { HeaderSectionProps } from '../core/header-section'; +import type { LayoutSectionProps } from '../core/layout-section'; + +// ---------------------------------------------------------------------- + +type LayoutBaseProps = Pick; + +export type DashboardLayoutProps = LayoutBaseProps & { + layoutQuery?: Breakpoint; + slotProps?: { + header?: HeaderSectionProps; + main?: MainSectionProps; + }; +}; + +export function DashboardLayout({ + sx, + cssVars, + children, + slotProps, + layoutQuery = 'lg', +}: DashboardLayoutProps) { + const theme = useTheme(); + const { user, isAuthenticated } = useAuth() + + const { value: open, onFalse: onClose, onTrue: onOpen } = useBoolean(); + const navData = isAuthenticated ? (user?.role === UserRole.ADMIN ? navDataAdmin : user?.role === UserRole.VENUE_OWNER ? navDataVenueOwner : navDataUser) : []; + + const renderHeader = () => { + const headerSlotProps: HeaderSectionProps['slotProps'] = { + container: { + maxWidth: false, + }, + }; + + const headerSlots: HeaderSectionProps['slots'] = { + topArea: ( + + This is an info Alert. + + ), + leftArea: ( + <> + {/** @slot Nav mobile */} + + + + ), + rightArea: ( + + {/** @slot Searchbar */} + + + {/** @slot Language popover */} + + + {/** @slot Notifications popover */} + + + {/** @slot Account drawer */} + + + ), + }; + + return ( + + ); + }; + + const renderFooter = () => null; + + const renderMain = () => {children}; + + return ( + + } + /** ************************************** + * @Footer + *************************************** */ + footerSection={renderFooter()} + /** ************************************** + * @Styles + *************************************** */ + cssVars={{ ...dashboardLayoutVars(theme), ...cssVars }} + sx={[ + { + [`& .${layoutClasses.sidebarContainer}`]: { + [theme.breakpoints.up(layoutQuery)]: { + pl: 'var(--layout-nav-vertical-width)', + transition: theme.transitions.create(['padding-left'], { + easing: 'var(--layout-transition-easing)', + duration: 'var(--layout-transition-duration)', + }), + }, + }, + }, + ...(Array.isArray(sx) ? sx : [sx]), + ]} + > + {renderMain()} + + ); +} diff --git a/frontend/src/layouts/dashboard/nav.tsx b/frontend/src/layouts/dashboard/nav.tsx new file mode 100644 index 000000000..f46007d54 --- /dev/null +++ b/frontend/src/layouts/dashboard/nav.tsx @@ -0,0 +1,194 @@ +import type { Theme, SxProps, Breakpoint } from '@mui/material/styles'; + +import { useEffect } from 'react'; +import { varAlpha } from 'minimal-shared/utils'; + +import Box from '@mui/material/Box'; +import ListItem from '@mui/material/ListItem'; +import { useTheme } from '@mui/material/styles'; +import ListItemButton from '@mui/material/ListItemButton'; +import Drawer, { drawerClasses } from '@mui/material/Drawer'; + +import { usePathname } from 'src/routes/hooks'; +import { RouterLink } from 'src/routes/components'; + +import { Logo } from 'src/components/logo'; +import { Scrollbar } from 'src/components/scrollbar'; + +import { NavUpgrade } from '../components/nav-upgrade'; +import { WorkspacesPopover } from '../components/workspaces-popover'; + +import type { NavItem } from '../nav-config-dashboard'; +import type { WorkspacesPopoverProps } from '../components/workspaces-popover'; + +// ---------------------------------------------------------------------- + +export type NavContentProps = { + data: NavItem[]; + slots?: { + topArea?: React.ReactNode; + bottomArea?: React.ReactNode; + }; + workspaces: WorkspacesPopoverProps['data']; + sx?: SxProps; +}; + +export function NavDesktop({ + sx, + data, + slots, + workspaces, + layoutQuery, +}: NavContentProps & { layoutQuery: Breakpoint }) { + const theme = useTheme(); + + return ( + + + + ); +} + +// ---------------------------------------------------------------------- + +export function NavMobile({ + sx, + data, + open, + slots, + onClose, + workspaces, +}: NavContentProps & { open: boolean; onClose: () => void }) { + const pathname = usePathname(); + + useEffect(() => { + if (open) { + onClose(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [pathname]); + + return ( + + + + ); +} + +// ---------------------------------------------------------------------- + +export function NavContent({ data, slots, workspaces, sx }: NavContentProps) { + const pathname = usePathname(); + + return ( + <> + + + {slots?.topArea} + + + + + + + {data.map((item) => { + const isActived = item.path === pathname; + + return ( + + ({ + pl: 2, + py: 1, + gap: 2, + pr: 1.5, + borderRadius: 0.75, + typography: 'body2', + fontWeight: 'fontWeightMedium', + color: theme.vars.palette.text.secondary, + minHeight: 44, + ...(isActived && { + fontWeight: 'fontWeightSemiBold', + color: theme.vars.palette.primary.main, + bgcolor: varAlpha(theme.vars.palette.primary.mainChannel, 0.08), + '&:hover': { + bgcolor: varAlpha(theme.vars.palette.primary.mainChannel, 0.16), + }, + }), + }), + ]} + > + + {item.icon} + + + + {item.title} + + + {item.info && item.info} + + + ); + })} + + + + + {slots?.bottomArea} + + + + ); +} diff --git a/frontend/src/layouts/nav-config-account.tsx b/frontend/src/layouts/nav-config-account.tsx new file mode 100644 index 000000000..ea32510d0 --- /dev/null +++ b/frontend/src/layouts/nav-config-account.tsx @@ -0,0 +1,23 @@ +import { Iconify } from 'src/components/iconify'; + +import type { AccountPopoverProps } from './components/account-popover'; + +// ---------------------------------------------------------------------- + +export const _account: AccountPopoverProps['data'] = [ + { + label: 'Home', + href: '/', + icon: , + }, + { + label: 'Profile', + href: '#', + icon: , + }, + { + label: 'Settings', + href: '#', + icon: , + }, +]; diff --git a/frontend/src/layouts/nav-config-dashboard.tsx b/frontend/src/layouts/nav-config-dashboard.tsx new file mode 100644 index 000000000..9143bc507 --- /dev/null +++ b/frontend/src/layouts/nav-config-dashboard.tsx @@ -0,0 +1,99 @@ +import { Label } from 'src/components/label'; +import { Iconify } from 'src/components/iconify'; +import { SvgColor } from 'src/components/svg-color'; + +// ---------------------------------------------------------------------- + +const icon = (name: string) => ; + +export type NavItem = { + title: string; + path: string; + icon: React.ReactNode; + info?: React.ReactNode; +}; + +export const navDataUser = [ + { + title: 'Dashboard', + path: '/', + icon: icon('ic-analytics'), + }, + { + title: 'User', + path: '/user', + icon: icon('ic-user'), + }, + { + title: 'Product', + path: '/products', + icon: icon('ic-cart'), + info: ( + + ), + }, + { + title: 'Blog', + path: '/blog', + icon: icon('ic-blog'), + }, + { + title: 'Sign in', + path: '/sign-in', + icon: icon('ic-lock'), + }, + { + title: 'Not found', + path: '/404', + icon: icon('ic-disabled'), + }, +]; + +export const navDataAdmin = [ + { + title: 'Dashboard', + path: '/admin', + icon: icon('ic-analytics'), + }, + { + title: 'User', + path: '/admin/users', + icon: icon('ic-user'), + }, + { + title: 'Venues', + path: '/admin/venues', + icon: icon('ic-cart'), + info: ( + + ), + }, +]; + + +export const navDataVenueOwner = [ + { + title: 'Dashboard', + path: '/owner', + icon: icon('ic-analytics'), + }, + { + title: 'My Venues', + path: '/owner/venues', + icon: , + }, + { + title: 'Bookings', + path: '/owner/bookings', + icon: , + // info: ( + // + // ), + }, +]; diff --git a/frontend/src/layouts/nav-config-workspace.tsx b/frontend/src/layouts/nav-config-workspace.tsx new file mode 100644 index 000000000..b665f885c --- /dev/null +++ b/frontend/src/layouts/nav-config-workspace.tsx @@ -0,0 +1,24 @@ +import type { WorkspacesPopoverProps } from './components/workspaces-popover'; + +// ---------------------------------------------------------------------- + +export const _workspaces: WorkspacesPopoverProps['data'] = [ + { + id: 'team-1', + name: 'Team 1', + plan: 'Free', + logo: '/assets/icons/workspaces/logo-1.webp', + }, + { + id: 'team-2', + name: 'Team 2', + plan: 'Pro', + logo: '/assets/icons/workspaces/logo-2.webp', + }, + { + id: 'team-3', + name: 'Team 3', + plan: 'Pro', + logo: '/assets/icons/workspaces/logo-3.webp', + }, +]; diff --git a/frontend/src/layouts/public/index.tsx b/frontend/src/layouts/public/index.tsx new file mode 100644 index 000000000..3fec35c39 --- /dev/null +++ b/frontend/src/layouts/public/index.tsx @@ -0,0 +1,26 @@ +import type { ReactNode } from 'react'; + +import { Box } from '@mui/material'; + +import { PublicNavbar } from './public-navbar'; +import { PublicFooter } from './public-footer'; + +interface PublicLayoutProps { + children: ReactNode; + transparentNavbar?: boolean; + hideFooter?: boolean; +} + +export function PublicLayout({ children, transparentNavbar = false, hideFooter = false }: PublicLayoutProps) { + return ( + + + + + {children} + + + {!hideFooter && } + + ); +} diff --git a/frontend/src/layouts/public/public-footer.tsx b/frontend/src/layouts/public/public-footer.tsx new file mode 100644 index 000000000..10e46a287 --- /dev/null +++ b/frontend/src/layouts/public/public-footer.tsx @@ -0,0 +1,188 @@ +import { Link } from 'react-router-dom'; + +import { + Box, + Grid, + Stack, + Divider, + Container, + IconButton, + Typography, +} from '@mui/material'; + +import { Iconify } from 'src/components/iconify'; + +const FOOTER_LINKS = { + Explore: [ + { label: 'Banquet Halls', href: '/search?venueType=BANQUET_HALL' }, + { label: 'Conference Rooms', href: '/search?venueType=CONFERENCE_ROOM' }, + { label: 'Event Spaces', href: '/search?venueType=EVENT_SPACE' }, + { label: 'Restaurants', href: '/search?venueType=RESTAURANT' }, + { label: 'Hotels & Resorts', href: '/search?venueType=HOTEL' }, + ], + Company: [ + { label: 'About Us', href: '/about' }, + { label: 'How It Works', href: '/#how-it-works' }, + { label: 'Blog', href: '/blog' }, + { label: 'Careers', href: '/careers' }, + { label: 'Press', href: '/press' }, + ], + Support: [ + { label: 'Help Center', href: '/faq' }, + { label: 'Contact Us', href: '/contact' }, + { label: 'Cancellation Policy', href: '/cancellation-policy' }, + { label: 'Safety Information', href: '/safety' }, + ], + Hosts: [ + { label: 'List Your Venue', href: '/sign-up?role=owner' }, + { label: 'Host Resources', href: '/host-resources' }, + { label: 'Community', href: '/community' }, + ], +}; + +const SOCIAL_LINKS = [ + { icon: 'mdi:facebook', href: '#', label: 'Facebook' }, + { icon: 'mdi:twitter', href: '#', label: 'Twitter' }, + { icon: 'mdi:instagram', href: '#', label: 'Instagram' }, + { icon: 'mdi:linkedin', href: '#', label: 'LinkedIn' }, + { icon: 'mdi:youtube', href: '#', label: 'YouTube' }, +]; + +export function PublicFooter() { + return ( + + + {/* Top Section */} + + {/* Brand */} + + + + + + + + BookMyVenue + + + + + Discover and book the perfect venue for your next event. From intimate gatherings to grand celebrations. + + + + {SOCIAL_LINKS.map((s) => ( + + + + ))} + + + + + + hello@bookmyvenue.in + + + + +91 98765 43210 + + + + + + {/* Links */} + {Object.entries(FOOTER_LINKS).map(([title, links]) => ( + + + {title} + + + {links.map((link) => ( + + {link.label} + + ))} + + + ))} + + + + + {/* Bottom Row */} + + + © {new Date().getFullYear()} BookMyVenue. All rights reserved. + + + + {['Privacy Policy', 'Terms of Service', 'Cookie Policy'].map((item) => ( + + {item} + + ))} + + + + + ); +} diff --git a/frontend/src/layouts/public/public-navbar.tsx b/frontend/src/layouts/public/public-navbar.tsx new file mode 100644 index 000000000..dcf5843bf --- /dev/null +++ b/frontend/src/layouts/public/public-navbar.tsx @@ -0,0 +1,365 @@ +import { useState } from 'react'; +import { Link, useNavigate } from 'react-router-dom'; + +import { + Box, + List, + Menu, + Stack, + AppBar, + Avatar, + Button, + Drawer, + Divider, + Toolbar, + ListItem, + MenuItem, + Container, + IconButton, + Typography, + ListItemText, + ListItemButton, + useScrollTrigger, +} from '@mui/material'; + +import { useAuth } from 'src/context/auth/use-auth'; +import { NotificationsPopover } from 'src/layouts/components/notifications-popover'; + +import { Iconify } from 'src/components/iconify'; + +const NAV_LINKS = [ + { label: 'Explore Venues', href: '/search' }, + { label: 'How It Works', href: '/#how-it-works' }, + { label: 'For Hosts', href: '/#for-hosts' }, +]; + +interface Props { + transparent?: boolean; +} + +export function PublicNavbar({ transparent = false }: Props) { + const navigate = useNavigate(); + const { isAuthenticated, user, logout } = useAuth(); + const [mobileOpen, setMobileOpen] = useState(false); + const [anchorEl, setAnchorEl] = useState(null); + + const scrolled = useScrollTrigger({ disableHysteresis: true, threshold: 60 }); + const elevated = !transparent || scrolled; + + const handleUserMenuOpen = (e: React.MouseEvent) => setAnchorEl(e.currentTarget); + const handleUserMenuClose = () => setAnchorEl(null); + + const handleLogout = () => { + handleUserMenuClose(); + logout(); + navigate('/'); + }; + + const userInitial = user?.name?.charAt(0).toUpperCase() ?? 'U'; + + return ( + <> + + + + {/* Logo */} + + + + + + BookMyVenue + + + + {/* Desktop Nav Links */} + + {NAV_LINKS.map((link) => ( + + ))} + + + + + {/* Desktop Auth Actions */} + + {isAuthenticated && user ? ( + <> + + + + + {userInitial} + + + + + {user.name} + {user.email} + + + { handleUserMenuClose(); navigate('/my/profile'); }}> + Profile + + { handleUserMenuClose(); navigate('/my/bookings'); }}> + My Bookings + + { handleUserMenuClose(); navigate('/my/favorites'); }}> + Favorites + + + + Sign Out + + + + ) : ( + <> + + + + )} + + + {/* Mobile notifications */} + {isAuthenticated && user && ( + + )} + + {/* Mobile hamburger */} + setMobileOpen(true)} + > + + + + + + + {/* Mobile Drawer */} + setMobileOpen(false)} + PaperProps={{ sx: { width: 280, borderRadius: '16px 0 0 16px' } }} + > + + + + BookMyVenue + + setMobileOpen(false)}> + + + + + {isAuthenticated && user && ( + + + {userInitial} + + + {user.name} + {user.email} + + + )} + + + {NAV_LINKS.map((link) => ( + + setMobileOpen(false)} + sx={{ borderRadius: 1.5, mb: 0.5 }} + > + + + + ))} + + {isAuthenticated && user ? ( + <> + + {[ + { label: 'My Bookings', href: '/my/bookings', icon: 'mdi:calendar-check-outline' }, + { label: 'Favorites', href: '/my/favorites', icon: 'mdi:heart-outline' }, + { label: 'Profile', href: '/my/profile', icon: 'mdi:account-outline' }, + ].map((item) => ( + + setMobileOpen(false)} + sx={{ borderRadius: 1.5, mb: 0.5 }} + > + + + + + ))} + + + + + + + + + ) : ( + <> + + + + + + + )} + + + + + ); +} diff --git a/frontend/src/lib/axios.ts b/frontend/src/lib/axios.ts new file mode 100644 index 000000000..e2715d1c2 --- /dev/null +++ b/frontend/src/lib/axios.ts @@ -0,0 +1,113 @@ +import axios, { type AxiosError } from 'axios'; + +import { tokenStorage } from './token'; + +const API_URL = + import.meta.env.VITE_API_URL; + +export const axiosClient = axios.create({ + baseURL: API_URL, + timeout: 30000, + headers: { + 'Content-Type': 'application/json', + }, +}); + +/** + * Request Interceptor + */ +axiosClient.interceptors.request.use( + (config) => { + const accessToken = + tokenStorage.getAccessToken(); + + if (accessToken) { + config.headers.Authorization = + `Bearer ${accessToken}`; + } + + return config; + }, + (error) => + Promise.reject(error), +); + +/** + * Response Interceptor + */ +axiosClient.interceptors.response.use( + (response) => response, + + async (error: AxiosError) => { + const originalRequest = error.config as any; + + if ( + error.response?.status !== 401 || + originalRequest?._retry + ) { + return Promise.reject(normalizeAxiosError(error)); + } + + originalRequest._retry = true; + + try { + const refreshToken = tokenStorage.getRefreshToken(); + + if (!refreshToken) { + throw error; + } + + const response = await axios.post( + `${API_URL}/auth/refresh`, + { + refreshToken, + }, + ); + + const { + accessToken, + refreshToken: newRefreshToken, + } = response.data; + + tokenStorage.setTokens( + accessToken, + newRefreshToken, + ); + + originalRequest.headers.Authorization = + `Bearer ${accessToken}`; + + return axiosClient(originalRequest); + } catch (refreshError) { + tokenStorage.clear(); + + // window.location.href = '/sign-in'; + + return Promise.reject( + normalizeAxiosError(refreshError), + ); + } + }, +); + +function normalizeAxiosError(error: unknown): Error { + if (!axios.isAxiosError(error)) { + return error instanceof Error + ? error + : new Error('Something went wrong'); + } + + const data = error.response?.data as any; + + const message = + data?.message || + data?.error || + error.message || + 'Something went wrong'; + + return new Error( + Array.isArray(message) + ? message.join('\n') + : message, + ); +} \ No newline at end of file diff --git a/frontend/src/lib/razorpay.ts b/frontend/src/lib/razorpay.ts new file mode 100644 index 000000000..563110f1f --- /dev/null +++ b/frontend/src/lib/razorpay.ts @@ -0,0 +1,69 @@ +import type { RazorpayCheckoutData } from 'src/api/types/payment.type'; + +export interface RazorpaySuccessResponse { + razorpay_order_id: string; + razorpay_payment_id: string; + razorpay_signature: string; +} + +declare global { + interface Window { + Razorpay?: new (options: Record) => { open: () => void }; + } +} + +export function loadRazorpayScript(): Promise { + if (typeof window === 'undefined') { + return Promise.resolve(false); + } + + if (window.Razorpay) { + return Promise.resolve(true); + } + + return new Promise((resolve) => { + const script = document.createElement('script'); + script.src = 'https://checkout.razorpay.com/v1/checkout.js'; + script.async = true; + script.onload = () => resolve(!!window.Razorpay); + script.onerror = () => resolve(false); + document.body.appendChild(script); + }); +} + +export function openRazorpayCheckout( + checkoutData: RazorpayCheckoutData, + options: { + name: string; + email?: string; + phone: string; + description?: string; + onSuccess: (response: RazorpaySuccessResponse) => void; + onDismiss?: () => void; + }, +): void { + if (!window.Razorpay) { + throw new Error('Razorpay SDK failed to load'); + } + + const rzp = new window.Razorpay({ + key: checkoutData.key, + amount: checkoutData.amount, + currency: checkoutData.currency, + order_id: checkoutData.orderId, + name: 'BookMyVenue', + description: options.description, + prefill: { + name: options.name, + email: options.email, + contact: options.phone, + }, + theme: { color: '#1877F2' }, + handler: options.onSuccess, + modal: { + ondismiss: options.onDismiss, + }, + }); + + rzp.open(); +} diff --git a/frontend/src/lib/token.ts b/frontend/src/lib/token.ts new file mode 100644 index 000000000..21b1eb7f0 --- /dev/null +++ b/frontend/src/lib/token.ts @@ -0,0 +1,41 @@ +const ACCESS_TOKEN_KEY = 'bmv_access_token'; +const REFRESH_TOKEN_KEY = 'bmv_refresh_token'; + +export const tokenStorage = { + getAccessToken(): string | null { + return localStorage.getItem( + ACCESS_TOKEN_KEY, + ); + }, + + getRefreshToken(): string | null { + return localStorage.getItem( + REFRESH_TOKEN_KEY, + ); + }, + + setTokens( + accessToken: string, + refreshToken: string, + ): void { + localStorage.setItem( + ACCESS_TOKEN_KEY, + accessToken, + ); + + localStorage.setItem( + REFRESH_TOKEN_KEY, + refreshToken, + ); + }, + + clear(): void { + localStorage.removeItem( + ACCESS_TOKEN_KEY, + ); + + localStorage.removeItem( + REFRESH_TOKEN_KEY, + ); + }, +}; \ No newline at end of file diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 000000000..9ae50be9c --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,29 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { Outlet, RouterProvider, createBrowserRouter } from 'react-router'; + +import App from './app'; +import { routesSection } from './routes/sections'; +import { ErrorBoundary } from './routes/components'; + +// ---------------------------------------------------------------------- + +const router = createBrowserRouter([ + { + Component: () => ( + + + + ), + errorElement: , + children: routesSection, + }, +]); + +const root = createRoot(document.getElementById('root')!); + +root.render( + + + +); diff --git a/frontend/src/pages/admin/dashboard.tsx b/frontend/src/pages/admin/dashboard.tsx new file mode 100644 index 000000000..f9862524e --- /dev/null +++ b/frontend/src/pages/admin/dashboard.tsx @@ -0,0 +1,12 @@ +import { CONFIG } from 'src/config-global'; + +import { AdminDashboard } from 'src/sections/admin/view/dashboard'; + +export default function AdminDashboardPage() { + return ( + <> + {`Admin Dashboard | ${CONFIG.appName}`} + + + ); +} diff --git a/frontend/src/pages/admin/users/create.tsx b/frontend/src/pages/admin/users/create.tsx new file mode 100644 index 000000000..fe71d7ebc --- /dev/null +++ b/frontend/src/pages/admin/users/create.tsx @@ -0,0 +1,16 @@ +import { CONFIG } from 'src/config-global'; + +import { CreateUserForm } from 'src/sections/admin/user/create'; + + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Create Users | ${CONFIG.appName}`} + + + + ); +} diff --git a/frontend/src/pages/admin/users/list.tsx b/frontend/src/pages/admin/users/list.tsx new file mode 100644 index 000000000..50707f7ea --- /dev/null +++ b/frontend/src/pages/admin/users/list.tsx @@ -0,0 +1,15 @@ +import { CONFIG } from 'src/config-global'; + +import { ListUsers } from 'src/sections/admin/user/list'; + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Users - ${CONFIG.appName}`} + + + + ); +} diff --git a/frontend/src/pages/admin/venues/list.tsx b/frontend/src/pages/admin/venues/list.tsx new file mode 100644 index 000000000..dfd6c8250 --- /dev/null +++ b/frontend/src/pages/admin/venues/list.tsx @@ -0,0 +1,14 @@ +import { CONFIG } from 'src/config-global'; + +import { VenueView } from 'src/sections/admin/venues/view'; + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Venues | ${CONFIG.appName}`} + + + ); +} diff --git a/frontend/src/pages/blog.tsx b/frontend/src/pages/blog.tsx new file mode 100644 index 000000000..2ce43be8a --- /dev/null +++ b/frontend/src/pages/blog.tsx @@ -0,0 +1,16 @@ +import { _posts } from 'src/_mock'; +import { CONFIG } from 'src/config-global'; + +import { BlogView } from 'src/sections/blog/view'; + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Blog - ${CONFIG.appName}`} + + + + ); +} diff --git a/frontend/src/pages/dashboard.tsx b/frontend/src/pages/dashboard.tsx new file mode 100644 index 000000000..a078c39b7 --- /dev/null +++ b/frontend/src/pages/dashboard.tsx @@ -0,0 +1,20 @@ +import { CONFIG } from 'src/config-global'; + +import { OverviewAnalyticsView as DashboardView } from 'src/sections/overview/view'; + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Dashboard - ${CONFIG.appName}`} + + + + + + ); +} diff --git a/frontend/src/pages/page-not-found.tsx b/frontend/src/pages/page-not-found.tsx new file mode 100644 index 000000000..3cb7ff17b --- /dev/null +++ b/frontend/src/pages/page-not-found.tsx @@ -0,0 +1,15 @@ +import { CONFIG } from 'src/config-global'; + +import { NotFoundView } from 'src/sections/error'; + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`404 page not found! | Error - ${CONFIG.appName}`} + + + + ); +} diff --git a/frontend/src/pages/products.tsx b/frontend/src/pages/products.tsx new file mode 100644 index 000000000..049603b9c --- /dev/null +++ b/frontend/src/pages/products.tsx @@ -0,0 +1,15 @@ +import { CONFIG } from 'src/config-global'; + +import { ProductsView } from 'src/sections/product/view'; + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Products - ${CONFIG.appName}`} + + + + ); +} diff --git a/frontend/src/pages/sign-in.tsx b/frontend/src/pages/sign-in.tsx new file mode 100644 index 000000000..dcc440c14 --- /dev/null +++ b/frontend/src/pages/sign-in.tsx @@ -0,0 +1,15 @@ +import { CONFIG } from 'src/config-global'; + +import { SignInView } from 'src/sections/auth'; + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Sign in - ${CONFIG.appName}`} + + + + ); +} diff --git a/frontend/src/pages/user.tsx b/frontend/src/pages/user.tsx new file mode 100644 index 000000000..68e1adcc3 --- /dev/null +++ b/frontend/src/pages/user.tsx @@ -0,0 +1,15 @@ +import { CONFIG } from 'src/config-global'; + +import { UserView } from 'src/sections/user/view'; + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Users - ${CONFIG.appName}`} + + + + ); +} diff --git a/frontend/src/pages/user/booking-details.tsx b/frontend/src/pages/user/booking-details.tsx new file mode 100644 index 000000000..f6ba94d88 --- /dev/null +++ b/frontend/src/pages/user/booking-details.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { BookingDetailsView } from 'src/sections/user/booking-details'; + +export default function BookingDetailsPage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/user/booking.tsx b/frontend/src/pages/user/booking.tsx new file mode 100644 index 000000000..eee5e7da5 --- /dev/null +++ b/frontend/src/pages/user/booking.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { BookingView } from 'src/sections/user/booking'; + +export default function BookingPage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/user/favorites.tsx b/frontend/src/pages/user/favorites.tsx new file mode 100644 index 000000000..18c796712 --- /dev/null +++ b/frontend/src/pages/user/favorites.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { FavoritesView } from 'src/sections/user/favorites'; + +export default function FavoritesPage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/user/landing.tsx b/frontend/src/pages/user/landing.tsx new file mode 100644 index 000000000..4722c8604 --- /dev/null +++ b/frontend/src/pages/user/landing.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { LandingView } from 'src/sections/user/landing'; + +export default function LandingPage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/user/my-bookings.tsx b/frontend/src/pages/user/my-bookings.tsx new file mode 100644 index 000000000..67cd68756 --- /dev/null +++ b/frontend/src/pages/user/my-bookings.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { MyBookingsView } from 'src/sections/user/my-bookings'; + +export default function MyBookingsPage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/user/payment.tsx b/frontend/src/pages/user/payment.tsx new file mode 100644 index 000000000..473232f49 --- /dev/null +++ b/frontend/src/pages/user/payment.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { PaymentView } from 'src/sections/user/payment'; + +export default function PaymentPage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/user/profile.tsx b/frontend/src/pages/user/profile.tsx new file mode 100644 index 000000000..ba2dd55ef --- /dev/null +++ b/frontend/src/pages/user/profile.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { ProfileView } from 'src/sections/user/profile'; + +export default function ProfilePage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/user/search.tsx b/frontend/src/pages/user/search.tsx new file mode 100644 index 000000000..011fd8f10 --- /dev/null +++ b/frontend/src/pages/user/search.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { SearchView } from 'src/sections/user/search'; + +export default function SearchPage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/user/venue-details.tsx b/frontend/src/pages/user/venue-details.tsx new file mode 100644 index 000000000..0fa09af45 --- /dev/null +++ b/frontend/src/pages/user/venue-details.tsx @@ -0,0 +1,11 @@ +import { PublicLayout } from 'src/layouts/public'; + +import { VenueDetailsView } from 'src/sections/user/venue-details'; + +export default function VenueDetailsPage() { + return ( + + + + ); +} diff --git a/frontend/src/pages/venue-owner/booking/details.tsx b/frontend/src/pages/venue-owner/booking/details.tsx new file mode 100644 index 000000000..4af98295f --- /dev/null +++ b/frontend/src/pages/venue-owner/booking/details.tsx @@ -0,0 +1,16 @@ +import { CONFIG } from 'src/config-global'; + +import { BookingDetails } from 'src/sections/venue-owner/booking/details'; + + + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Venue Bookings | ${CONFIG.appName}`} + + + ); +} diff --git a/frontend/src/pages/venue-owner/booking/list.tsx b/frontend/src/pages/venue-owner/booking/list.tsx new file mode 100644 index 000000000..cd13bfaac --- /dev/null +++ b/frontend/src/pages/venue-owner/booking/list.tsx @@ -0,0 +1,15 @@ +import { CONFIG } from 'src/config-global'; + +import { ListBookings } from 'src/sections/venue-owner/booking/list'; + + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Venue Bookings | ${CONFIG.appName}`} + + + ); +} diff --git a/frontend/src/pages/venue-owner/dashboard.tsx b/frontend/src/pages/venue-owner/dashboard.tsx new file mode 100644 index 000000000..ecb3d299a --- /dev/null +++ b/frontend/src/pages/venue-owner/dashboard.tsx @@ -0,0 +1,12 @@ +import { CONFIG } from 'src/config-global'; + +import { OwnerDashboard } from 'src/sections/venue-owner/view/dashboard'; + +export default function OwnerDashboardPage() { + return ( + <> + {`Owner Dashboard | ${CONFIG.appName}`} + + + ); +} diff --git a/frontend/src/pages/venue-owner/venues/create.tsx b/frontend/src/pages/venue-owner/venues/create.tsx new file mode 100644 index 000000000..b36b9bfbb --- /dev/null +++ b/frontend/src/pages/venue-owner/venues/create.tsx @@ -0,0 +1,15 @@ +import { CONFIG } from 'src/config-global'; + +import { CreateVenueForm } from 'src/sections/venue-owner/venues/create'; + + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`Create Venue | ${CONFIG.appName}`} + + + ); +} diff --git a/frontend/src/pages/venue-owner/venues/list.tsx b/frontend/src/pages/venue-owner/venues/list.tsx new file mode 100644 index 000000000..577dd9b51 --- /dev/null +++ b/frontend/src/pages/venue-owner/venues/list.tsx @@ -0,0 +1,15 @@ +import { CONFIG } from 'src/config-global'; + +import { ListVenues } from 'src/sections/venue-owner/venues/list'; + + +// ---------------------------------------------------------------------- + +export default function Page() { + return ( + <> + {`My Venues | ${CONFIG.appName}`} + + + ); +} diff --git a/frontend/src/routes/components/error-boundary.tsx b/frontend/src/routes/components/error-boundary.tsx new file mode 100644 index 000000000..66a032605 --- /dev/null +++ b/frontend/src/routes/components/error-boundary.tsx @@ -0,0 +1,168 @@ +import type { Theme, CSSObject } from '@mui/material/styles'; + +import { useRouteError, isRouteErrorResponse } from 'react-router'; + +import GlobalStyles from '@mui/material/GlobalStyles'; + +// ---------------------------------------------------------------------- + +export function ErrorBoundary() { + const error = useRouteError(); + + return ( + <> + {inputGlobalStyles()} + +
    +
    {renderErrorMessage(error)}
    +
    + + ); +} + +// ---------------------------------------------------------------------- + +function parseStackTrace(stack?: string) { + if (!stack) return { filePath: null, functionName: null }; + + const filePathMatch = stack.match(/\/src\/[^?]+/); + const functionNameMatch = stack.match(/at (\S+)/); + + return { + filePath: filePathMatch ? filePathMatch[0] : null, + functionName: functionNameMatch ? functionNameMatch[1] : null, + }; +} + +function renderErrorMessage(error: any) { + if (isRouteErrorResponse(error)) { + return ( + <> +

    + {error.status}: {error.statusText} +

    +

    {error.data}

    + + ); + } + + if (error instanceof Error) { + const { filePath, functionName } = parseStackTrace(error.stack); + + return ( + <> +

    Unexpected Application Error!

    +

    + {error.name}: {error.message} +

    +
    {error.stack}
    + {(filePath || functionName) && ( +

    + {filePath} ({functionName}) +

    + )} + + ); + } + + return

    Unknown Error

    ; +} + +// ---------------------------------------------------------------------- + +const errorBoundaryClasses = { + root: 'error-boundary-root', + container: 'error-boundary-container', + title: 'error-boundary-title', + details: 'error-boundary-details', + message: 'error-boundary-message', + filePath: 'error-boundary-file-path', +}; + +const cssVars: CSSObject = { + '--info-color': '#2dd9da', + '--warning-color': '#e2aa53', + '--error-color': '#ff5555', + '--error-background': '#2a1e1e', + '--details-background': '#111111', + '--root-background': '#2c2c2e', + '--container-background': '#1c1c1e', + '--font-stack-monospace': + '"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace', + '--font-stack-sans': + '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"', +}; + +const rootStyles = (): CSSObject => ({ + display: 'flex', + flex: '1 1 auto', + alignItems: 'center', + padding: '10vh 15px 0', + flexDirection: 'column', + fontFamily: 'var(--font-stack-sans)', +}); + +const contentStyles = (): CSSObject => ({ + gap: 24, + padding: 20, + width: '100%', + maxWidth: 960, + display: 'flex', + borderRadius: 8, + flexDirection: 'column', + backgroundColor: 'var(--container-background)', +}); + +const titleStyles = (theme: Theme): CSSObject => ({ + margin: 0, + lineHeight: 1.2, + fontSize: theme.typography.pxToRem(20), + fontWeight: theme.typography.fontWeightBold, +}); + +const messageStyles = (theme: Theme): CSSObject => ({ + margin: 0, + lineHeight: 1.5, + padding: '12px 16px', + whiteSpace: 'pre-wrap', + color: 'var(--error-color)', + fontSize: theme.typography.pxToRem(14), + fontFamily: 'var(--font-stack-monospace)', + backgroundColor: 'var(--error-background)', + borderLeft: '2px solid var(--error-color)', + fontWeight: theme.typography.fontWeightBold, +}); + +const detailsStyles = (): CSSObject => ({ + margin: 0, + padding: 16, + lineHeight: 1.5, + overflow: 'auto', + borderRadius: 'inherit', + color: 'var(--warning-color)', + backgroundColor: 'var(--details-background)', +}); + +const filePathStyles = (): CSSObject => ({ + marginTop: 0, + color: 'var(--info-color)', +}); + +const inputGlobalStyles = () => ( + ({ + body: { + ...cssVars, + margin: 0, + color: 'white', + backgroundColor: 'var(--root-background)', + [`& .${errorBoundaryClasses.root}`]: rootStyles(), + [`& .${errorBoundaryClasses.container}`]: contentStyles(), + [`& .${errorBoundaryClasses.title}`]: titleStyles(theme), + [`& .${errorBoundaryClasses.message}`]: messageStyles(theme), + [`& .${errorBoundaryClasses.filePath}`]: filePathStyles(), + [`& .${errorBoundaryClasses.details}`]: detailsStyles(), + }, + })} + /> +); diff --git a/frontend/src/routes/components/index.ts b/frontend/src/routes/components/index.ts new file mode 100644 index 000000000..12530ea1e --- /dev/null +++ b/frontend/src/routes/components/index.ts @@ -0,0 +1,3 @@ +export * from './router-link'; + +export * from './error-boundary'; diff --git a/frontend/src/routes/components/router-link.tsx b/frontend/src/routes/components/router-link.tsx new file mode 100644 index 000000000..ac48a7601 --- /dev/null +++ b/frontend/src/routes/components/router-link.tsx @@ -0,0 +1,14 @@ +import type { LinkProps } from 'react-router'; + +import { Link } from 'react-router'; + +// ---------------------------------------------------------------------- + +interface RouterLinkProps extends Omit { + href: string; + ref?: React.RefObject; +} + +export function RouterLink({ href, ref, ...other }: RouterLinkProps) { + return ; +} diff --git a/frontend/src/routes/hooks/index.ts b/frontend/src/routes/hooks/index.ts new file mode 100644 index 000000000..03b735171 --- /dev/null +++ b/frontend/src/routes/hooks/index.ts @@ -0,0 +1,3 @@ +export { useRouter } from './use-router'; + +export { usePathname } from './use-pathname'; diff --git a/frontend/src/routes/hooks/use-pathname.ts b/frontend/src/routes/hooks/use-pathname.ts new file mode 100644 index 000000000..76a035e04 --- /dev/null +++ b/frontend/src/routes/hooks/use-pathname.ts @@ -0,0 +1,10 @@ +import { useMemo } from 'react'; +import { useLocation } from 'react-router'; + +// ---------------------------------------------------------------------- + +export function usePathname() { + const { pathname } = useLocation(); + + return useMemo(() => pathname, [pathname]); +} diff --git a/frontend/src/routes/hooks/use-router.ts b/frontend/src/routes/hooks/use-router.ts new file mode 100644 index 000000000..2a7ecf69c --- /dev/null +++ b/frontend/src/routes/hooks/use-router.ts @@ -0,0 +1,21 @@ +import { useMemo } from 'react'; +import { useNavigate } from 'react-router'; + +// ---------------------------------------------------------------------- + +export function useRouter() { + const navigate = useNavigate(); + + const router = useMemo( + () => ({ + back: () => navigate(-1), + forward: () => navigate(1), + refresh: () => navigate(0), + push: (href: string) => navigate(href), + replace: (href: string) => navigate(href, { replace: true }), + }), + [navigate] + ); + + return router; +} diff --git a/frontend/src/routes/sections.tsx b/frontend/src/routes/sections.tsx new file mode 100644 index 000000000..fce897d14 --- /dev/null +++ b/frontend/src/routes/sections.tsx @@ -0,0 +1,271 @@ +import type { RouteObject } from 'react-router'; + +import { lazy, Suspense } from 'react'; +import { varAlpha } from 'minimal-shared/utils'; +import { Outlet, Navigate } from 'react-router-dom'; + +import Box from '@mui/material/Box'; +import LinearProgress, { linearProgressClasses } from '@mui/material/LinearProgress'; + +import { AuthLayout } from 'src/layouts/auth'; +import { RoleGuard } from 'src/guards/role.guard'; +import { AuthGuard } from 'src/guards/auth-guard'; +import { GuestGuard } from 'src/guards/guest-guard'; +import { UserRole } from 'src/context/auth/auth.types'; +import { DashboardLayout } from 'src/layouts/dashboard'; + +// ---------------------------------------------------------------------- + +// Public / Consumer Pages +export const LandingPage = lazy(() => import('src/pages/user/landing')); +export const SearchPage = lazy(() => import('src/pages/user/search')); +export const VenueDetailsPage = lazy(() => import('src/pages/user/venue-details')); +export const BookingPage = lazy(() => import('src/pages/user/booking')); + +// Authenticated User Pages +export const MyBookingsPage = lazy(() => import('src/pages/user/my-bookings')); +export const BookingDetailsPage = lazy(() => import('src/pages/user/booking-details')); +export const PaymentPage = lazy(() => import('src/pages/user/payment')); +export const FavoritesPage = lazy(() => import('src/pages/user/favorites')); +export const ProfilePage = lazy(() => import('src/pages/user/profile')); + +// Auth Pages +export const SignInPage = lazy(() => import('src/pages/sign-in')); +export const Page404 = lazy(() => import('src/pages/page-not-found')); + +// Admin pages +export const AdminDashboardPage = lazy(() => import('src/pages/admin/dashboard')); +export const AdminVenuesPage = lazy(() => import('src/pages/admin/venues/list')); +export const AdminUsersPage = lazy(() => import('src/pages/admin/users/list')); +export const CreateUsersPage = lazy(() => import('src/pages/admin/users/create')); + +// Owner pages +export const OwnerDashboardPage = lazy(() => import('src/pages/venue-owner/dashboard')); +export const OwnerVenuesPage = lazy(() => import('src/pages/venue-owner/venues/list')); +export const CreateVenuePage = lazy(() => import('src/pages/venue-owner/venues/create')); +export const OwnerBookingPage = lazy(() => import('src/pages/venue-owner/booking/list')); +export const OwnerBookingDetailsPage = lazy(() => import('src/pages/venue-owner/booking/details')); + +const renderFallback = () => ( + + varAlpha(theme.vars.palette.text.primaryChannel, 0.16), + [`& .${linearProgressClasses.bar}`]: { bgcolor: 'text.primary' }, + }} + /> + +); + +export const routesSection: RouteObject[] = [ + // ───────────────────────────────────────────── + // PUBLIC ROUTES (no auth required) + // ───────────────────────────────────────────── + { + path: '/', + element: ( + + + + ), + }, + { + path: 'search', + element: ( + + + + ), + }, + { + path: 'venues/:venueId', + element: ( + + + + ), + }, + + // ───────────────────────────────────────────── + // GUEST ONLY (redirect if already authenticated) + // ───────────────────────────────────────────── + { + element: , + children: [ + { + path: 'sign-in', + element: ( + + + + + + ), + }, + ], + }, + + // ───────────────────────────────────────────── + // AUTHENTICATED USER ROUTES (any logged-in user) + // ───────────────────────────────────────────── + { + element: , + children: [ + // Booking flow — accessible to any authenticated user + { + path: 'booking/:venueId', + element: ( + + + + ), + }, + + // USER role — consumer pages + { + element: , + children: [ + { + path: 'my/bookings', + element: ( + + + + ), + }, + { + path: 'my/bookings/:bookingId/payment', + element: ( + + + + ), + }, + { + path: 'my/bookings/:bookingId', + element: ( + + + + ), + }, + { + path: 'my/favorites', + element: ( + + + + ), + }, + { + path: 'my/profile', + element: ( + + + + ), + }, + ], + }, + + // ─── VENUE OWNER ROUTES ─────────────────── + { + element: , + children: [ + { + element: ( + + + + + + ), + children: [ + { + path: 'owner', + element: , + }, + { + path: 'owner/venues', + element: , + }, + { + path: 'owner/venues/create', + element: , + }, + { + path: 'owner/bookings', + element: , + }, + { + path: 'owner/bookings/:bookingId', + element: , + }, + ], + }, + ], + }, + + // ─── ADMIN ROUTES ───────────────────────── + { + element: , + children: [ + { + element: ( + + + + + + ), + children: [ + { + path: 'admin', + element: , + }, + { + path: 'admin/users', + element: , + }, + { + path: 'admin/venues', + element: , + }, + { + path: 'admin/users/create', + element: , + }, + ], + }, + ], + }, + ], + }, + + // ───────────────────────────────────────────── + // ERROR ROUTES + // ───────────────────────────────────────────── + { + path: '404', + element: ( + + + + ), + }, + + { + path: '*', + element: , + }, +]; diff --git a/frontend/src/sections/admin/user/create/index.tsx b/frontend/src/sections/admin/user/create/index.tsx new file mode 100644 index 000000000..072b67dc6 --- /dev/null +++ b/frontend/src/sections/admin/user/create/index.tsx @@ -0,0 +1,265 @@ +import { z } from "zod"; +import { useForm } from "react-hook-form"; +import { useMutation } from "@tanstack/react-query"; +import { zodResolver } from "@hookform/resolvers/zod"; + +import { LoadingButton } from "@mui/lab"; +import { + Box, + Card, + Grid, + Stack, + MenuItem, + TextField, + CardHeader, + Typography, + CardContent, +} from "@mui/material"; + +import { AdminApiService } from "src/api/admin"; +import { UserRole } from "src/api/types/auth.type"; + + +const schema = z.object({ + email: z.email(), + + password: z + .string() + .min(8, "Password must contain at least 8 characters"), + + firstName: z + .string() + .min(1, "First name is required"), + + lastName: z.string().optional(), + + phone: z.string().optional(), + + role: z.enum([ + UserRole.USER, + UserRole.VENUE_OWNER, + ]), +}); + +export type CreateUserFormValues = z.infer< + typeof schema +>; + +export function CreateUserForm() { + const { + register, + handleSubmit, + reset, + formState: { errors }, + } = useForm({ + resolver: zodResolver(schema), + + defaultValues: { + role: UserRole.USER, + }, + }); + + const { isPending, mutateAsync } = useMutation({ + mutationFn: ( + data: CreateUserFormValues + ) => AdminApiService.createUser(data), + }); + + const onSubmit = async ( + data: CreateUserFormValues + ) => { + await mutateAsync(data); + + reset(); + }; + + return ( + + + + Create User + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + User + + + + Venue Owner + + + + + + + + Create User + + + + + + + + + ); +} \ No newline at end of file diff --git a/frontend/src/sections/admin/user/list/index.tsx b/frontend/src/sections/admin/user/list/index.tsx new file mode 100644 index 000000000..df3f1c18a --- /dev/null +++ b/frontend/src/sections/admin/user/list/index.tsx @@ -0,0 +1,72 @@ + +import { Box, Avatar } from "@mui/material"; + +import { AdminApiService } from "src/api/admin"; + +import { Label } from "src/components/label"; +import { Iconify } from "src/components/iconify"; +import { DataTable } from "src/components/data-table"; + + +export function ListUsers() { + + + return ( + + + {data.firstName} {data.lastName}
    + + ) + }, + }, + { + id: 'role', + label: 'Role', + }, + { + id: 'verified', + label: 'Verified', + component(data) { + return <> + {data.status === 'ACTIVE' ? ( + + ) : ( + '-' + )} + + }, + }, + { + id: 'status', + label: 'Status', + component(data) { + return ( + + ) + }, + }, + ]} + /> + ) +} \ No newline at end of file diff --git a/frontend/src/sections/admin/venues/table-empty-rows.tsx b/frontend/src/sections/admin/venues/table-empty-rows.tsx new file mode 100644 index 000000000..6bc9ee0ba --- /dev/null +++ b/frontend/src/sections/admin/venues/table-empty-rows.tsx @@ -0,0 +1,26 @@ +import type { TableRowProps } from '@mui/material/TableRow'; + +import TableRow from '@mui/material/TableRow'; +import TableCell from '@mui/material/TableCell'; + +// ---------------------------------------------------------------------- + +type TableEmptyRowsProps = TableRowProps & { + emptyRows: number; + height?: number; +}; + +export function TableEmptyRows({ emptyRows, height, sx, ...other }: TableEmptyRowsProps) { + if (!emptyRows) { + return null; + } + + return ( + + + + ); +} diff --git a/frontend/src/sections/admin/venues/table-no-data.tsx b/frontend/src/sections/admin/venues/table-no-data.tsx new file mode 100644 index 000000000..914e23f38 --- /dev/null +++ b/frontend/src/sections/admin/venues/table-no-data.tsx @@ -0,0 +1,32 @@ +import type { TableRowProps } from '@mui/material/TableRow'; + +import Box from '@mui/material/Box'; +import TableRow from '@mui/material/TableRow'; +import TableCell from '@mui/material/TableCell'; +import Typography from '@mui/material/Typography'; + +// ---------------------------------------------------------------------- + +type TableNoDataProps = TableRowProps & { + searchQuery: string; +}; + +export function TableNoData({ searchQuery, ...other }: TableNoDataProps) { + return ( + + + + + Not found + + + + No results found for   + "{searchQuery}". +
    Try checking for typos or using complete words. +
    +
    +
    +
    + ); +} diff --git a/frontend/src/sections/admin/venues/utils.ts b/frontend/src/sections/admin/venues/utils.ts new file mode 100644 index 000000000..da91626e1 --- /dev/null +++ b/frontend/src/sections/admin/venues/utils.ts @@ -0,0 +1,78 @@ + +// ---------------------------------------------------------------------- + +export const visuallyHidden = { + border: 0, + margin: -1, + padding: 0, + width: '1px', + height: '1px', + overflow: 'hidden', + position: 'absolute', + whiteSpace: 'nowrap', + clip: 'rect(0 0 0 0)', +} as const; + +// ---------------------------------------------------------------------- + +export function emptyRows(page: number, rowsPerPage: number, arrayLength: number) { + return page ? Math.max(0, (1 + page) * rowsPerPage - arrayLength) : 0; +} + +// ---------------------------------------------------------------------- + +function descendingComparator(a: T, b: T, orderBy: keyof T) { + if (b[orderBy] < a[orderBy]) { + return -1; + } + if (b[orderBy] > a[orderBy]) { + return 1; + } + return 0; +} + +// ---------------------------------------------------------------------- + +export function getComparator( + order: 'asc' | 'desc', + orderBy: Key +): ( + a: { + [key in Key]: number | string; + }, + b: { + [key in Key]: number | string; + } +) => number { + return order === 'desc' + ? (a, b) => descendingComparator(a, b, orderBy) + : (a, b) => -descendingComparator(a, b, orderBy); +} + +// ---------------------------------------------------------------------- + +type ApplyFilterProps = { + inputData: any[]; + filterName: string; + comparator: (a: any, b: any) => number; +}; + +export function applyFilter({ inputData, comparator, filterName }: ApplyFilterProps) { + const stabilizedThis = inputData.map((el, index) => [el, index] as const); + + stabilizedThis.sort((a, b) => { + const order = comparator(a[0], b[0]); + if (order !== 0) return order; + return a[1] - b[1]; + }); + + inputData = stabilizedThis.map((el) => el[0]); + + if (filterName) { + inputData = inputData.filter( + (user) => user.name.toLowerCase().indexOf(filterName.toLowerCase()) !== -1 + ); + } + + return inputData; +} diff --git a/frontend/src/sections/admin/venues/venue-table-head.tsx b/frontend/src/sections/admin/venues/venue-table-head.tsx new file mode 100644 index 000000000..d9aafe53d --- /dev/null +++ b/frontend/src/sections/admin/venues/venue-table-head.tsx @@ -0,0 +1,69 @@ +import Box from '@mui/material/Box'; +import TableRow from '@mui/material/TableRow'; +import Checkbox from '@mui/material/Checkbox'; +import TableHead from '@mui/material/TableHead'; +import TableCell from '@mui/material/TableCell'; +import TableSortLabel from '@mui/material/TableSortLabel'; + +import { visuallyHidden } from './utils'; + +// ---------------------------------------------------------------------- + +type VenueTableHeadProps = { + orderBy: string; + rowCount: number; + numSelected: number; + order: 'asc' | 'desc'; + onSort: (id: string) => void; + headLabel: Record[]; + onSelectAllRows: (checked: boolean) => void; +}; + +export function VenueTableHead({ + order, + onSort, + orderBy, + rowCount, + headLabel, + numSelected, + onSelectAllRows, +}: VenueTableHeadProps) { + return ( + + + + 0 && numSelected < rowCount} + checked={rowCount > 0 && numSelected === rowCount} + onChange={(event: React.ChangeEvent) => + onSelectAllRows(event.target.checked) + } + /> + + + {headLabel.map((headCell) => ( + + onSort(headCell.id)} + > + {headCell.label} + {orderBy === headCell.id ? ( + + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + + ))} + + + ); +} diff --git a/frontend/src/sections/admin/venues/venue-table-row.tsx b/frontend/src/sections/admin/venues/venue-table-row.tsx new file mode 100644 index 000000000..a03c644cf --- /dev/null +++ b/frontend/src/sections/admin/venues/venue-table-row.tsx @@ -0,0 +1,116 @@ +import { useState, useCallback } from 'react'; + +import TableRow from '@mui/material/TableRow'; +import Checkbox from '@mui/material/Checkbox'; +import TableCell from '@mui/material/TableCell'; +import { Popover, MenuItem, MenuList, IconButton, menuItemClasses } from '@mui/material'; + +import { AdminApiService } from 'src/api/admin'; +import { VenueStatus } from 'src/api/types/venue.type'; + +import { Label } from 'src/components/label'; +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +type VenueTableRowProps = { + row: any; + selected: boolean; + onSelectRow: () => void; +}; + +export function VenueTableRow({ row, selected, onSelectRow }: VenueTableRowProps) { + const [openPopover, setOpenPopover] = useState(null); + const [status, setStatus] = useState(row.status) + + const handleOpenPopover = useCallback((event: React.MouseEvent) => { + setOpenPopover(event.currentTarget); + }, []); + + const handleClosePopover = useCallback(() => { + setOpenPopover(null); + }, []); + + const handleApprove = useCallback(() => { + handleClosePopover() + setStatus(VenueStatus.APPROVED) + AdminApiService.approveVenue(row.id) + }, []); + + const handleReject = useCallback(() => { + handleClosePopover() + setStatus(VenueStatus.REJECTED) + AdminApiService.rejectVenue(row.id) + }, []); + + + return ( + <> + + + + + {/* + + + {row.name} + + */} + {row.title} + {row.venueType} + {row.addressLine1} + + + + + { + status === VenueStatus.PENDING && + + + + } + + + + + + + Approve + + + + + Reject + + + + + ); +} diff --git a/frontend/src/sections/admin/venues/venue-table-toolbar.tsx b/frontend/src/sections/admin/venues/venue-table-toolbar.tsx new file mode 100644 index 000000000..988a8987b --- /dev/null +++ b/frontend/src/sections/admin/venues/venue-table-toolbar.tsx @@ -0,0 +1,66 @@ +import Tooltip from '@mui/material/Tooltip'; +import Toolbar from '@mui/material/Toolbar'; +import Typography from '@mui/material/Typography'; +import IconButton from '@mui/material/IconButton'; +import OutlinedInput from '@mui/material/OutlinedInput'; +import InputAdornment from '@mui/material/InputAdornment'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +type VenueTableToolbarProps = { + numSelected: number; + filterName: string; + onFilterName: (event: React.ChangeEvent) => void; +}; + +export function VenueTableToolbar({ numSelected, filterName, onFilterName }: VenueTableToolbarProps) { + return ( + theme.spacing(0, 1, 0, 3), + ...(numSelected > 0 && { + color: 'primary.main', + bgcolor: 'primary.lighter', + }), + }} + > + {numSelected > 0 ? ( + + {numSelected} selected + + ) : ( + + + + } + sx={{ maxWidth: 320 }} + /> + )} + + {numSelected > 0 ? ( + + + + + + ) : ( + + + + + + )} + + ); +} diff --git a/frontend/src/sections/admin/venues/view/index.ts b/frontend/src/sections/admin/venues/view/index.ts new file mode 100644 index 000000000..862c628ed --- /dev/null +++ b/frontend/src/sections/admin/venues/view/index.ts @@ -0,0 +1 @@ +export * from './venue-view'; diff --git a/frontend/src/sections/admin/venues/view/venue-view.tsx b/frontend/src/sections/admin/venues/view/venue-view.tsx new file mode 100644 index 000000000..9b165882f --- /dev/null +++ b/frontend/src/sections/admin/venues/view/venue-view.tsx @@ -0,0 +1,196 @@ +import { useState, useCallback } from 'react'; +import { useQuery } from '@tanstack/react-query'; + +import Box from '@mui/material/Box'; +import Card from '@mui/material/Card'; +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; +import Typography from '@mui/material/Typography'; +import TableContainer from '@mui/material/TableContainer'; +import TablePagination from '@mui/material/TablePagination'; + +import { _users } from 'src/_mock'; +import { AdminApiService } from 'src/api/admin'; +import { DashboardContent } from 'src/layouts/dashboard'; + +import { Scrollbar } from 'src/components/scrollbar'; + +import { emptyRows } from '../utils'; +import { TableNoData } from '../table-no-data'; +import { VenueTableRow } from '../venue-table-row'; +import { VenueTableHead } from '../venue-table-head'; +import { TableEmptyRows } from '../table-empty-rows'; +import { VenueTableToolbar } from '../venue-table-toolbar'; + + +// ---------------------------------------------------------------------- + + +export function VenueView() { + const table = useTable(); + + const [filterName, setFilterName] = useState(''); + const { data } = useQuery({ + queryKey: ['users'], + queryFn: () => AdminApiService.listVenues(table.page + 1, table.rowsPerPage), + }); + + const dataFiltered = data?.data || []; + + + const notFound = !dataFiltered.length && !!filterName; + + return ( + + + + Venues + + + + + ) => { + setFilterName(event.target.value); + table.onResetPage(); + }} + /> + + + + + + table.onSelectAllRows( + checked, + _users.map((user) => user.id) + ) + } + headLabel={[ + { id: 'name', label: 'Name' }, + { id: 'venueType', label: 'Type' }, + { id: 'addressLine1', label: 'Address' }, + { id: 'status', label: 'Status' }, + { id: '' }, + ]} + /> + + {dataFiltered + .slice( + table.page * table.rowsPerPage, + table.page * table.rowsPerPage + table.rowsPerPage + ) + .map((row) => ( + table.onSelectRow(row.id)} + /> + ))} + + + + {notFound && } + +
    +
    +
    + + +
    +
    + ); +} + +// ---------------------------------------------------------------------- + +export function useTable() { + const [page, setPage] = useState(0); + const [orderBy, setOrderBy] = useState('name'); + const [rowsPerPage, setRowsPerPage] = useState(5); + const [selected, setSelected] = useState([]); + const [order, setOrder] = useState<'asc' | 'desc'>('asc'); + + const onSort = useCallback( + (id: string) => { + const isAsc = orderBy === id && order === 'asc'; + setOrder(isAsc ? 'desc' : 'asc'); + setOrderBy(id); + }, + [order, orderBy] + ); + + const onSelectAllRows = useCallback((checked: boolean, newSelecteds: string[]) => { + if (checked) { + setSelected(newSelecteds); + return; + } + setSelected([]); + }, []); + + const onSelectRow = useCallback( + (inputValue: string) => { + const newSelected = selected.includes(inputValue) + ? selected.filter((value) => value !== inputValue) + : [...selected, inputValue]; + + setSelected(newSelected); + }, + [selected] + ); + + const onResetPage = useCallback(() => { + setPage(0); + }, []); + + const onChangePage = useCallback((event: unknown, newPage: number) => { + setPage(newPage); + }, []); + + const onChangeRowsPerPage = useCallback( + (event: React.ChangeEvent) => { + setRowsPerPage(parseInt(event.target.value, 10)); + onResetPage(); + }, + [onResetPage] + ); + + return { + page, + order, + onSort, + orderBy, + selected, + rowsPerPage, + onSelectRow, + onResetPage, + onChangePage, + onSelectAllRows, + onChangeRowsPerPage, + }; +} diff --git a/frontend/src/sections/admin/view/dashboard.tsx b/frontend/src/sections/admin/view/dashboard.tsx new file mode 100644 index 000000000..dc95190fa --- /dev/null +++ b/frontend/src/sections/admin/view/dashboard.tsx @@ -0,0 +1,322 @@ +import dayjs from 'dayjs'; +import { useNavigate } from 'react-router-dom'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; + +import { + Box, + Card, + Grid, + Stack, + Table, + Button, + Divider, + TableRow, + TableBody, + TableCell, + TableHead, + Typography, + CardContent, + TableContainer, + CircularProgress, +} from '@mui/material'; + +import { AdminApiService } from 'src/api/admin'; +import { DashboardApiService } from 'src/api/dashboard'; +import { DashboardContent } from 'src/layouts/dashboard'; + +import { Label } from 'src/components/label'; +import { Iconify } from 'src/components/iconify'; + +// ─── Stat card ──────────────────────────────────────────────────────────────── + +function StatCard({ + label, + value, + icon, + color, + sub, +}: { + label: string; + value: string | number; + icon: string; + color: string; + sub?: string; +}) { + return ( + + + + + + {label} + + + {value} + + {sub && ( + + {sub} + + )} + + + + + + + + ); +} + +const STATUS_COLOR: Record = { + PENDING: 'warning', + APPROVED: 'success', + REJECTED: 'error', + SUSPENDED: 'error', +}; + +const STATUS_BAR_COLOR: Record = { + APPROVED: '#22C55E', + PENDING: '#F59E0B', + REJECTED: '#EF4444', + SUSPENDED: '#9CA3AF', +}; + +// ─── Main component ──────────────────────────────────────────────────────────── + +export function AdminDashboard() { + const navigate = useNavigate(); + const queryClient = useQueryClient(); + + const { data, isLoading } = useQuery({ + queryKey: ['admin-dashboard'], + queryFn: DashboardApiService.getAdminDashboard, + retry: false, + }); + + const approveMutation = useMutation({ + mutationFn: (id: string) => AdminApiService.approveVenue(id), + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['admin-dashboard'] }), + }); + + const rejectMutation = useMutation({ + mutationFn: (id: string) => AdminApiService.rejectVenue(id), + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['admin-dashboard'] }), + }); + + const isActing = approveMutation.isPending || rejectMutation.isPending; + + const pendingCount = data?.approvalPendingVenues?.length ?? 0; + const approvedCount = data?.venueStatusSummary?.find((s) => s.status === 'APPROVED')?.count ?? 0; + + return ( + + {/* Header */} + + + Admin Dashboard + + Platform overview — {dayjs().format('dddd, D MMMM YYYY')} + + + + + {/* Stat cards */} + {isLoading ? ( + + + + ) : ( + <> + + {[ + { + label: 'Total Users', + value: data?.totalUsers ?? 0, + icon: 'mdi:account-group', + color: 'info', + sub: `${data?.totalOwners ?? 0} venue owners`, + }, + { + label: 'Total Venues', + value: data?.totalVenues ?? 0, + icon: 'mdi:domain', + color: 'primary', + sub: `${approvedCount} approved`, + }, + { + label: 'Pending Approval', + value: pendingCount, + icon: 'mdi:clock-outline', + color: 'warning', + sub: 'Awaiting review', + }, + { + label: 'Venue Owners', + value: data?.totalOwners ?? 0, + icon: 'mdi:account-tie', + color: 'success', + sub: 'Registered owners', + }, + ].map((s) => ( + + + + ))} + + + + {/* Pending Venues */} + + + + + Pending Approval + + Venues waiting for review + + + + + + + {(data?.approvalPendingVenues?.length ?? 0) === 0 ? ( + + + + No pending venues + + + ) : ( + + + + + Venue + Type + Capacity + Actions + + + + {data?.approvalPendingVenues.map((venue) => ( + + + + {venue.title} + + + {venue.addressLine1} + + + + + {venue.venueType?.replace(/_/g, ' ')} + + + + {venue.capacity} + + + + + + + + + ))} + +
    +
    + )} +
    +
    + + {/* Right column */} + + {/* Venue status breakdown */} + + + Venue Status Breakdown + + Distribution across all venues + + + + + {(data?.venueStatusSummary?.length ?? 0) === 0 ? ( + No data + ) : ( + + {data?.venueStatusSummary.map((item) => ( + + + + + + + {item.count} / {data?.totalVenues ?? 0} + + + + + + + ))} + + )} + + + +
    + + )} +
    + ); +} diff --git a/frontend/src/sections/auth/index.ts b/frontend/src/sections/auth/index.ts new file mode 100644 index 000000000..d9ccca24c --- /dev/null +++ b/frontend/src/sections/auth/index.ts @@ -0,0 +1 @@ +export * from './sign-in-view'; diff --git a/frontend/src/sections/auth/sign-in-view.tsx b/frontend/src/sections/auth/sign-in-view.tsx new file mode 100644 index 000000000..01768d6af --- /dev/null +++ b/frontend/src/sections/auth/sign-in-view.tsx @@ -0,0 +1,200 @@ +import { useState, useCallback } from 'react'; +import { Navigate, useNavigate } from 'react-router-dom'; + +import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; +import { Alert } from '@mui/material'; +import { LoadingButton } from '@mui/lab'; +import Divider from '@mui/material/Divider'; +import TextField from '@mui/material/TextField'; +import IconButton from '@mui/material/IconButton'; +import Typography from '@mui/material/Typography'; +import InputAdornment from '@mui/material/InputAdornment'; + +import { AuthApiService } from 'src/api/auth'; +import { useAuth } from 'src/context/auth/use-auth'; +import { UserRole } from 'src/context/auth/auth.types'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +export function SignInView() { + + const { login, isAuthenticated, user } = useAuth(); + const navigate = useNavigate() + + const [showPassword, setShowPassword] = useState(false); + const [email, setEmail] = useState('user@bmv.com'); + const [password, setPassword] = useState('password123'); + const [isLoading, setIsLoading] = useState(false); + const [errorMessage, setErrorMessage] = useState('') + + const handleSignIn = useCallback(async () => { + + setIsLoading(true); + + try { + setErrorMessage('') + const response = await AuthApiService.login({ email, password }); + login( + { + id: response.user.id, + name: `${response.user.firstName} ${response.user.lastName}`, + email, + role: response.user.role, + }, + { + accessToken: response.accessToken, + refreshToken: response.refreshToken, + }, + ); + switch (response.user.role) { + case UserRole.ADMIN: + navigate('/admin'); + break; + + case UserRole.VENUE_OWNER: + navigate('/owner'); + break; + + default: + navigate('/'); + break; + } + } catch (error) { + setErrorMessage((error as any).response?.data?.message) + } finally { + setIsLoading(false); + } + + return; + + }, [email, password, login]); + const renderForm = ( + + { + errorMessage && {errorMessage} + } + setEmail(event.target.value)} + sx={{ mb: 3 }} + slotProps={{ + inputLabel: { shrink: true }, + }} + /> + + + Forgot password? + + + setPassword(event.target.value)} + type={showPassword ? 'text' : 'password'} + slotProps={{ + inputLabel: { shrink: true }, + input: { + endAdornment: ( + + setShowPassword(!showPassword)} edge="end"> + + + + ), + }, + }} + sx={{ mb: 3 }} + /> + + + Sign in + + + ); + + if (isAuthenticated) { + switch (user?.role) { + case UserRole.ADMIN: + return ; + case UserRole.VENUE_OWNER: + return ; + default: + return ; + } + } + + return ( + <> + + Sign in + + Don’t have an account? + + Get started + + + + {renderForm} + + + OR + + + + + + + + + + + + + + + ); +} diff --git a/frontend/src/sections/blog/post-item.tsx b/frontend/src/sections/blog/post-item.tsx new file mode 100644 index 000000000..90980bf85 --- /dev/null +++ b/frontend/src/sections/blog/post-item.tsx @@ -0,0 +1,211 @@ +import type { CardProps } from '@mui/material/Card'; +import type { IconifyName } from 'src/components/iconify'; + +import { varAlpha } from 'minimal-shared/utils'; + +import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; +import Card from '@mui/material/Card'; +import Avatar from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; + +import { fDate } from 'src/utils/format-time'; +import { fShortenNumber } from 'src/utils/format-number'; + +import { Iconify } from 'src/components/iconify'; +import { SvgColor } from 'src/components/svg-color'; + +// ---------------------------------------------------------------------- + +export type IPostItem = { + id: string; + title: string; + coverUrl: string; + totalViews: number; + description: string; + totalShares: number; + totalComments: number; + totalFavorites: number; + postedAt: string | number | null; + author: { + name: string; + avatarUrl: string; + }; +}; + +export function PostItem({ + sx, + post, + latestPost, + latestPostLarge, + ...other +}: CardProps & { + post: IPostItem; + latestPost: boolean; + latestPostLarge: boolean; +}) { + const renderAvatar = ( + + ); + + const renderTitle = ( + + {post.title} + + ); + + const renderInfo = ( + + {[ + { number: post.totalComments, icon: 'solar:chat-round-dots-bold' }, + { number: post.totalViews, icon: 'solar:eye-bold' }, + { number: post.totalShares, icon: 'solar:share-bold' }, + ].map((info, _index) => ( + + + {fShortenNumber(info.number)} + + ))} + + ); + + const renderCover = ( + + ); + + const renderDate = ( + + {fDate(post.postedAt)} + + ); + + const renderShape = ( + + ); + + return ( + + ({ + position: 'relative', + pt: 'calc(100% * 3 / 4)', + ...((latestPostLarge || latestPost) && { + pt: 'calc(100% * 4 / 3)', + '&:after': { + top: 0, + content: "''", + width: '100%', + height: '100%', + position: 'absolute', + bgcolor: varAlpha(theme.palette.grey['900Channel'], 0.72), + }, + }), + ...(latestPostLarge && { + pt: { + xs: 'calc(100% * 4 / 3)', + sm: 'calc(100% * 3 / 4.66)', + }, + }), + })} + > + {renderShape} + {renderAvatar} + {renderCover} + + + ({ + p: theme.spacing(6, 3, 3, 3), + ...((latestPostLarge || latestPost) && { + width: 1, + bottom: 0, + position: 'absolute', + }), + })} + > + {renderDate} + {renderTitle} + {renderInfo} + + + ); +} diff --git a/frontend/src/sections/blog/post-search.tsx b/frontend/src/sections/blog/post-search.tsx new file mode 100644 index 000000000..828a0b87f --- /dev/null +++ b/frontend/src/sections/blog/post-search.tsx @@ -0,0 +1,59 @@ +import type { Theme, SxProps } from '@mui/material/styles'; + +import TextField from '@mui/material/TextField'; +import InputAdornment from '@mui/material/InputAdornment'; +import Autocomplete, { autocompleteClasses } from '@mui/material/Autocomplete'; + +import { Iconify } from 'src/components/iconify'; + +import type { IPostItem } from './post-item'; + +// ---------------------------------------------------------------------- + +type PostSearchProps = { + posts: IPostItem[]; + sx?: SxProps; +}; + +export function PostSearch({ posts, sx }: PostSearchProps) { + return ( + post.title} + isOptionEqualToValue={(option, value) => option.id === value.id} + renderInput={(params) => ( + + + + ), + }, + }} + /> + )} + /> + ); +} diff --git a/frontend/src/sections/blog/post-sort.tsx b/frontend/src/sections/blog/post-sort.tsx new file mode 100644 index 000000000..9b1c1558c --- /dev/null +++ b/frontend/src/sections/blog/post-sort.tsx @@ -0,0 +1,96 @@ +import type { ButtonProps } from '@mui/material/Button'; + +import { useState, useCallback } from 'react'; +import { varAlpha } from 'minimal-shared/utils'; + +import Button from '@mui/material/Button'; +import Popover from '@mui/material/Popover'; +import MenuList from '@mui/material/MenuList'; +import MenuItem, { menuItemClasses } from '@mui/material/MenuItem'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +type PostSortProps = ButtonProps & { + sortBy: string; + onSort: (newSort: string) => void; + options: { value: string; label: string }[]; +}; + +export function PostSort({ options, sortBy, onSort, sx, ...other }: PostSortProps) { + const [openPopover, setOpenPopover] = useState(null); + + const handleOpenPopover = useCallback((event: React.MouseEvent) => { + setOpenPopover(event.currentTarget); + }, []); + + const handleClosePopover = useCallback(() => { + setOpenPopover(null); + }, []); + + return ( + <> + + + + + {options.map((option) => ( + { + onSort(option.value); + handleClosePopover(); + }} + > + {option.label} + + ))} + + + + ); +} diff --git a/frontend/src/sections/blog/view/blog-view.tsx b/frontend/src/sections/blog/view/blog-view.tsx new file mode 100644 index 000000000..37d7ea98d --- /dev/null +++ b/frontend/src/sections/blog/view/blog-view.tsx @@ -0,0 +1,96 @@ +import { useState, useCallback } from 'react'; + +import Box from '@mui/material/Box'; +import Grid from '@mui/material/Grid'; +import Button from '@mui/material/Button'; +import Typography from '@mui/material/Typography'; +import Pagination from '@mui/material/Pagination'; + +import { DashboardContent } from 'src/layouts/dashboard'; + +import { Iconify } from 'src/components/iconify'; + +import { PostItem } from '../post-item'; +import { PostSort } from '../post-sort'; +import { PostSearch } from '../post-search'; + +import type { IPostItem } from '../post-item'; + +// ---------------------------------------------------------------------- + +type Props = { + posts: IPostItem[]; +}; + +export function BlogView({ posts }: Props) { + const [sortBy, setSortBy] = useState('latest'); + + const handleSort = useCallback((newSort: string) => { + setSortBy(newSort); + }, []); + + return ( + + + + Blog + + + + + + + + + + + {posts.map((post, index) => { + const latestPostLarge = index === 0; + const latestPost = index === 1 || index === 2; + + return ( + + + + ); + })} + + + + + ); +} diff --git a/frontend/src/sections/blog/view/index.ts b/frontend/src/sections/blog/view/index.ts new file mode 100644 index 000000000..f7cb1c6ad --- /dev/null +++ b/frontend/src/sections/blog/view/index.ts @@ -0,0 +1 @@ +export * from './blog-view'; diff --git a/frontend/src/sections/error/index.ts b/frontend/src/sections/error/index.ts new file mode 100644 index 000000000..f64297290 --- /dev/null +++ b/frontend/src/sections/error/index.ts @@ -0,0 +1 @@ +export * from './not-found-view'; diff --git a/frontend/src/sections/error/not-found-view.tsx b/frontend/src/sections/error/not-found-view.tsx new file mode 100644 index 000000000..34e5d8b82 --- /dev/null +++ b/frontend/src/sections/error/not-found-view.tsx @@ -0,0 +1,52 @@ +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import Container from '@mui/material/Container'; +import Typography from '@mui/material/Typography'; + +import { RouterLink } from 'src/routes/components'; + +import { Logo } from 'src/components/logo'; + +// ---------------------------------------------------------------------- + +export function NotFoundView() { + return ( + <> + + + + + Sorry, page not found! + + + + Sorry, we couldn’t find the page you’re looking for. Perhaps you’ve mistyped the URL? Be + sure to check your spelling. + + + + + + + + ); +} diff --git a/frontend/src/sections/overview/analytics-conversion-rates.tsx b/frontend/src/sections/overview/analytics-conversion-rates.tsx new file mode 100644 index 000000000..7b8e7375e --- /dev/null +++ b/frontend/src/sections/overview/analytics-conversion-rates.tsx @@ -0,0 +1,82 @@ +import type { CardProps } from '@mui/material/Card'; +import type { ChartOptions } from 'src/components/chart'; + +import Card from '@mui/material/Card'; +import CardHeader from '@mui/material/CardHeader'; +import { useTheme, alpha as hexAlpha } from '@mui/material/styles'; + +import { fNumber } from 'src/utils/format-number'; + +import { Chart, useChart } from 'src/components/chart'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title?: string; + subheader?: string; + chart: { + colors?: string[]; + categories?: string[]; + series: { + name: string; + data: number[]; + }[]; + options?: ChartOptions; + }; +}; + +export function AnalyticsConversionRates({ title, subheader, chart, sx, ...other }: Props) { + const theme = useTheme(); + + const chartColors = chart.colors ?? [ + theme.palette.primary.dark, + hexAlpha(theme.palette.primary.dark, 0.24), + ]; + + const chartOptions = useChart({ + colors: chartColors, + stroke: { width: 2, colors: ['transparent'] }, + tooltip: { + shared: true, + intersect: false, + y: { + formatter: (value: number) => fNumber(value), + title: { formatter: (seriesName: string) => `${seriesName}: ` }, + }, + }, + xaxis: { categories: chart.categories }, + dataLabels: { + enabled: true, + offsetX: -6, + style: { fontSize: '10px', colors: ['#FFFFFF', theme.palette.text.primary] }, + }, + plotOptions: { + bar: { + horizontal: true, + borderRadius: 2, + barHeight: '48%', + dataLabels: { position: 'top' }, + }, + }, + ...chart.options, + }); + + return ( + + + + + + ); +} diff --git a/frontend/src/sections/overview/analytics-current-subject.tsx b/frontend/src/sections/overview/analytics-current-subject.tsx new file mode 100644 index 000000000..87dc34487 --- /dev/null +++ b/frontend/src/sections/overview/analytics-current-subject.tsx @@ -0,0 +1,73 @@ +import type { CardProps } from '@mui/material/Card'; +import type { ChartOptions } from 'src/components/chart'; + +import Card from '@mui/material/Card'; +import Divider from '@mui/material/Divider'; +import { useTheme } from '@mui/material/styles'; +import CardHeader from '@mui/material/CardHeader'; + +import { Chart, useChart, ChartLegends } from 'src/components/chart'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title?: string; + subheader?: string; + chart: { + colors?: string[]; + categories: string[]; + series: { + name: string; + data: number[]; + }[]; + options?: ChartOptions; + }; +}; + +export function AnalyticsCurrentSubject({ title, subheader, chart, sx, ...other }: Props) { + const theme = useTheme(); + + const chartColors = chart.colors ?? [ + theme.palette.primary.main, + theme.palette.warning.main, + theme.palette.info.main, + ]; + + const chartOptions = useChart({ + colors: chartColors, + stroke: { width: 2 }, + fill: { opacity: 0.48 }, + xaxis: { + categories: chart.categories, + labels: { style: { colors: Array.from({ length: 6 }, () => theme.palette.text.secondary) } }, + }, + ...chart.options, + }); + + return ( + + + + + + + + item.name)} + colors={chartOptions?.colors} + sx={{ p: 3, justifyContent: 'center' }} + /> + + ); +} diff --git a/frontend/src/sections/overview/analytics-current-visits.tsx b/frontend/src/sections/overview/analytics-current-visits.tsx new file mode 100644 index 000000000..c6077964c --- /dev/null +++ b/frontend/src/sections/overview/analytics-current-visits.tsx @@ -0,0 +1,81 @@ +import type { CardProps } from '@mui/material/Card'; +import type { ChartOptions } from 'src/components/chart'; + +import Card from '@mui/material/Card'; +import Divider from '@mui/material/Divider'; +import { useTheme } from '@mui/material/styles'; +import CardHeader from '@mui/material/CardHeader'; + +import { fNumber } from 'src/utils/format-number'; + +import { Chart, useChart, ChartLegends } from 'src/components/chart'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title?: string; + subheader?: string; + chart: { + colors?: string[]; + series: { + label: string; + value: number; + }[]; + options?: ChartOptions; + }; +}; + +export function AnalyticsCurrentVisits({ title, subheader, chart, sx, ...other }: Props) { + const theme = useTheme(); + + const chartSeries = chart.series.map((item) => item.value); + + const chartColors = chart.colors ?? [ + theme.palette.primary.main, + theme.palette.warning.light, + theme.palette.info.dark, + theme.palette.error.main, + ]; + + const chartOptions = useChart({ + chart: { sparkline: { enabled: true } }, + colors: chartColors, + labels: chart.series.map((item) => item.label), + stroke: { width: 0 }, + dataLabels: { enabled: true, dropShadow: { enabled: false } }, + tooltip: { + y: { + formatter: (value: number) => fNumber(value), + title: { formatter: (seriesName: string) => `${seriesName}` }, + }, + }, + plotOptions: { pie: { donut: { labels: { show: false } } } }, + ...chart.options, + }); + + return ( + + + + + + + + + + ); +} diff --git a/frontend/src/sections/overview/analytics-news.tsx b/frontend/src/sections/overview/analytics-news.tsx new file mode 100644 index 000000000..3b377a908 --- /dev/null +++ b/frontend/src/sections/overview/analytics-news.tsx @@ -0,0 +1,103 @@ +import type { BoxProps } from '@mui/material/Box'; +import type { CardProps } from '@mui/material/Card'; + +import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; +import Card from '@mui/material/Card'; +import Button from '@mui/material/Button'; +import Avatar from '@mui/material/Avatar'; +import CardHeader from '@mui/material/CardHeader'; +import ListItemText from '@mui/material/ListItemText'; + +import { fToNow } from 'src/utils/format-time'; + +import { Iconify } from 'src/components/iconify'; +import { Scrollbar } from 'src/components/scrollbar'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title?: string; + subheader?: string; + list: { + id: string; + title: string; + coverUrl: string; + description: string; + postedAt: string | number | null; + }[]; +}; + +export function AnalyticsNews({ title, subheader, list, sx, ...other }: Props) { + return ( + + + + + + {list.map((item) => ( + + ))} + + + + + + + + ); +} + +// ---------------------------------------------------------------------- + +type ItemProps = BoxProps & { + item: Props['list'][number]; +}; + +function Item({ item, sx, ...other }: ItemProps) { + return ( + ({ + py: 2, + px: 3, + gap: 2, + display: 'flex', + alignItems: 'center', + borderBottom: `dashed 1px ${theme.vars.palette.divider}`, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + + + {item.title}} + secondary={item.description} + slotProps={{ + primary: { noWrap: true }, + secondary: { + noWrap: true, + sx: { mt: 0.5 }, + }, + }} + /> + + + {fToNow(item.postedAt)} + + + ); +} diff --git a/frontend/src/sections/overview/analytics-order-timeline.tsx b/frontend/src/sections/overview/analytics-order-timeline.tsx new file mode 100644 index 000000000..9abb88a13 --- /dev/null +++ b/frontend/src/sections/overview/analytics-order-timeline.tsx @@ -0,0 +1,77 @@ +import type { CardProps } from '@mui/material/Card'; +import type { TimelineItemProps } from '@mui/lab/TimelineItem'; + +import Card from '@mui/material/Card'; +import Timeline from '@mui/lab/Timeline'; +import TimelineDot from '@mui/lab/TimelineDot'; +import Typography from '@mui/material/Typography'; +import CardHeader from '@mui/material/CardHeader'; +import TimelineContent from '@mui/lab/TimelineContent'; +import TimelineSeparator from '@mui/lab/TimelineSeparator'; +import TimelineConnector from '@mui/lab/TimelineConnector'; +import TimelineItem, { timelineItemClasses } from '@mui/lab/TimelineItem'; + +import { fDateTime } from 'src/utils/format-time'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title?: string; + subheader?: string; + list: { + id: string; + type: string; + title: string; + time: string | number | null; + }[]; +}; + +export function AnalyticsOrderTimeline({ title, subheader, list, sx, ...other }: Props) { + return ( + + + + + {list.map((item, index) => ( + + ))} + + + ); +} + +// ---------------------------------------------------------------------- + +type ItemProps = TimelineItemProps & { + lastItem: boolean; + item: Props['list'][number]; +}; + +function Item({ item, lastItem, ...other }: ItemProps) { + return ( + + + + {lastItem ? null : } + + + + {item.title} + + + {fDateTime(item.time)} + + + + ); +} diff --git a/frontend/src/sections/overview/analytics-tasks.tsx b/frontend/src/sections/overview/analytics-tasks.tsx new file mode 100644 index 000000000..5accf38c1 --- /dev/null +++ b/frontend/src/sections/overview/analytics-tasks.tsx @@ -0,0 +1,179 @@ +import type { BoxProps } from '@mui/material/Box'; +import type { CardProps } from '@mui/material/Card'; + +import { useState } from 'react'; +import { usePopover } from 'minimal-shared/hooks'; + +import Box from '@mui/material/Box'; +import Card from '@mui/material/Card'; +import Stack from '@mui/material/Stack'; +import Popover from '@mui/material/Popover'; +import Divider from '@mui/material/Divider'; +import MenuList from '@mui/material/MenuList'; +import Checkbox from '@mui/material/Checkbox'; +import IconButton from '@mui/material/IconButton'; +import CardHeader from '@mui/material/CardHeader'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import MenuItem, { menuItemClasses } from '@mui/material/MenuItem'; + +import { Iconify } from 'src/components/iconify'; +import { Scrollbar } from 'src/components/scrollbar'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title?: string; + subheader?: string; + list: { + id: string; + name: string; + }[]; +}; + +export function AnalyticsTasks({ title, subheader, list, sx, ...other }: Props) { + const [selected, setSelected] = useState(['2']); + + const handleClickComplete = (taskId: string) => { + const tasksCompleted = selected.includes(taskId) + ? selected.filter((value) => value !== taskId) + : [...selected, taskId]; + + setSelected(tasksCompleted); + }; + + return ( + + + + + } sx={{ minWidth: 560 }}> + {list.map((item) => ( + handleClickComplete(item.id)} + /> + ))} + + + + ); +} + +// ---------------------------------------------------------------------- + +type TaskItemProps = BoxProps & { + selected: boolean; + item: Props['list'][number]; + onChange: (id: string) => void; +}; + +function TaskItem({ item, selected, onChange, sx, ...other }: TaskItemProps) { + const menuActions = usePopover(); + + const handleMarkComplete = () => { + menuActions.onClose(); + console.info('MARK COMPLETE', item.id); + }; + + const handleShare = () => { + menuActions.onClose(); + console.info('SHARE', item.id); + }; + + const handleEdit = () => { + menuActions.onClose(); + console.info('EDIT', item.id); + }; + + const handleDelete = () => { + menuActions.onClose(); + console.info('DELETE', item.id); + }; + + return ( + <> + ({ + pl: 2, + pr: 1, + py: 1.5, + display: 'flex', + ...(selected && { + color: 'text.disabled', + textDecoration: 'line-through', + }), + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + + } + sx={{ flexGrow: 1, m: 0 }} + /> + + + + + + + + + + + Mark complete + + + + + Edit + + + + + Share + + + + + + + Delete + + + + + ); +} diff --git a/frontend/src/sections/overview/analytics-traffic-by-site.tsx b/frontend/src/sections/overview/analytics-traffic-by-site.tsx new file mode 100644 index 000000000..607b292fc --- /dev/null +++ b/frontend/src/sections/overview/analytics-traffic-by-site.tsx @@ -0,0 +1,64 @@ +import type { CardProps } from '@mui/material/Card'; + +import { varAlpha } from 'minimal-shared/utils'; + +import Box from '@mui/material/Box'; +import Card from '@mui/material/Card'; +import CardHeader from '@mui/material/CardHeader'; +import Typography from '@mui/material/Typography'; + +import { fShortenNumber } from 'src/utils/format-number'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title?: string; + subheader?: string; + list: { value: string; label: string; total: number }[]; +}; + +export function AnalyticsTrafficBySite({ title, subheader, list, sx, ...other }: Props) { + return ( + + + + {list.map((site) => ( + ({ + py: 2.5, + display: 'flex', + borderRadius: 1.5, + textAlign: 'center', + alignItems: 'center', + flexDirection: 'column', + border: `solid 1px ${varAlpha(theme.vars.palette.grey['500Channel'], 0.12)}`, + })} + > + {site.value === 'twitter' && } + {site.value === 'facebook' && } + {site.value === 'google' && } + {site.value === 'linkedin' && } + + + {fShortenNumber(site.total)} + + + + {site.label} + + + ))} + + + ); +} diff --git a/frontend/src/sections/overview/analytics-website-visits.tsx b/frontend/src/sections/overview/analytics-website-visits.tsx new file mode 100644 index 000000000..b6ea5ee03 --- /dev/null +++ b/frontend/src/sections/overview/analytics-website-visits.tsx @@ -0,0 +1,61 @@ +import type { CardProps } from '@mui/material/Card'; +import type { ChartOptions } from 'src/components/chart'; + +import Card from '@mui/material/Card'; +import CardHeader from '@mui/material/CardHeader'; +import { useTheme, alpha as hexAlpha } from '@mui/material/styles'; + +import { Chart, useChart } from 'src/components/chart'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title?: string; + subheader?: string; + chart: { + colors?: string[]; + categories?: string[]; + series: { + name: string; + data: number[]; + }[]; + options?: ChartOptions; + }; +}; + +export function AnalyticsWebsiteVisits({ title, subheader, chart, sx, ...other }: Props) { + const theme = useTheme(); + + const chartColors = chart.colors ?? [ + hexAlpha(theme.palette.primary.dark, 0.8), + hexAlpha(theme.palette.warning.main, 0.8), + ]; + + const chartOptions = useChart({ + colors: chartColors, + stroke: { width: 2, colors: ['transparent'] }, + xaxis: { categories: chart.categories }, + legend: { show: true }, + tooltip: { y: { formatter: (value: number) => `${value} visits` } }, + ...chart.options, + }); + + return ( + + + + + + ); +} diff --git a/frontend/src/sections/overview/analytics-widget-summary.tsx b/frontend/src/sections/overview/analytics-widget-summary.tsx new file mode 100644 index 000000000..efecd09cf --- /dev/null +++ b/frontend/src/sections/overview/analytics-widget-summary.tsx @@ -0,0 +1,142 @@ +import type { CardProps } from '@mui/material/Card'; +import type { PaletteColorKey } from 'src/theme/core'; +import type { ChartOptions } from 'src/components/chart'; + +import { varAlpha } from 'minimal-shared/utils'; + +import Box from '@mui/material/Box'; +import Card from '@mui/material/Card'; +import { useTheme } from '@mui/material/styles'; + +import { fNumber, fPercent, fShortenNumber } from 'src/utils/format-number'; + +import { Iconify } from 'src/components/iconify'; +import { SvgColor } from 'src/components/svg-color'; +import { Chart, useChart } from 'src/components/chart'; + +// ---------------------------------------------------------------------- + +type Props = CardProps & { + title: string; + total: number; + percent: number; + color?: PaletteColorKey; + icon: React.ReactNode; + chart: { + series: number[]; + categories: string[]; + options?: ChartOptions; + }; +}; + +export function AnalyticsWidgetSummary({ + sx, + icon, + title, + total, + chart, + percent, + color = 'primary', + ...other +}: Props) { + const theme = useTheme(); + + const chartColors = [theme.palette[color].dark]; + + const chartOptions = useChart({ + chart: { sparkline: { enabled: true } }, + colors: chartColors, + xaxis: { categories: chart.categories }, + grid: { + padding: { + top: 6, + left: 6, + right: 6, + bottom: 6, + }, + }, + tooltip: { + y: { formatter: (value: number) => fNumber(value), title: { formatter: () => '' } }, + }, + markers: { + strokeWidth: 0, + }, + ...chart.options, + }); + + const renderTrending = () => ( + + + + {percent > 0 && '+'} + {fPercent(percent)} + + + ); + + return ( + ({ + p: 3, + boxShadow: 'none', + position: 'relative', + color: `${color}.darker`, + backgroundColor: 'common.white', + backgroundImage: `linear-gradient(135deg, ${varAlpha(theme.vars.palette[color].lighterChannel, 0.48)}, ${varAlpha(theme.vars.palette[color].lightChannel, 0.48)})`, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + {icon} + + {renderTrending()} + + + + {title} + + {fShortenNumber(total)} + + + + + + + + ); +} diff --git a/frontend/src/sections/overview/view/index.ts b/frontend/src/sections/overview/view/index.ts new file mode 100644 index 000000000..fb212b45f --- /dev/null +++ b/frontend/src/sections/overview/view/index.ts @@ -0,0 +1 @@ +export * from './overview-analytics-view'; diff --git a/frontend/src/sections/overview/view/overview-analytics-view.tsx b/frontend/src/sections/overview/view/overview-analytics-view.tsx new file mode 100644 index 000000000..a98ca5bef --- /dev/null +++ b/frontend/src/sections/overview/view/overview-analytics-view.tsx @@ -0,0 +1,156 @@ +import Grid from '@mui/material/Grid'; +import Typography from '@mui/material/Typography'; + +import { DashboardContent } from 'src/layouts/dashboard'; +import { _posts, _tasks, _traffic, _timeline } from 'src/_mock'; + +import { AnalyticsNews } from '../analytics-news'; +import { AnalyticsTasks } from '../analytics-tasks'; +import { AnalyticsCurrentVisits } from '../analytics-current-visits'; +import { AnalyticsOrderTimeline } from '../analytics-order-timeline'; +import { AnalyticsWebsiteVisits } from '../analytics-website-visits'; +import { AnalyticsWidgetSummary } from '../analytics-widget-summary'; +import { AnalyticsTrafficBySite } from '../analytics-traffic-by-site'; +import { AnalyticsCurrentSubject } from '../analytics-current-subject'; +import { AnalyticsConversionRates } from '../analytics-conversion-rates'; + +// ---------------------------------------------------------------------- + +export function OverviewAnalyticsView() { + return ( + + + Hi, Welcome back 👋 + + + + + } + chart={{ + categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'], + series: [22, 8, 35, 50, 82, 84, 77, 12], + }} + /> + + + + } + chart={{ + categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'], + series: [56, 47, 40, 62, 73, 30, 23, 54], + }} + /> + + + + } + chart={{ + categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'], + series: [40, 70, 50, 28, 70, 75, 7, 64], + }} + /> + + + + } + chart={{ + categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'], + series: [56, 30, 23, 54, 47, 40, 62, 73], + }} + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/frontend/src/sections/product/product-cart-widget.tsx b/frontend/src/sections/product/product-cart-widget.tsx new file mode 100644 index 000000000..30840609d --- /dev/null +++ b/frontend/src/sections/product/product-cart-widget.tsx @@ -0,0 +1,47 @@ +import type { BoxProps } from '@mui/material/Box'; + +import Box from '@mui/material/Box'; +import Badge from '@mui/material/Badge'; + +import { RouterLink } from 'src/routes/components'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +type CartIconProps = BoxProps & { + totalItems: number; +}; + +export function CartIcon({ totalItems, sx, ...other }: CartIconProps) { + return ( + ({ + right: 0, + top: 112, + zIndex: 999, + display: 'flex', + cursor: 'pointer', + position: 'fixed', + color: 'text.primary', + borderTopLeftRadius: 16, + borderBottomLeftRadius: 16, + bgcolor: 'background.paper', + padding: theme.spacing(1, 3, 1, 2), + boxShadow: theme.vars.customShadows.dropdown, + transition: theme.transitions.create(['opacity']), + '&:hover': { opacity: 0.72 }, + }), + ...(Array.isArray(sx) ? sx : [sx]), + ]} + {...other} + > + + + + + ); +} diff --git a/frontend/src/sections/product/product-filters.tsx b/frontend/src/sections/product/product-filters.tsx new file mode 100644 index 000000000..3777a98c1 --- /dev/null +++ b/frontend/src/sections/product/product-filters.tsx @@ -0,0 +1,232 @@ +import Box from '@mui/material/Box'; +import Stack from '@mui/material/Stack'; +import Radio from '@mui/material/Radio'; +import Badge from '@mui/material/Badge'; +import Button from '@mui/material/Button'; +import Drawer from '@mui/material/Drawer'; +import Rating from '@mui/material/Rating'; +import Divider from '@mui/material/Divider'; +import Checkbox from '@mui/material/Checkbox'; +import FormGroup from '@mui/material/FormGroup'; +import RadioGroup from '@mui/material/RadioGroup'; +import Typography from '@mui/material/Typography'; +import IconButton from '@mui/material/IconButton'; +import FormControlLabel from '@mui/material/FormControlLabel'; + +import { Iconify } from 'src/components/iconify'; +import { Scrollbar } from 'src/components/scrollbar'; +import { ColorPicker } from 'src/components/color-utils'; + +// ---------------------------------------------------------------------- + +export type FiltersProps = { + price: string; + rating: string; + gender: string[]; + colors: string[]; + category: string; +}; + +type ProductFiltersProps = { + canReset: boolean; + openFilter: boolean; + filters: FiltersProps; + onOpenFilter: () => void; + onCloseFilter: () => void; + onResetFilter: () => void; + onSetFilters: (updateState: Partial) => void; + options: { + colors: string[]; + ratings: string[]; + categories: { value: string; label: string }[]; + genders: { value: string; label: string }[]; + price: { value: string; label: string }[]; + }; +}; + +export function ProductFilters({ + filters, + options, + canReset, + openFilter, + onSetFilters, + onOpenFilter, + onCloseFilter, + onResetFilter, +}: ProductFiltersProps) { + const renderGender = ( + + Gender + + {options.genders.map((option) => ( + { + const checked = filters.gender.includes(option.value) + ? filters.gender.filter((value) => value !== option.value) + : [...filters.gender, option.value]; + + onSetFilters({ gender: checked }); + }} + /> + } + label={option.label} + /> + ))} + + + ); + + const renderCategory = ( + + Category + + {options.categories.map((option) => ( + onSetFilters({ category: option.value })} + /> + } + label={option.label} + /> + ))} + + + ); + + const renderColors = ( + + Colors + onSetFilters({ colors: colors as string[] })} + limit={6} + /> + + ); + + const renderPrice = ( + + Price + + {options.price.map((option) => ( + onSetFilters({ price: option.value })} + /> + } + label={option.label} + /> + ))} + + + ); + + const renderRating = ( + + + Rating + + + {options.ratings.map((option, index) => ( + onSetFilters({ rating: option })} + sx={{ + mb: 1, + gap: 1, + ml: -1, + p: 0.5, + display: 'flex', + borderRadius: 1, + cursor: 'pointer', + typography: 'body2', + alignItems: 'center', + '&:hover': { opacity: 0.48 }, + ...(filters.rating === option && { + bgcolor: 'action.selected', + }), + }} + > + & Up + + ))} + + ); + + return ( + <> + + + + + + Filters + + + + + + + + + + + + + + + + + + {renderGender} + {renderCategory} + {renderColors} + {renderPrice} + {renderRating} + + + + + ); +} diff --git a/frontend/src/sections/product/product-item.tsx b/frontend/src/sections/product/product-item.tsx new file mode 100644 index 000000000..722d3409b --- /dev/null +++ b/frontend/src/sections/product/product-item.tsx @@ -0,0 +1,98 @@ +import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; +import Card from '@mui/material/Card'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; + +import { fCurrency } from 'src/utils/format-number'; + +import { Label } from 'src/components/label'; +import { ColorPreview } from 'src/components/color-utils'; + +// ---------------------------------------------------------------------- + +export type ProductItemProps = { + id: string; + name: string; + price: number; + status: string; + coverUrl: string; + colors: string[]; + priceSale: number | null; +}; + +export function ProductItem({ product }: { product: ProductItemProps }) { + const renderStatus = ( + + ); + + const renderImg = ( + + ); + + const renderPrice = ( + + + {product.priceSale && fCurrency(product.priceSale)} + +   + {fCurrency(product.price)} + + ); + + return ( + + + {product.status && renderStatus} + {renderImg} + + + + + {product.name} + + + + + {renderPrice} + + + + ); +} diff --git a/frontend/src/sections/product/product-sort.tsx b/frontend/src/sections/product/product-sort.tsx new file mode 100644 index 000000000..6fcade45f --- /dev/null +++ b/frontend/src/sections/product/product-sort.tsx @@ -0,0 +1,91 @@ +import type { ButtonProps } from '@mui/material/Button'; + +import { useState, useCallback } from 'react'; + +import Button from '@mui/material/Button'; +import Popover from '@mui/material/Popover'; +import MenuList from '@mui/material/MenuList'; +import Typography from '@mui/material/Typography'; +import MenuItem, { menuItemClasses } from '@mui/material/MenuItem'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +type ProductSortProps = ButtonProps & { + sortBy: string; + onSort: (newSort: string) => void; + options: { value: string; label: string }[]; +}; + +export function ProductSort({ options, sortBy, onSort, sx, ...other }: ProductSortProps) { + const [openPopover, setOpenPopover] = useState(null); + + const handleOpenPopover = useCallback((event: React.MouseEvent) => { + setOpenPopover(event.currentTarget); + }, []); + + const handleClosePopover = useCallback(() => { + setOpenPopover(null); + }, []); + + return ( + <> + + + + + {options.map((option) => ( + { + onSort(option.value); + handleClosePopover(); + }} + > + {option.label} + + ))} + + + + ); +} diff --git a/frontend/src/sections/product/view/index.ts b/frontend/src/sections/product/view/index.ts new file mode 100644 index 000000000..6a59b368d --- /dev/null +++ b/frontend/src/sections/product/view/index.ts @@ -0,0 +1 @@ +export * from './products-view'; diff --git a/frontend/src/sections/product/view/products-view.tsx b/frontend/src/sections/product/view/products-view.tsx new file mode 100644 index 000000000..8b4291023 --- /dev/null +++ b/frontend/src/sections/product/view/products-view.tsx @@ -0,0 +1,152 @@ +import { useState, useCallback } from 'react'; + +import Box from '@mui/material/Box'; +import Grid from '@mui/material/Grid'; +import Pagination from '@mui/material/Pagination'; +import Typography from '@mui/material/Typography'; + +import { _products } from 'src/_mock'; +import { DashboardContent } from 'src/layouts/dashboard'; + +import { ProductItem } from '../product-item'; +import { ProductSort } from '../product-sort'; +import { CartIcon } from '../product-cart-widget'; +import { ProductFilters } from '../product-filters'; + +import type { FiltersProps } from '../product-filters'; + +// ---------------------------------------------------------------------- + +const GENDER_OPTIONS = [ + { value: 'men', label: 'Men' }, + { value: 'women', label: 'Women' }, + { value: 'kids', label: 'Kids' }, +]; + +const CATEGORY_OPTIONS = [ + { value: 'all', label: 'All' }, + { value: 'shose', label: 'Shose' }, + { value: 'apparel', label: 'Apparel' }, + { value: 'accessories', label: 'Accessories' }, +]; + +const RATING_OPTIONS = ['up4Star', 'up3Star', 'up2Star', 'up1Star']; + +const PRICE_OPTIONS = [ + { value: 'below', label: 'Below $25' }, + { value: 'between', label: 'Between $25 - $75' }, + { value: 'above', label: 'Above $75' }, +]; + +const COLOR_OPTIONS = [ + '#00AB55', + '#000000', + '#FFFFFF', + '#FFC0CB', + '#FF4842', + '#1890FF', + '#94D82D', + '#FFC107', +]; + +const defaultFilters = { + price: '', + gender: [GENDER_OPTIONS[0].value], + colors: [COLOR_OPTIONS[4]], + rating: RATING_OPTIONS[0], + category: CATEGORY_OPTIONS[0].value, +}; + +export function ProductsView() { + const [sortBy, setSortBy] = useState('featured'); + + const [openFilter, setOpenFilter] = useState(false); + + const [filters, setFilters] = useState(defaultFilters); + + const handleOpenFilter = useCallback(() => { + setOpenFilter(true); + }, []); + + const handleCloseFilter = useCallback(() => { + setOpenFilter(false); + }, []); + + const handleSort = useCallback((newSort: string) => { + setSortBy(newSort); + }, []); + + const handleSetFilters = useCallback((updateState: Partial) => { + setFilters((prevValue) => ({ ...prevValue, ...updateState })); + }, []); + + const canReset = Object.keys(filters).some( + (key) => filters[key as keyof FiltersProps] !== defaultFilters[key as keyof FiltersProps] + ); + + return ( + + + + + Products + + + + setFilters(defaultFilters)} + options={{ + genders: GENDER_OPTIONS, + categories: CATEGORY_OPTIONS, + ratings: RATING_OPTIONS, + price: PRICE_OPTIONS, + colors: COLOR_OPTIONS, + }} + /> + + + + + + + {_products.map((product) => ( + + + + ))} + + + + + ); +} diff --git a/frontend/src/sections/user/booking-details/index.tsx b/frontend/src/sections/user/booking-details/index.tsx new file mode 100644 index 000000000..96e6ef9fa --- /dev/null +++ b/frontend/src/sections/user/booking-details/index.tsx @@ -0,0 +1,450 @@ +import type { BookingStatus } from 'src/api/types/venue.type'; + +import dayjs from 'dayjs'; +import { useState } from 'react'; +import { Link, useParams, useNavigate } from 'react-router-dom'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; + +import { + Box, + Chip, + Grid, + Paper, + Stack, + Alert, + Button, + Dialog, + Divider, + Skeleton, + Container, + Typography, + DialogTitle, + Breadcrumbs, + DialogActions, + DialogContent, + CircularProgress, +} from '@mui/material'; + +import { PaymentStatus } from 'src/api/types/payment.type'; +import { UserBookingApiService } from 'src/api/user-booking'; + +import { Iconify } from 'src/components/iconify'; + +const STATUS_CONFIG: Record = { + BOOKED: { label: 'Booked', color: 'success', icon: 'mdi:check-circle-outline', bg: '#F0FDF4', text: '#16A34A' }, + CANCELLED: { label: 'Cancelled', color: 'error', icon: 'mdi:close-circle-outline', bg: '#FEF2F2', text: '#DC2626' }, +}; + +function InfoRow({ label, value, icon }: { label: string; value: string; icon?: string }) { + return ( + + + {icon && } + {label} + + {value} + + ); +} + +function BookingDetailsSkeleton() { + return ( + + + + + + + + + + + + + ); +} + +export function BookingDetailsView() { + const navigate = useNavigate(); + const queryClient = useQueryClient(); + const { bookingId } = useParams<{ bookingId: string }>(); + const [cancelDialog, setCancelDialog] = useState(false); + + const { data: booking, isLoading, isError } = useQuery({ + queryKey: ['booking-details', bookingId], + queryFn: () => UserBookingApiService.getBookingDetails(bookingId!), + enabled: !!bookingId, + retry: 1, + }); + + const cancelMutation = useMutation({ + mutationFn: () => UserBookingApiService.cancelBooking(bookingId!), + onSuccess: () => { + setCancelDialog(false); + queryClient.invalidateQueries({ queryKey: ['booking-details', bookingId] }); + queryClient.invalidateQueries({ queryKey: ['my-bookings'] }); + }, + }); + + if (isLoading) return ; + + if (isError || !booking) { + return ( + + + Booking Not Found + + This booking may not exist or you don't have access to it. + + + + ); + } + + const statusCfg = STATUS_CONFIG[booking.status] ?? STATUS_CONFIG.BOOKED; + const bookingRef = (booking.bookingId ?? booking.id ?? '').slice(-8).toUpperCase(); + const nights = Math.max(1, dayjs(booking.endDate).diff(dayjs(booking.startDate), 'day')); + const baseAmount = booking.totalAmount ? Math.round(booking.totalAmount / 1.1) : 0; + const serviceFee = booking.totalAmount ? booking.totalAmount - baseAmount : 0; + const canCancel = booking.status === 'BOOKED'; + const paymentStatus = booking.paymentStatus ?? PaymentStatus.PENDING; + const showPayButton = + booking.status === 'BOOKED' + && paymentStatus !== PaymentStatus.PAID + && paymentStatus !== PaymentStatus.REFUNDED; + const venueId = booking.venue?.id ?? booking.venueId; + + return ( + + {/* Header Banner */} + + + } + sx={{ mb: 2 }} + > + navigate('/my/bookings')} + sx={{ cursor: 'pointer', '&:hover': { color: 'white' } }} + > + My Bookings + + + Booking #{bookingRef} + + + + + + + Booking Details + + + {booking.venue?.title || booking.venueName} + + + } + label={statusCfg.label} + sx={{ + bgcolor: statusCfg.bg, + color: statusCfg.text, + fontWeight: 700, + fontSize: 13, + height: 36, + px: 1, + '& .MuiChip-icon': { color: statusCfg.text }, + }} + /> + + + + + + + {/* Left column */} + + + {/* Venue Card */} + + + + + {booking.venue?.title || booking.venueName} + + + + + {booking.venueCity}, {booking.venueState} + + + + + + + {/* Booking Info */} + + + Booking Information + + + + + + + + + + + + + + + + {booking.specialRequests && ( + <> + + + + + Special Requests + + + + {booking.specialRequests} + + + + + )} + + + {/* Cancellation Policy */} + {canCancel && ( + } + sx={{ borderRadius: 3 }} + > + Free cancellation available up to 48 hours before check-in. Cancellation fees may apply after that. + + )} + + + + {/* Right column */} + + + {/* Payment Summary */} + + + Payment Summary + + + + + + Base amount ({nights} day{nights !== 1 ? 's' : ''}) + + + â‚č{baseAmount.toLocaleString('en-IN')} + + + + Service fee (10%) + + â‚č{serviceFee.toLocaleString('en-IN')} + + + + + + {paymentStatus === PaymentStatus.PAID ? 'Total Paid' : 'Total Amount'} + + + â‚č{(booking.totalAmount ?? 0).toLocaleString('en-IN')} + + + + + + {/* Status Card */} + + + + + {statusCfg.label} + + + + {/* {booking.status === 'PENDING' && 'Your booking is awaiting confirmation from the venue host.'} */} + {booking.status === 'BOOKED' && 'Your booking is confirmed. Enjoy your event!'} + {booking.status === 'CANCELLED' && 'This booking has been cancelled.'} + {/* {booking.status === 'COMPLETED' && 'This booking has been completed. Thank you!'} */} + {/* {booking.status === 'REFUNDED' && 'A refund has been processed for this booking.'} */} + + + + {/* Actions */} + + {showPayButton && ( + + )} + + + + {canCancel && ( + + )} + + + + + + + {/* Cancel Confirmation Dialog */} + setCancelDialog(false)} + PaperProps={{ sx: { borderRadius: 4, p: 1 } }} + > + + + + Cancel Booking + + + + + Are you sure you want to cancel booking #{bookingRef}? + This action cannot be undone. Cancellation fees may apply. + + + + + + + + + ); +} diff --git a/frontend/src/sections/user/booking/index.tsx b/frontend/src/sections/user/booking/index.tsx new file mode 100644 index 000000000..1047624b1 --- /dev/null +++ b/frontend/src/sections/user/booking/index.tsx @@ -0,0 +1,497 @@ +import dayjs from 'dayjs'; +import { useState, useCallback } from 'react'; +import { useQuery, useMutation } from '@tanstack/react-query'; +import { useParams, useNavigate, useSearchParams } from 'react-router-dom'; + +import { + Box, + Grid, + Step, + Alert, + Paper, + Stack, + Button, + Rating, + Divider, + Stepper, + Skeleton, + Container, + StepLabel, + TextField, + Typography, + CircularProgress, +} from '@mui/material'; + +import { VenuePublicApiService } from 'src/api/venue-public'; +import { UserBookingApiService } from 'src/api/user-booking'; + +import { Iconify } from 'src/components/iconify'; + +const STEPS = ['Select Dates', 'Guest Details', 'Review & Pay']; + +export function BookingView() { + const navigate = useNavigate(); + const { venueId } = useParams<{ venueId: string }>(); + const [searchParams] = useSearchParams(); + + const [activeStep, setActiveStep] = useState(0); + const [startDate, setStartDate] = useState(searchParams.get('startDate') ?? ''); + const [endDate, setEndDate] = useState(searchParams.get('endDate') ?? ''); + const [guestsCount, setGuestsCount] = useState(Number(searchParams.get('guests') ?? 10)); + const [specialRequests, setSpecialRequests] = useState(''); + const [bookingSuccess, setBookingSuccess] = useState<{ id: string } | null>(null); + + const today = dayjs().format('YYYY-MM-DD'); + + const { data: venue, isLoading: venueLoading } = useQuery({ + queryKey: ['venue-details', venueId], + queryFn: () => VenuePublicApiService.getVenueDetails(venueId!), + enabled: !!venueId, + }); + + const nights = startDate && endDate ? Math.max(1, dayjs(endDate).diff(dayjs(startDate), 'day')) : 0; + const baseAmount = nights * (venue?.pricePerDay ?? 0); + const serviceFee = Math.round(baseAmount * 0.1); + const total = baseAmount + serviceFee; + + const createBookingMutation = useMutation({ + mutationFn: () => + UserBookingApiService.createBooking({ + venueId: venueId!, + startDate, + endDate, + guestsCount, + specialRequests: specialRequests || undefined, + }), + onSuccess: (data) => { + setBookingSuccess({ id: data.bookingId ?? data.id ?? '' }); + setActiveStep(3); + }, + }); + + const canProceedStep0 = startDate && endDate && dayjs(endDate).isAfter(dayjs(startDate)); + const canProceedStep1 = guestsCount > 0; + + const handleNext = useCallback(() => { + if (activeStep === STEPS.length - 1) { + createBookingMutation.mutate(); + } else { + setActiveStep((s) => s + 1); + } + }, [activeStep, createBookingMutation]); + + const handleBack = () => setActiveStep((s) => s - 1); + + if (venueLoading) { + return ( + + + + ); + } + + if (!venue) { + return ( + + Venue not found + + + ); + } + + // Success Screen + if (activeStep === 3 && bookingSuccess) { + return ( + + + + + + + + Booking Confirmed! + + + Your booking ID is + + + #{bookingSuccess.id.slice(-8).toUpperCase()} + + + + + + + Venue + {venue.title} + + + Check-in + {dayjs(startDate).format('DD MMM YYYY')} + + + Check-out + {dayjs(endDate).format('DD MMM YYYY')} + + + Guests + {guestsCount} + + + + Total Paid + + â‚č{total.toLocaleString('en-IN')} + + + + + + + + + + + ); + } + + return ( + + {/* Header */} + + + + Book Your Venue + + + + {/* Stepper */} + + {STEPS.map((label) => ( + + + {label} + + + ))} + + + + {/* Left: Form */} + + + {/* Step 0: Date Selection */} + {activeStep === 0 && ( + + + Select Your Dates + + Choose your check-in and check-out dates + + + + + + { + setStartDate(e.target.value); + if (endDate && e.target.value >= endDate) setEndDate(''); + }} + inputProps={{ min: today }} + InputLabelProps={{ shrink: true }} + sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2.5 } }} + /> + + + setEndDate(e.target.value)} + inputProps={{ min: startDate || today }} + InputLabelProps={{ shrink: true }} + sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2.5 } }} + /> + + + + setGuestsCount(Math.min(Number(e.target.value), venue.capacity))} + inputProps={{ min: 1, max: venue.capacity }} + helperText={`Maximum capacity: ${venue.capacity} guests`} + sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2.5 } }} + /> + + {nights > 0 && ( + } sx={{ borderRadius: 2.5 }}> + {nights} day{nights !== 1 ? 's' : ''} selected · {dayjs(startDate).format('DD MMM')} → {dayjs(endDate).format('DD MMM YYYY')} + + )} + + )} + + {/* Step 1: Guest Details */} + {activeStep === 1 && ( + + + Guest Information + + Tell the host about your event + + + + setSpecialRequests(e.target.value)} + placeholder="Any special requirements, event type, decorations, catering needs, etc." + sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2.5 } }} + /> + + + The host will review your request and confirm availability within 2-4 hours. + + + )} + + {/* Step 2: Review & Pay */} + {activeStep === 2 && ( + + + Review Your Booking + + Please verify the details before confirming + + + + + {[ + { label: 'Venue', value: venue.title }, + { label: 'Location', value: `${venue.city ?? venue.address?.city}, ${venue.state ?? venue.address?.state}` }, + { label: 'Check-in', value: dayjs(startDate).format('dddd, DD MMM YYYY') }, + { label: 'Check-out', value: dayjs(endDate).format('dddd, DD MMM YYYY') }, + { label: 'Duration', value: `${nights} day${nights !== 1 ? 's' : ''}` }, + { label: 'Guests', value: `${guestsCount} people` }, + ].map((item) => ( + + {item.label} + {item.value} + + ))} + + + {specialRequests && ( + + + Special Requests + + {specialRequests} + + )} + + {createBookingMutation.isError && ( + + {/* Booking failed. Please try again. */} + {createBookingMutation.error.message} + + )} + + )} + + {/* Navigation Buttons */} + + {activeStep > 0 && ( + + )} + + + + + + {/* Right: Summary Card */} + + + {/* Venue Image */} + + + + {venue.title} + + + + {venue.city ?? venue.address?.city}, {venue.state ?? venue.address?.state} + + + + {(venue.averageRating ?? 0).toFixed(1)} + ({venue.reviewCount ?? 0}) + + + + + {/* Price Breakdown */} + + Price Breakdown + + + â‚č{venue.pricePerDay.toLocaleString('en-IN')} × {nights || '—'} day{nights !== 1 ? 's' : ''} + + + {nights > 0 ? `â‚č${baseAmount.toLocaleString('en-IN')}` : '—'} + + + + Service fee (10%) + + {nights > 0 ? `â‚č${serviceFee.toLocaleString('en-IN')}` : '—'} + + + + + Total + + {nights > 0 ? `â‚č${total.toLocaleString('en-IN')}` : '—'} + + + + + + + + ); +} diff --git a/frontend/src/sections/user/favorites/index.tsx b/frontend/src/sections/user/favorites/index.tsx new file mode 100644 index 000000000..92ded3cf4 --- /dev/null +++ b/frontend/src/sections/user/favorites/index.tsx @@ -0,0 +1,234 @@ +import type { SavedVenue } from 'src/api/types/venue.type'; + +import { useNavigate } from 'react-router-dom'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; + +import { + Box, + Card, + Grid, + Stack, + Button, + Rating, + Tooltip, + Skeleton, + Container, + IconButton, + Typography, + CardContent, + CardActionArea, +} from '@mui/material'; + +import { UserFavoritesApiService } from 'src/api/user-favorites'; + +import { Iconify } from 'src/components/iconify'; + +function FavoriteCard({ savedVenue, onUnsave }: { savedVenue: SavedVenue; onUnsave: (id: string) => void }) { + const navigate = useNavigate(); + const { venue } = savedVenue; + + return ( + + navigate(`/venues/${venue.id}`)}> + + + + { e.stopPropagation(); onUnsave(venue.id); }} + sx={{ + position: 'absolute', + top: 8, + right: 8, + bgcolor: 'rgba(255,255,255,0.92)', + color: 'error.main', + '&:hover': { bgcolor: 'white', transform: 'scale(1.1)' }, + transition: 'all 0.2s', + }} + > + + + + + + + {venue.title} + + + + + {venue.city}, {venue.state} + + + + + {venue.averageRating?.toFixed(1) ?? '0.0'} + + + + â‚č{venue.pricePerDay.toLocaleString('en-IN')} + /day + + + + + + + ); +} + +function FavoriteCardSkeleton() { + return ( + + + + + + + + + ); +} + +export function FavoritesView() { + const navigate = useNavigate(); + const queryClient = useQueryClient(); + + const { data, isLoading } = useQuery({ + queryKey: ['saved-venues'], + queryFn: () => UserFavoritesApiService.getSavedVenues(1, 24), + retry: false, + }); + + const unsaveMutation = useMutation({ + mutationFn: (venueId: string) => UserFavoritesApiService.unsaveVenue(venueId), + onSuccess: () => queryClient.invalidateQueries({ queryKey: ['saved-venues'] }), + }); + + return ( + + {/* Header */} + + + + + + My Favorites + + + + Venues you've saved for later + + + + + + {isLoading ? ( + + {Array.from({ length: 6 }).map((_, i) => ( + + + + ))} + + ) : data?.data.length === 0 ? ( + + + + + + No saved venues yet + + + Tap the heart icon on any venue to save it here for easy access later. + + + + ) : ( + <> + + + {data?.total ?? 0} saved venue{(data?.total ?? 0) !== 1 ? 's' : ''} + + + + {data?.data.map((savedVenue) => ( + + unsaveMutation.mutate(id)} + /> + + ))} + + + )} + + + ); +} diff --git a/frontend/src/sections/user/landing/featured-venues.tsx b/frontend/src/sections/user/landing/featured-venues.tsx new file mode 100644 index 000000000..b60761c00 --- /dev/null +++ b/frontend/src/sections/user/landing/featured-venues.tsx @@ -0,0 +1,258 @@ +import type { VenueCard } from 'src/api/types/venue.type'; + +import { useNavigate } from 'react-router-dom'; +import { useQuery } from '@tanstack/react-query'; + +import { + Box, + Card, + Chip, + Grid, + Stack, + Button, + Rating, + Skeleton, + Container, + Typography, + CardContent, + CardActionArea, +} from '@mui/material'; + +import { VenuePublicApiService } from 'src/api/venue-public'; + +import { Iconify } from 'src/components/iconify'; + +const MOCK_VENUES: VenueCard[] = [ + { + id: '1', title: 'The Grand Ballroom', venueType: 'BANQUET_HALL', + city: 'Mumbai', state: 'Maharashtra', country: 'India', + capacity: 500, pricePerDay: 85000, averageRating: 4.9, reviewCount: 248, + thumbnail: 'https://images.unsplash.com/photo-1519167758481-83f550bb49b3?w=600&q=75', + isSaved: false, + description: 'Elegant ballroom for premium events', + }, + { + id: '2', title: 'Sky Garden Terrace', venueType: 'EVENT_SPACE', + city: 'Bangalore', state: 'Karnataka', country: 'India', + capacity: 200, pricePerDay: 42000, averageRating: 4.7, reviewCount: 185, + thumbnail: 'https://images.unsplash.com/photo-1464366400600-7168b8af9bc3?w=600&q=75', + isSaved: true, + description: 'Stunning rooftop with city views', + }, + { + id: '3', title: 'The Conference Hub', venueType: 'CONFERENCE_ROOM', + city: 'Delhi', state: 'Delhi', country: 'India', + capacity: 100, pricePerDay: 22000, averageRating: 4.8, reviewCount: 312, + thumbnail: 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=600&q=75', + isSaved: false, + description: 'Modern conference room in the heart of Delhi', + }, + { + id: '4', title: 'Heritage Manor', venueType: 'HOTEL', + city: 'Udaipur', state: 'Rajasthan', country: 'India', + capacity: 300, pricePerDay: 120000, averageRating: 4.9, reviewCount: 97, + thumbnail: 'https://images.unsplash.com/photo-1551882547-ff40c4a49a5c?w=600&q=75', + isSaved: false, + description: 'Royal heritage property by the lake', + }, + { + id: '5', title: 'La Bella Cucina', venueType: 'RESTAURANT', + city: 'Pune', state: 'Maharashtra', country: 'India', + capacity: 80, pricePerDay: 18000, averageRating: 4.6, reviewCount: 421, + thumbnail: 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=600&q=75', + isSaved: true, + description: 'Exquisite restaurant for private dining', + }, + { + id: '6', title: 'The Party Loft', venueType: 'PARTY_HALL', + city: 'Hyderabad', state: 'Telangana', country: 'India', + capacity: 150, pricePerDay: 35000, averageRating: 4.7, reviewCount: 163, + thumbnail: 'https://images.unsplash.com/photo-1530103862676-de8c9debad1d?w=600&q=75', + isSaved: false, + description: 'Vibrant party space with great amenities', + }, +]; + +function VenueCardSkeleton() { + return ( + + + + + + + + + ); +} + +interface VenueCardItemProps { + venue: VenueCard; +} + +function VenueCardItem({ venue }: VenueCardItemProps) { + const navigate = useNavigate(); + + return ( + + navigate(`/venues/${venue.id}`)}> + {/* Image */} + + + {/* Type Badge */} + + {/* Heart */} + + + + + + {/* Info */} + + + {venue.title} + + + + + {venue.city}, {venue.state} + + + + + + {venue.averageRating?.toFixed(1) ?? '0.0'} ({venue.reviewCount ?? 0}) + + + + + Starting from + + â‚č{venue.pricePerDay.toLocaleString('en-IN')} + + {' '}/day + + + + + + {venue.capacity} + + + + + + ); +} + +export function FeaturedVenues() { + const navigate = useNavigate(); + + const { data: venues, isLoading } = useQuery({ + queryKey: ['featured-venues'], + queryFn: () => VenuePublicApiService.getFeaturedVenues(), + retry: false, + }); + + const displayVenues = venues?.data && venues.data.length > 0 ? venues.data : MOCK_VENUES; + + return ( + + + + + + Featured + + + Top Venues Near You + + + Handpicked spaces for unforgettable events + + + + + + + {isLoading + ? Array.from({ length: 6 }).map((_, i) => ( + + + + )) + : displayVenues.slice(0, 6).map((venue) => ( + + + + )) + } + + + + ); +} diff --git a/frontend/src/sections/user/landing/hero-section.tsx b/frontend/src/sections/user/landing/hero-section.tsx new file mode 100644 index 000000000..503542671 --- /dev/null +++ b/frontend/src/sections/user/landing/hero-section.tsx @@ -0,0 +1,290 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +import { + Box, + Chip, + Paper, + Stack, + Button, + useTheme, + Container, + Typography, + OutlinedInput, + useMediaQuery, + InputAdornment, +} from '@mui/material'; + +import { Iconify } from 'src/components/iconify'; + +const TRENDING_SEARCHES = ['Banquet Hall', 'Conference Room', 'Mumbai', 'Bangalore', 'Delhi']; + +const STATS = [ + { value: '10K+', label: 'Venues Listed' }, + { value: '50K+', label: 'Events Hosted' }, + { value: '100+', label: 'Cities Covered' }, + { value: '4.8★', label: 'Average Rating' }, +]; + +export function HeroSection() { + const navigate = useNavigate(); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + + const [location, setLocation] = useState(''); + const [guests, setGuests] = useState(''); + + const handleSearch = () => { + const params = new URLSearchParams(); + if (location) params.set('query', location); + if (guests) params.set('minCapacity', guests); + navigate(`/search?${params.toString()}`); + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') handleSearch(); + }; + + return ( + + {/* Background Image */} + + + {/* Gradient Overlay */} + + + + + {/* Badge */} + } + label="India's #1 Venue Discovery Platform" + sx={{ + bgcolor: 'rgba(255,255,255,0.15)', + color: 'white', + backdropFilter: 'blur(8px)', + border: '1px solid rgba(255,255,255,0.3)', + fontWeight: 600, + fontSize: 13, + px: 1, + '& .MuiChip-icon': { color: '#FFD700' }, + }} + /> + + {/* Headline */} + + + Find Your Perfect + + Venue + + + + From intimate gatherings to grand celebrations — discover, book, and celebrate + + + + {/* Search Bar */} + + + {/* Location Input */} + setLocation(e.target.value)} + onKeyDown={handleKeyDown} + startAdornment={ + + + + } + sx={{ + flex: 1, + borderRadius: 3, + '& .MuiOutlinedInput-notchedOutline': { border: '1.5px solid', borderColor: 'divider' }, + '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: 'primary.main' }, + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { borderColor: 'primary.main', borderWidth: 2 }, + fontSize: { xs: 15, md: 16 }, + }} + /> + + {/* Guests Input */} + setGuests(e.target.value)} + onKeyDown={handleKeyDown} + startAdornment={ + + + + } + sx={{ + width: { xs: '100%', sm: 160 }, + borderRadius: 3, + '& .MuiOutlinedInput-notchedOutline': { border: '1.5px solid', borderColor: 'divider' }, + '&:hover .MuiOutlinedInput-notchedOutline': { borderColor: 'primary.main' }, + '&.Mui-focused .MuiOutlinedInput-notchedOutline': { borderColor: 'primary.main', borderWidth: 2 }, + }} + /> + + {/* Search Button */} + + + + + {/* Trending Searches */} + + + Trending: + + {TRENDING_SEARCHES.map((term) => ( + navigate(`/search?query=${term}`)} + size="small" + sx={{ + bgcolor: 'rgba(255,255,255,0.15)', + color: 'white', + border: '1px solid rgba(255,255,255,0.25)', + fontWeight: 500, + cursor: 'pointer', + backdropFilter: 'blur(6px)', + '&:hover': { bgcolor: 'rgba(255,255,255,0.25)' }, + }} + /> + ))} + + + {/* Stats */} + + {STATS.map((stat) => ( + + + {stat.value} + + + {stat.label} + + + ))} + + + + + {/* Bottom Wave */} + + + ); +} diff --git a/frontend/src/sections/user/landing/host-cta.tsx b/frontend/src/sections/user/landing/host-cta.tsx new file mode 100644 index 000000000..baddb8756 --- /dev/null +++ b/frontend/src/sections/user/landing/host-cta.tsx @@ -0,0 +1,234 @@ +import { useNavigate } from 'react-router-dom'; + +import { Box, Grid, Paper, Stack, Button, Container, Typography } from '@mui/material'; + +import { Iconify } from 'src/components/iconify'; + +const HOST_BENEFITS = [ + { icon: 'mdi:cash-multiple', label: 'Earn Extra Income', desc: 'List your venue and start earning from day one' }, + { icon: 'mdi:account-multiple', label: 'Reach More Clients', desc: '50K+ event planners actively searching for venues' }, + { icon: 'mdi:calendar-month', label: 'Flexible Availability', desc: 'You control your calendar and pricing' }, + { icon: 'mdi:headset', label: 'Dedicated Support', desc: 'Our host success team is always here to help' }, +]; + +export function HostCta() { + const navigate = useNavigate(); + + return ( + + + + {/* Decorative Elements */} + + + + + {/* Left Content */} + + + + + + For Venue Owners + + + Turn Your Space Into + + A Revenue Machine + + + + Join 5,000+ venue owners earning consistent income by listing their spaces on + BookMyVenue. Setup takes less than 10 minutes. + + + + + {HOST_BENEFITS.map((benefit) => ( + + + + + + + {benefit.label} + + + {benefit.desc} + + + + ))} + + + + + + + + + + + {/* Right Image */} + + + {/* Earnings Badge */} + + + + + + + + +â‚č1.2L + + + Average monthly earnings + + + + + + + + + + + ); +} diff --git a/frontend/src/sections/user/landing/how-it-works.tsx b/frontend/src/sections/user/landing/how-it-works.tsx new file mode 100644 index 000000000..cec86c556 --- /dev/null +++ b/frontend/src/sections/user/landing/how-it-works.tsx @@ -0,0 +1,155 @@ +import { Box, Grid, Stack, Container, Typography } from '@mui/material'; + +import { Iconify } from 'src/components/iconify'; + +const STEPS = [ + { + step: '01', + icon: 'mdi:magnify', + title: 'Search & Discover', + description: + 'Browse thousands of verified venues. Filter by location, capacity, type, and price to find your ideal space.', + color: '#1877F2', + bg: 'linear-gradient(135deg, #E3F2FD 0%, #EDE7F6 100%)', + }, + { + step: '02', + icon: 'mdi:calendar-check', + title: 'Check Availability', + description: + 'View real-time availability, detailed photos, amenities, and verified reviews before you decide.', + color: '#8E33FF', + bg: 'linear-gradient(135deg, #F3E5F5 0%, #E8EAF6 100%)', + }, + { + step: '03', + icon: 'mdi:credit-card-check', + title: 'Book & Pay Securely', + description: + 'Book instantly or send a request. Pay securely with multiple payment options. Instant confirmation.', + color: '#22C55E', + bg: 'linear-gradient(135deg, #E8F5E9 0%, #F0FFF4 100%)', + }, + { + step: '04', + icon: 'mdi:party-popper', + title: 'Celebrate!', + description: + 'Arrive and enjoy your event. Our support team is available 24/7 to assist you every step of the way.', + color: '#FF6B6B', + bg: 'linear-gradient(135deg, #FFF0F0 0%, #FFF8F0 100%)', + }, +]; + +export function HowItWorks() { + return ( + + + + + Simple Process + + + How BookMyVenue Works + + + Booking a venue has never been this easy. Four simple steps to your perfect event. + + + + + {STEPS.map((step, index) => ( + + + {/* Step Number (bg text) */} + + {step.step} + + + {/* Connector Arrow (desktop) */} + {index < STEPS.length - 1 && ( + + + + )} + + + {/* Icon */} + + + + + {/* Step Badge */} + + Step {step.step} + + + + {step.title} + + + + {step.description} + + + + + ))} + + + + ); +} diff --git a/frontend/src/sections/user/landing/index.tsx b/frontend/src/sections/user/landing/index.tsx new file mode 100644 index 000000000..268ffd5c1 --- /dev/null +++ b/frontend/src/sections/user/landing/index.tsx @@ -0,0 +1,19 @@ +import { HostCta } from './host-cta'; +import { HowItWorks } from './how-it-works'; +import { HeroSection } from './hero-section'; +import { Testimonials } from './testimonials'; +import { FeaturedVenues } from './featured-venues'; +import { PopularCategories } from './popular-categories'; + +export function LandingView() { + return ( + <> + + + + + + + + ); +} diff --git a/frontend/src/sections/user/landing/popular-categories.tsx b/frontend/src/sections/user/landing/popular-categories.tsx new file mode 100644 index 000000000..562924d90 --- /dev/null +++ b/frontend/src/sections/user/landing/popular-categories.tsx @@ -0,0 +1,171 @@ +import { useNavigate } from 'react-router-dom'; + +import { Box, Grid, Paper, Stack, Container, Typography } from '@mui/material'; + +import { Iconify } from 'src/components/iconify'; + +const CATEGORIES = [ + { + label: 'Banquet Halls', + icon: 'mdi:silverware-fork-knife', + type: 'BANQUET_HALL', + color: '#FF6B6B', + bg: '#FFF0F0', + count: '2.4K venues', + image: 'https://images.unsplash.com/photo-1519167758481-83f550bb49b3?w=400&q=70', + }, + { + label: 'Conference Rooms', + icon: 'mdi:presentation', + type: 'CONFERENCE_ROOM', + color: '#4ECDC4', + bg: '#F0FFFE', + count: '1.8K venues', + image: 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=400&q=70', + }, + { + label: 'Event Spaces', + icon: 'mdi:party-popper', + type: 'EVENT_SPACE', + color: '#8E33FF', + bg: '#F5F0FF', + count: '3.1K venues', + image: 'https://images.unsplash.com/photo-1511795409834-ef04bbd61622?w=400&q=70', + }, + { + label: 'Restaurants', + icon: 'mdi:food', + type: 'RESTAURANT', + color: '#FF8C00', + bg: '#FFF8F0', + count: '2.7K venues', + image: 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=400&q=70', + }, + { + label: 'Hotels & Resorts', + icon: 'mdi:hotel', + type: 'HOTEL', + color: '#1877F2', + bg: '#F0F5FF', + count: '1.5K venues', + image: 'https://images.unsplash.com/photo-1551882547-ff40c4a49a5c?w=400&q=70', + }, + { + label: 'Auditoriums', + icon: 'mdi:theater', + type: 'AUDITORIUM', + color: '#E91E63', + bg: '#FFF0F5', + count: '890 venues', + image: 'https://images.unsplash.com/photo-1540575467063-178a50c2df87?w=400&q=70', + }, + { + label: 'Party Halls', + icon: 'mdi:balloon', + type: 'PARTY_HALL', + color: '#00BCD4', + bg: '#F0FBFF', + count: '1.2K venues', + image: 'https://images.unsplash.com/photo-1464366400600-7168b8af9bc3?w=400&q=70', + }, + { + label: 'Meeting Rooms', + icon: 'mdi:account-group', + type: 'MEETING_ROOM', + color: '#4CAF50', + bg: '#F0FFF4', + count: '2.0K venues', + image: 'https://images.unsplash.com/photo-1552664730-d307ca884978?w=400&q=70', + }, +]; + +export function PopularCategories() { + const navigate = useNavigate(); + + return ( + + + + + Browse by Category + + + What are you looking for? + + + Explore our wide range of venue categories to find the perfect space for any occasion + + + + + {CATEGORIES.map((cat) => ( + + navigate(`/search?venueType=${cat.type}`)} + elevation={0} + sx={{ + borderRadius: 4, + overflow: 'hidden', + cursor: 'pointer', + border: '1.5px solid', + borderColor: 'divider', + transition: 'all 0.25s ease', + '&:hover': { + transform: 'translateY(-6px)', + boxShadow: `0 16px 40px ${cat.color}25`, + borderColor: cat.color, + }, + }} + > + {/* Image */} + + + + + + + + {/* Info */} + + + {cat.label} + + + {cat.count} + + + + + ))} + + + + ); +} diff --git a/frontend/src/sections/user/landing/testimonials.tsx b/frontend/src/sections/user/landing/testimonials.tsx new file mode 100644 index 000000000..825159605 --- /dev/null +++ b/frontend/src/sections/user/landing/testimonials.tsx @@ -0,0 +1,190 @@ +import { Box, Grid, Paper, Stack, Avatar, Rating, Container, Typography } from '@mui/material'; + +import { Iconify } from 'src/components/iconify'; + +const TESTIMONIALS = [ + { + name: 'Priya Sharma', + role: 'Wedding Planner', + avatar: 'https://i.pravatar.cc/100?img=1', + rating: 5, + text: 'BookMyVenue made planning my clients\' weddings so much easier. The platform has an incredible selection of venues and the booking process is seamless. Highly recommended!', + venue: 'The Grand Ballroom, Mumbai', + event: 'Wedding Reception', + }, + { + name: 'Rahul Mehta', + role: 'Corporate Events Manager', + avatar: 'https://i.pravatar.cc/100?img=11', + rating: 5, + text: 'We use BookMyVenue for all our corporate events. The ability to filter by capacity and amenities saves us hours. The venues are exactly as described — no surprises!', + venue: 'The Conference Hub, Delhi', + event: 'Annual Conference', + }, + { + name: 'Sneha Patel', + role: 'Birthday Party Host', + avatar: 'https://i.pravatar.cc/100?img=5', + rating: 5, + text: 'Booked the Sky Garden Terrace for my 30th birthday and it was absolutely magical! The team was responsive, the venue was stunning, and the experience was unforgettable.', + venue: 'Sky Garden Terrace, Bangalore', + event: 'Birthday Party', + }, + { + name: 'Arjun Nair', + role: 'Startup Founder', + avatar: 'https://i.pravatar.cc/100?img=15', + rating: 4, + text: 'Used BookMyVenue for our product launch event. Got a great space at a competitive price. The instant booking confirmation was a huge plus for our tight timeline.', + venue: 'InnoSpace Hub, Chennai', + event: 'Product Launch', + }, + { + name: 'Kavya Reddy', + role: 'Event Coordinator', + avatar: 'https://i.pravatar.cc/100?img=9', + rating: 5, + text: 'The platform is intuitive and the venue listings are detailed and accurate. I\'ve booked 12+ venues through BookMyVenue and never had an issue. Excellent service!', + venue: 'Multiple Venues', + event: 'Various Events', + }, + { + name: 'Vikram Singh', + role: 'Restaurant Owner', + avatar: 'https://i.pravatar.cc/100?img=21', + rating: 5, + text: 'Listed my restaurant on BookMyVenue and bookings increased by 40%. The platform is easy to manage and the support team is always helpful. Game changer for my business!', + venue: 'La Bella Cucina, Pune', + event: 'Private Dining', + }, +]; + +interface TestimonialCardProps { + testimonial: typeof TESTIMONIALS[number]; +} + +function TestimonialCard({ testimonial }: TestimonialCardProps) { + return ( + + {/* Quote Icon */} + + + + + {/* Review Text */} + + “{testimonial.text}” + + + {/* Rating */} + + + {/* Venue Tag */} + + + {testimonial.venue} + + + {/* Author */} + + + + {testimonial.name} + {testimonial.role} + + + + ); +} + +export function Testimonials() { + return ( + + + + + Testimonials + + + What Our Users Say + + + Join thousands of happy hosts and guests who have found their perfect venue on BookMyVenue + + + + + {TESTIMONIALS.map((t) => ( + + + + ))} + + + {/* Trust Indicators */} + + {[ + { icon: 'mdi:shield-check', label: 'Verified Venues', color: '#22C55E' }, + { icon: 'mdi:lock-check', label: 'Secure Payments', color: '#1877F2' }, + { icon: 'mdi:headset', label: '24/7 Support', color: '#8E33FF' }, + { icon: 'mdi:star-circle', label: '4.8/5 Rating', color: '#FF6B6B' }, + ].map((item) => ( + + + + {item.label} + + + ))} + + + + ); +} diff --git a/frontend/src/sections/user/my-bookings/index.tsx b/frontend/src/sections/user/my-bookings/index.tsx new file mode 100644 index 000000000..7abd1424f --- /dev/null +++ b/frontend/src/sections/user/my-bookings/index.tsx @@ -0,0 +1,430 @@ +import type { BookingStatus, BookingSummary } from 'src/api/types/venue.type'; + +import dayjs from 'dayjs'; +import { useState } from 'react'; +import { Link, useNavigate } from 'react-router-dom'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; + +import { + Box, + Tab, + Chip, + Grid, + Tabs, + Paper, + Stack, + Button, + Dialog, + Divider, + Skeleton, + Container, + Typography, + DialogTitle, + DialogActions, + DialogContent, +} from '@mui/material'; + +import { PaymentStatus } from 'src/api/types/payment.type'; +import { UserBookingApiService } from 'src/api/user-booking'; + +import { Iconify } from 'src/components/iconify'; + +const STATUS_CONFIG: Record = { + BOOKED: { label: 'Booked', color: 'success', icon: 'mdi:check-circle-outline' }, + CANCELLED: { label: 'Cancelled', color: 'error', icon: 'mdi:close-circle-outline' }, +}; + +const PAYMENT_STATUS_CONFIG: Record< + PaymentStatus, + { label: string; color: 'default' | 'warning' | 'success' | 'error' | 'info'; icon: string } +> = { + PENDING: { label: 'Payment Pending', color: 'warning', icon: 'mdi:clock-outline' }, + INITIATED: { label: 'Payment Initiated', color: 'info', icon: 'mdi:credit-card-clock-outline' }, + PAID: { label: 'Paid', color: 'success', icon: 'mdi:check-circle-outline' }, + FAILED: { label: 'Payment Failed', color: 'error', icon: 'mdi:close-circle-outline' }, + REFUNDED: { label: 'Refunded', color: 'default', icon: 'mdi:cash-refund' }, +}; + +function getPaymentButtonProps(booking: BookingSummary) { + const paymentPath = `/my/bookings/${booking.id}/payment`; + + if (booking.status !== 'BOOKED') { + return null; + } + + switch (booking.paymentStatus) { + case PaymentStatus.PENDING: + return { + label: 'Pay Now', + path: paymentPath, + variant: 'contained' as const, + color: 'primary' as const, + icon: 'mdi:credit-card-outline', + }; + case PaymentStatus.FAILED: + return { + label: 'Retry Payment', + path: paymentPath, + variant: 'contained' as const, + color: 'warning' as const, + icon: 'mdi:refresh', + }; + case PaymentStatus.INITIATED: + return { + label: 'Complete Payment', + path: paymentPath, + variant: 'contained' as const, + color: 'primary' as const, + icon: 'mdi:credit-card-check-outline', + }; + case PaymentStatus.PAID: + return { + label: 'View Payment', + path: paymentPath, + variant: 'outlined' as const, + color: 'success' as const, + icon: 'mdi:receipt-text-outline', + }; + case PaymentStatus.REFUNDED: + return { + label: 'Refund Details', + path: paymentPath, + variant: 'outlined' as const, + color: 'inherit' as const, + icon: 'mdi:cash-refund', + }; + default: + return null; + } +} +interface BookingCardProps { + booking: BookingSummary; + onCancel: (id: string) => void; +} + +function BookingCard({ booking, onCancel }: BookingCardProps) { + const statusCfg = STATUS_CONFIG[booking.status]; + const paymentCfg = PAYMENT_STATUS_CONFIG[booking.paymentStatus]; + const paymentButton = getPaymentButtonProps(booking); + const nights = Math.max(1, dayjs(booking.endDate).diff(dayjs(booking.startDate), 'day')); + const venueId = booking.venue?.id; + return ( + + + {/* Venue Image */} + + + + + {/* Details */} + + + + + + {booking.venue?.title || booking.venueName} + + + Booking #{(booking.id ?? '').slice(-8).toUpperCase()} + + + + } + label={paymentCfg.label} + color={paymentCfg.color} + size="small" + sx={{ fontWeight: 700 }} + /> + } + label={statusCfg.label} + color={statusCfg.color} + size="small" + sx={{ fontWeight: 700 }} + /> + + + + {[ + { icon: 'mdi:calendar-arrow-right', label: 'Check-in', value: dayjs(booking.startDate).format('DD MMM YYYY') }, + { icon: 'mdi:calendar-arrow-left', label: 'Check-out', value: dayjs(booking.endDate).format('DD MMM YYYY') }, + { icon: 'mdi:weather-night', label: 'Duration', value: `${nights} day${nights !== 1 ? 's' : ''}` }, + { icon: 'mdi:cash', label: 'Total Amount', value: `â‚č${booking.totalAmount.toLocaleString('en-IN')}` }, + ].map((item) => ( + + + + + {item.label} + {item.value} + + + + ))} + + + + + + + + + {paymentButton && ( + + + + )} + {venueId && ( + + + + )} + {booking.status === 'BOOKED' && ( + + )} + + + + + ); +} + +function BookingCardSkeleton() { + return ( + + + + + + + + + + + + + + + ); +} + +const TAB_STATUSES = [ + { label: 'All Bookings', value: undefined as BookingStatus | undefined }, + { label: 'Booked', value: 'BOOKED' as BookingStatus }, + { label: 'Cancelled', value: 'CANCELLED' as BookingStatus }, +]; +export function MyBookingsView() { + const navigate = useNavigate(); + const queryClient = useQueryClient(); + const [tabIndex, setTabIndex] = useState(0); + const [cancelDialogId, setCancelDialogId] = useState(null); + + const selectedStatus = TAB_STATUSES[tabIndex].value; + + const { data, isLoading } = useQuery({ + queryKey: ['my-bookings', selectedStatus], + queryFn: () => UserBookingApiService.getMyBookings(1, 20, selectedStatus), + retry: false, + }); + + const cancelMutation = useMutation({ + mutationFn: (id: string) => UserBookingApiService.cancelBooking(id), + onSuccess: () => { + setCancelDialogId(null); + queryClient.invalidateQueries({ queryKey: ['my-bookings'] }); + }, + }); + + return ( + + {/* Header Banner */} + + + + + + My Bookings + + + + Manage all your venue bookings in one place + + + + + + {/* Tabs */} + + setTabIndex(v)} + variant="scrollable" + scrollButtons="auto" + sx={{ + px: 1, + '& .MuiTab-root': { fontWeight: 600, minHeight: 52 }, + '& .Mui-selected': { color: 'primary.main' }, + }} + > + {TAB_STATUSES.map((t) => ( + + ))} + + + + {/* Booking List */} + + {isLoading ? ( + Array.from({ length: 3 }).map((_, i) => ) + ) : (data?.data?.length ?? 0) === 0 ? ( + + + + + + No bookings yet + + + {tabIndex === 0 + ? "You haven't made any bookings. Start exploring venues!" + : `No ${TAB_STATUSES[tabIndex].label.toLowerCase()} bookings.`} + + + + ) : ( + (data?.data ?? []).map((booking) => ( + setCancelDialogId(id)} /> + )) + )} + + + + {/* Cancel Confirmation Dialog */} + setCancelDialogId(null)} + PaperProps={{ sx: { borderRadius: 4, p: 1 } }} + > + + + + Cancel Booking + + + + + Are you sure you want to cancel this booking? This action cannot be undone. + Cancellation fees may apply depending on the venue policy. + + + + + + + + + ); +} diff --git a/frontend/src/sections/user/payment/index.tsx b/frontend/src/sections/user/payment/index.tsx new file mode 100644 index 000000000..8a24d5d6b --- /dev/null +++ b/frontend/src/sections/user/payment/index.tsx @@ -0,0 +1,503 @@ +import type { BookingDetails } from 'src/api/user-booking'; + +import dayjs from 'dayjs'; +import { useState, useEffect } from 'react'; +import { Link, useParams, useNavigate } from 'react-router-dom'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; + +import LoadingButton from '@mui/lab/LoadingButton'; +import { + Box, + Chip, + Grid, + Paper, + Stack, + Alert, + Button, + Divider, + Skeleton, + Container, + TextField, + Typography, + Breadcrumbs, + CircularProgress, +} from '@mui/material'; + +import { UserApiService } from 'src/api/user'; +import { PaymentApiService } from 'src/api/payment'; +import { useAuth } from 'src/context/auth/use-auth'; +import { PaymentStatus } from 'src/api/types/payment.type'; +import { UserBookingApiService } from 'src/api/user-booking'; +import { loadRazorpayScript, openRazorpayCheckout } from 'src/lib/razorpay'; + +import { Iconify } from 'src/components/iconify'; + +const PAYMENT_STATUS_CONFIG: Record< + PaymentStatus, + { label: string; color: 'default' | 'warning' | 'success' | 'error' | 'info'; icon: string } +> = { + PENDING: { label: 'Payment Pending', color: 'warning', icon: 'mdi:clock-outline' }, + INITIATED: { label: 'Payment Initiated', color: 'info', icon: 'mdi:credit-card-clock-outline' }, + PAID: { label: 'Paid', color: 'success', icon: 'mdi:check-circle-outline' }, + FAILED: { label: 'Payment Failed', color: 'error', icon: 'mdi:close-circle-outline' }, + REFUNDED: { label: 'Refunded', color: 'default', icon: 'mdi:cash-refund' }, +}; + +function formatPhone(value: string) { + const digits = value.replace(/\D/g, ''); + if (digits.length <= 10) { + return digits; + } + if (digits.startsWith('91') && digits.length === 12) { + return `+${digits}`; + } + return value; +} + +function PaymentSkeleton() { + return ( + + + + + ); +} + +function PaymentSuccessView({ + booking, + paidAt, + onViewBooking, +}: { + booking: BookingDetails; + paidAt?: string; + onViewBooking: () => void; +}) { + const bookingRef = (booking.id ?? '').slice(-8).toUpperCase(); + + return ( + + + + + + + Payment Successful + + + Your booking #{bookingRef} has been paid successfully. + + + + + Venue + {booking.venue?.title} + + + Amount Paid + + â‚č{(booking.totalAmount ?? 0).toLocaleString('en-IN')} + + + {paidAt && ( + + Paid On + + {dayjs(paidAt).format('DD MMM YYYY, hh:mm A')} + + + )} + + + + + + + + ); +} + +export function PaymentView() { + const navigate = useNavigate(); + const queryClient = useQueryClient(); + const { user } = useAuth(); + const { bookingId } = useParams<{ bookingId: string }>(); + + const [phone, setPhone] = useState(''); + const [phoneTouched, setPhoneTouched] = useState(false); + const [errorMessage, setErrorMessage] = useState(''); + const [paidAt, setPaidAt] = useState(null); + const [isCheckoutOpen, setIsCheckoutOpen] = useState(false); + + const { data: booking, isLoading, isError } = useQuery({ + queryKey: ['booking-details', bookingId], + queryFn: () => UserBookingApiService.getBookingDetails(bookingId!), + enabled: !!bookingId, + retry: 1, + }); + + const { data: profile } = useQuery({ + queryKey: ['user-profile-phone'], + queryFn: UserApiService.me, + retry: false, + }); + + useEffect(() => { + const defaultPhone = booking?.user?.phone ?? profile?.phone; + if (defaultPhone) { + setPhone((prev) => prev || defaultPhone); + } + }, [booking?.user?.phone, profile?.phone]); + + const verifyMutation = useMutation({ + mutationFn: PaymentApiService.verifyPayment, + onSuccess: (result) => { + setPaidAt(result.paidAt); + setIsCheckoutOpen(false); + queryClient.invalidateQueries({ queryKey: ['booking-details', bookingId] }); + queryClient.invalidateQueries({ queryKey: ['my-bookings'] }); + }, + onError: () => { + setErrorMessage('Payment verification failed. If amount was deducted, contact support.'); + setIsCheckoutOpen(false); + }, + }); + + const handlePay = async () => { + if (!bookingId || !booking) return; + + setPhoneTouched(true); + setErrorMessage(''); + + const trimmedPhone = phone.trim(); + if (!trimmedPhone || trimmedPhone.replace(/\D/g, '').length < 10) { + setErrorMessage('Please enter a valid phone number.'); + return; + } + + const scriptLoaded = await loadRazorpayScript(); + if (!scriptLoaded) { + setErrorMessage('Unable to load payment gateway. Please try again.'); + return; + } + + try { + setIsCheckoutOpen(true); + const initiateResult = await PaymentApiService.initiatePayment({ + bookingId, + customerPhone: formatPhone(trimmedPhone), + }); + + openRazorpayCheckout(initiateResult.checkoutData, { + name: user?.name ?? `${booking.user?.firstName ?? ''} ${booking.user?.lastName ?? ''}`.trim(), + email: booking.user?.email ?? user?.email, + phone: formatPhone(trimmedPhone), + description: `Booking for ${booking.venue?.title ?? 'venue'}`, + onSuccess: (response) => { + verifyMutation.mutate({ + providerOrderId: response.razorpay_order_id, + providerPaymentId: response.razorpay_payment_id, + signature: response.razorpay_signature, + }); + }, + onDismiss: () => { + setIsCheckoutOpen(false); + queryClient.invalidateQueries({ queryKey: ['booking-details', bookingId] }); + }, + }); + } catch (err: unknown) { + setIsCheckoutOpen(false); + const message = + (err as { response?: { data?: { message?: string } } })?.response?.data?.message + ?? 'Failed to start payment. Please try again.'; + setErrorMessage(message); + } + }; + + if (isLoading) { + return ; + } + + if (isError || !booking) { + return ( + + + + Booking Not Found + + + + ); + } + + const paymentStatus = booking.paymentStatus ?? PaymentStatus.PENDING; + const paymentCfg = PAYMENT_STATUS_CONFIG[paymentStatus]; + const bookingRef = (booking.id ?? '').slice(-8).toUpperCase(); + const nights = Math.max(1, dayjs(booking.endDate).diff(dayjs(booking.startDate), 'day')); + const canPay = + booking.status === 'BOOKED' + && (paymentStatus === PaymentStatus.PENDING || paymentStatus === PaymentStatus.FAILED); + const isPaid = paymentStatus === PaymentStatus.PAID || !!paidAt; + const isRefunded = paymentStatus === PaymentStatus.REFUNDED; + const isInitiated = paymentStatus === PaymentStatus.INITIATED; + + return ( + + + + } + sx={{ mb: 2 }} + > + navigate('/my/bookings')} + sx={{ cursor: 'pointer', '&:hover': { color: 'white' } }} + > + My Bookings + + navigate(`/my/bookings/${bookingId}`)} + sx={{ cursor: 'pointer', '&:hover': { color: 'white' } }} + > + Booking #{bookingRef} + + + Payment + + + + + + + {isPaid ? 'Payment Receipt' : 'Complete Payment'} + + + {booking.venue?.title} + + + } + label={paymentCfg.label} + sx={{ + bgcolor: 'rgba(255,255,255,0.12)', + color: 'white', + fontWeight: 700, + '& .MuiChip-icon': { color: 'white' }, + }} + /> + + + + + + {isPaid ? ( + navigate(`/my/bookings/${bookingId}`)} + /> + ) : ( + + + + + Booking Summary + + + + {[ + { label: 'Venue', value: booking.venue?.title ?? '—' }, + { label: 'Check-in', value: dayjs(booking.startDate).format('DD MMM YYYY') }, + { label: 'Check-out', value: dayjs(booking.endDate).format('DD MMM YYYY') }, + { label: 'Duration', value: `${nights} day${nights !== 1 ? 's' : ''}` }, + { label: 'Guests', value: String(booking.guestsCount) }, + ].map((row) => ( + + {row.label} + {row.value} + + ))} + + + {isRefunded && ( + + This payment has been refunded. No further action is required. + + )} + + {isInitiated && ( + + A payment session was already started for this booking. If checkout was closed, + please contact support or try again later. + + )} + + {booking.status === 'CANCELLED' && ( + + This booking is cancelled. Payment is not available. + + )} + + {errorMessage && ( + + {errorMessage} + + )} + + {canPay && ( + <> + + + Contact Number + + setPhone(e.target.value)} + onBlur={() => setPhoneTouched(true)} + error={phoneTouched && phone.replace(/\D/g, '').length < 10} + helperText={ + phoneTouched && phone.replace(/\D/g, '').length < 10 + ? 'Enter a valid 10-digit phone number' + : 'Used for payment confirmation via Razorpay' + } + sx={{ mb: 2, '& .MuiOutlinedInput-root': { borderRadius: 2.5 } }} + /> + + } + sx={{ + borderRadius: 2.5, + fontWeight: 700, + py: 1.5, + background: 'linear-gradient(135deg, #1877F2 0%, #8E33FF 100%)', + }} + > + {paymentStatus === PaymentStatus.FAILED ? 'Retry Payment' : 'Pay with Razorpay'} + + + )} + + + + + + + Amount to Pay + + + + â‚č{(booking.totalAmount ?? 0).toLocaleString('en-IN')} + + + + + + + Secured by Razorpay + + + + + + 256-bit encrypted checkout + + + + + + + + + + + )} + + {verifyMutation.isPending && ( + + + + + Verifying payment... + + + + )} + + + ); +} diff --git a/frontend/src/sections/user/profile/index.tsx b/frontend/src/sections/user/profile/index.tsx new file mode 100644 index 000000000..f6342b29c --- /dev/null +++ b/frontend/src/sections/user/profile/index.tsx @@ -0,0 +1,363 @@ +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +import { + Box, + Grid, + List, + Alert, + Paper, + Stack, + Avatar, + Button, + Divider, + ListItem, + Container, + TextField, + Typography, + ListItemIcon, + ListItemText, + ListItemButton, +} from '@mui/material'; + +import { useAuth } from 'src/context/auth/use-auth'; + +import { Iconify } from 'src/components/iconify'; + +const QUICK_LINKS = [ + { icon: 'mdi:calendar-check-outline', label: 'My Bookings', href: '/my/bookings', color: '#1877F2' }, + { icon: 'mdi:heart-outline', label: 'Saved Venues', href: '/my/favorites', color: '#E91E63' }, + { icon: 'mdi:magnify', label: 'Explore Venues', href: '/search', color: '#8E33FF' }, + { icon: 'mdi:headset', label: 'Help & Support', href: '/faq', color: '#22C55E' }, +]; + +export function ProfileView() { + const navigate = useNavigate(); + const { user, logout } = useAuth(); + + const [editMode, setEditMode] = useState(false); + const [name, setName] = useState(user?.name ?? ''); + const [saveSuccess, setSaveSuccess] = useState(false); + + const nameParts = name.trim().split(' '); + const firstName = nameParts[0] ?? ''; + const lastName = nameParts.slice(1).join(' ') ?? ''; + + const handleSave = () => { + setEditMode(false); + setSaveSuccess(true); + setTimeout(() => setSaveSuccess(false), 3000); + }; + + const handleLogout = () => { + logout(); + navigate('/'); + }; + + const userInitial = (user?.name ?? 'U').charAt(0).toUpperCase(); + + return ( + + {/* Header Banner */} + + + + + My Profile + + + Manage your account information and preferences + + + + + + + {/* Left: Profile Card */} + + + {/* Avatar Section */} + + + + {userInitial} + + + {user?.name} + {user?.email} + + + Verified Account + + + + + + {/* Quick Links */} + + {QUICK_LINKS.map((link) => ( + + navigate(link.href)} + sx={{ py: 1.5, px: 2.5, '&:hover': { bgcolor: 'action.hover' } }} + > + + + + + + + + + + ))} + + + + + + + + + + + {/* Right: Profile Details */} + + + {/* Personal Information */} + + + + Personal Information + Update your personal details + + + + + {saveSuccess && ( + + Profile updated successfully! + + )} + + + + setName(`${e.target.value} ${lastName}`)} + fullWidth + sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2.5 } }} + /> + + + setName(`${firstName} ${e.target.value}`)} + fullWidth + sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2.5 } }} + /> + + + + + + + + + + {editMode && ( + + )} + + + {/* Security */} + + Security + + Manage your password and account security + + + + + + + + Password + Last changed 3 months ago + + + + + + + + + Two-Factor Auth + Add extra layer of security + + + + + + + + {/* Danger Zone */} + + + + Danger Zone + + + Once you delete your account, all your data will be permanently removed. This action cannot be undone. + + + + + + + + + ); +} diff --git a/frontend/src/sections/user/search/index.tsx b/frontend/src/sections/user/search/index.tsx new file mode 100644 index 000000000..a98d22a2d --- /dev/null +++ b/frontend/src/sections/user/search/index.tsx @@ -0,0 +1,538 @@ +import type { VenueSearchFilters } from 'src/api/types/venue.type'; + +import { useState, useCallback } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { useSearchParams } from 'react-router-dom'; + +import { + Box, + Chip, + Grid, + Alert, + Stack, + Button, + Drawer, + Select, + Slider, + Divider, + MenuItem, + useTheme, + Container, + IconButton, + InputLabel, + Pagination, + Typography, + FormControl, + OutlinedInput, + useMediaQuery, + InputAdornment, +} from '@mui/material'; + +import { VenuePublicApiService } from 'src/api/venue-public'; + +import { Iconify } from 'src/components/iconify'; + +import { VenueSearchCard, VenueSearchCardSkeleton } from './venue-search-card'; + +const VENUE_TYPES = [ + { value: '', label: 'All Types' }, + { value: 'BANQUET_HALL', label: 'Banquet Hall' }, + { value: 'CONFERENCE_ROOM', label: 'Conference Room' }, + { value: 'MEETING_ROOM', label: 'Meeting Room' }, + { value: 'EVENT_SPACE', label: 'Event Space' }, + { value: 'RESTAURANT', label: 'Restaurant' }, + { value: 'HOTEL', label: 'Hotel' }, + { value: 'RESORT', label: 'Resort' }, + { value: 'PARTY_HALL', label: 'Party Hall' }, + { value: 'AUDITORIUM', label: 'Auditorium' }, + { value: 'CAFE', label: 'CafĂ©' }, +]; + +const SORT_OPTIONS = [ + { value: 'rating_desc', label: 'Top Rated' }, + { value: 'price_asc', label: 'Price: Low to High' }, + { value: 'price_desc', label: 'Price: High to Low' }, + { value: 'newest', label: 'Newest First' }, +]; + +const PRICE_RANGE_MAX = 500000; + +interface FilterState { + query: string; + city: string; + venueType: string; + priceRange: [number, number]; + minCapacity: number | ''; + sortBy: string; +} + +function FiltersPanel({ + filters, + onFiltersChange, + onApply, + onReset, +}: { + filters: FilterState; + onFiltersChange: (f: Partial) => void; + onApply: () => void; + onReset: () => void; +}) { + return ( + + + Filters + + + + + {/* Venue Type */} + + Venue Type + + + + {/* City */} + onFiltersChange({ city: e.target.value })} + startAdornment={ + + + + } + sx={{ borderRadius: 2 }} + /> + + + + {/* Price Range */} + + + Price Range (per day) + + onFiltersChange({ priceRange: val as [number, number] })} + min={0} + max={PRICE_RANGE_MAX} + step={1000} + valueLabelDisplay="auto" + valueLabelFormat={(v) => `â‚č${(v / 1000).toFixed(0)}K`} + sx={{ mx: 0.5 }} + /> + + + â‚č{filters.priceRange[0].toLocaleString('en-IN')} + + + â‚č{filters.priceRange[1].toLocaleString('en-IN')} + + + + + + + {/* Min Capacity */} + + + Minimum Capacity + + onFiltersChange({ minCapacity: e.target.value ? Number(e.target.value) : '' })} + inputProps={{ min: 1 }} + startAdornment={ + + + + } + sx={{ borderRadius: 2 }} + /> + + + + + + ); +} + +export function SearchView() { + const [searchParams] = useSearchParams(); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('md')); + + const [drawerOpen, setDrawerOpen] = useState(false); + const [page, setPage] = useState(1); + const [appliedFilters, setAppliedFilters] = useState({ + query: searchParams.get('query') ?? '', + city: searchParams.get('city') ?? '', + venueType: searchParams.get('venueType') ?? '', + minCapacity: searchParams.get('minCapacity') ? Number(searchParams.get('minCapacity')) : undefined, + sortBy: 'rating_desc', + }); + + const [localFilters, setLocalFilters] = useState({ + query: searchParams.get('query') ?? '', + city: searchParams.get('city') ?? '', + venueType: searchParams.get('venueType') ?? '', + priceRange: [0, PRICE_RANGE_MAX], + minCapacity: searchParams.get('minCapacity') ? Number(searchParams.get('minCapacity')) : '', + sortBy: 'rating_desc', + }); + + const { data, isLoading, isError } = useQuery({ + queryKey: ['venues', 'search', appliedFilters, page], + queryFn: () => + VenuePublicApiService.searchVenues({ + ...appliedFilters, + page, + limit: 12, + }), + staleTime: 30_000, + }); + + const handleApplyFilters = useCallback(() => { + setPage(1); + setAppliedFilters({ + query: localFilters.query, + city: localFilters.city, + venueType: localFilters.venueType || undefined, + minPrice: localFilters.priceRange[0] || undefined, + maxPrice: localFilters.priceRange[1] < PRICE_RANGE_MAX ? localFilters.priceRange[1] : undefined, + minCapacity: localFilters.minCapacity || undefined, + sortBy: localFilters.sortBy as VenueSearchFilters['sortBy'], + }); + setDrawerOpen(false); + }, [localFilters]); + + const handleReset = useCallback(() => { + const defaultFilters: FilterState = { + query: '', + city: '', + venueType: '', + priceRange: [0, PRICE_RANGE_MAX], + minCapacity: '', + sortBy: 'rating_desc', + }; + setLocalFilters(defaultFilters); + setAppliedFilters({ sortBy: 'rating_desc' }); + setPage(1); + }, []); + + const activeFilterCount = [ + appliedFilters.venueType, + appliedFilters.city, + appliedFilters.minPrice, + appliedFilters.maxPrice, + appliedFilters.minCapacity, + ].filter(Boolean).length; + + return ( + + {/* Top Search Bar */} + + + + {/* Search Input */} + setLocalFilters((f) => ({ ...f, query: e.target.value }))} + onKeyDown={(e) => e.key === 'Enter' && handleApplyFilters()} + startAdornment={ + + + + } + endAdornment={ + localFilters.query && ( + + setLocalFilters((f) => ({ ...f, query: '' }))}> + + + + ) + } + sx={{ flex: 1, borderRadius: 3, maxWidth: { sm: 400 } }} + /> + + {/* Sort Select */} + + + + + {/* Filter Toggle (mobile) / Search (desktop) */} + + {isMobile && ( + + )} + + + + + + + + + {/* Sidebar Filters (desktop) */} + {!isMobile && ( + + + setLocalFilters((f) => ({ ...f, ...update }))} + onApply={handleApplyFilters} + onReset={handleReset} + /> + + + )} + + {/* Results */} + + {/* Results Header */} + + + {isLoading ? ( + Searching... + ) : ( + + {data?.total ?? 0} venues found + {appliedFilters.query && ( + + {' '}for “{appliedFilters.query}” + + )} + + )} + + + {/* Active Filter Chips */} + + {appliedFilters.venueType && ( + t.value === appliedFilters.venueType)?.label} + size="small" + onDelete={() => { + setLocalFilters((f) => ({ ...f, venueType: '' })); + setAppliedFilters((f) => ({ ...f, venueType: undefined })); + }} + color="primary" + variant="outlined" + /> + )} + {appliedFilters.city && ( + { + setLocalFilters((f) => ({ ...f, city: '' })); + setAppliedFilters((f) => ({ ...f, city: undefined })); + }} + color="primary" + variant="outlined" + /> + )} + {appliedFilters.minCapacity && ( + { + setLocalFilters((f) => ({ ...f, minCapacity: '' })); + setAppliedFilters((f) => ({ ...f, minCapacity: undefined })); + }} + color="primary" + variant="outlined" + /> + )} + + + + {/* Error */} + {isError && ( + + Unable to load venues. Showing sample data. + + )} + + {/* Venue Grid */} + + {isLoading + ? Array.from({ length: 9 }).map((_, i) => ( + + + + )) + : (data?.data ?? []).map((venue) => ( + + + + )) + } + + + {/* Empty State */} + {!isLoading && !isError && data?.data?.length === 0 && ( + + + + No venues found + + + Try adjusting your filters or searching for a different location. + + + + )} + + {/* Pagination */} + {data && data.totalPages > 1 && ( + + { setPage(p); window.scrollTo({ top: 0, behavior: 'smooth' }); }} + color="primary" + shape="rounded" + size="large" + /> + + )} + + + + + {/* Mobile Filter Drawer */} + setDrawerOpen(false)} + PaperProps={{ + sx: { + borderRadius: '24px 24px 0 0', + maxHeight: '90vh', + overflow: 'auto', + }, + }} + > + + + setLocalFilters((f) => ({ ...f, ...update }))} + onApply={handleApplyFilters} + onReset={handleReset} + /> + + + + ); +} diff --git a/frontend/src/sections/user/search/venue-search-card.tsx b/frontend/src/sections/user/search/venue-search-card.tsx new file mode 100644 index 000000000..19e9dd3fa --- /dev/null +++ b/frontend/src/sections/user/search/venue-search-card.tsx @@ -0,0 +1,201 @@ +import type { VenueCard } from 'src/api/types/venue.type'; + +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { + Box, + Card, + Chip, + Stack, + Rating, + Tooltip, + Skeleton, + IconButton, + Typography, + CardContent, + CardActionArea, +} from '@mui/material'; + +import { useAuth } from 'src/context/auth/use-auth'; +import { VenuePublicApiService } from 'src/api/venue-public'; + +import { Iconify } from 'src/components/iconify'; + +interface VenueSearchCardProps { + venue: VenueCard; +} + +export function VenueSearchCard({ venue }: VenueSearchCardProps) { + const navigate = useNavigate(); + const { isAuthenticated } = useAuth(); + const queryClient = useQueryClient(); + const [saved, setSaved] = useState(venue.isSaved ?? false); + + const saveMutation = useMutation({ + mutationFn: () => + saved + ? VenuePublicApiService.unsaveVenue(venue.id) + : VenuePublicApiService.saveVenue(venue.id), + onSuccess: () => { + setSaved((prev) => !prev); + queryClient.invalidateQueries({ queryKey: ['saved-venues'] }); + }, + }); + + const handleSave = (e: React.MouseEvent) => { + e.stopPropagation(); + if (!isAuthenticated) { + navigate('/sign-in'); + return; + } + saveMutation.mutate(); + }; + + const VENUE_TYPE_LABELS: Record = { + BANQUET_HALL: 'Banquet Hall', + CONFERENCE_ROOM: 'Conference Room', + MEETING_ROOM: 'Meeting Room', + CAFE: 'CafĂ©', + RESTAURANT: 'Restaurant', + HOTEL: 'Hotel', + RESORT: 'Resort', + PARTY_HALL: 'Party Hall', + EVENT_SPACE: 'Event Space', + AUDITORIUM: 'Auditorium', + OTHER: 'Other', + }; + + return ( + + navigate(`/venues/${venue.id}`)}> + + + + {/* Type Badge */} + + + {/* Save Button */} + + + + + + + + + + {venue.title} + + + + + + {venue.city}, {venue.state} + + + + + + + {(venue.averageRating ?? 0).toFixed(1)} + + + ({venue.reviewCount ?? 0} reviews) + + + + + + + â‚č{venue.pricePerDay.toLocaleString('en-IN')} + + + {' '}/day + + + + + + + Up to {venue.capacity} + + + + + + + ); +} + +export function VenueSearchCardSkeleton() { + return ( + + + + + + + + + + + + + ); +} diff --git a/frontend/src/sections/user/table-empty-rows.tsx b/frontend/src/sections/user/table-empty-rows.tsx new file mode 100644 index 000000000..6bc9ee0ba --- /dev/null +++ b/frontend/src/sections/user/table-empty-rows.tsx @@ -0,0 +1,26 @@ +import type { TableRowProps } from '@mui/material/TableRow'; + +import TableRow from '@mui/material/TableRow'; +import TableCell from '@mui/material/TableCell'; + +// ---------------------------------------------------------------------- + +type TableEmptyRowsProps = TableRowProps & { + emptyRows: number; + height?: number; +}; + +export function TableEmptyRows({ emptyRows, height, sx, ...other }: TableEmptyRowsProps) { + if (!emptyRows) { + return null; + } + + return ( + + + + ); +} diff --git a/frontend/src/sections/user/table-no-data.tsx b/frontend/src/sections/user/table-no-data.tsx new file mode 100644 index 000000000..914e23f38 --- /dev/null +++ b/frontend/src/sections/user/table-no-data.tsx @@ -0,0 +1,32 @@ +import type { TableRowProps } from '@mui/material/TableRow'; + +import Box from '@mui/material/Box'; +import TableRow from '@mui/material/TableRow'; +import TableCell from '@mui/material/TableCell'; +import Typography from '@mui/material/Typography'; + +// ---------------------------------------------------------------------- + +type TableNoDataProps = TableRowProps & { + searchQuery: string; +}; + +export function TableNoData({ searchQuery, ...other }: TableNoDataProps) { + return ( + + + + + Not found + + + + No results found for   + "{searchQuery}". +
    Try checking for typos or using complete words. +
    +
    +
    +
    + ); +} diff --git a/frontend/src/sections/user/user-table-head.tsx b/frontend/src/sections/user/user-table-head.tsx new file mode 100644 index 000000000..3888ee712 --- /dev/null +++ b/frontend/src/sections/user/user-table-head.tsx @@ -0,0 +1,69 @@ +import Box from '@mui/material/Box'; +import TableRow from '@mui/material/TableRow'; +import Checkbox from '@mui/material/Checkbox'; +import TableHead from '@mui/material/TableHead'; +import TableCell from '@mui/material/TableCell'; +import TableSortLabel from '@mui/material/TableSortLabel'; + +import { visuallyHidden } from './utils'; + +// ---------------------------------------------------------------------- + +type UserTableHeadProps = { + orderBy: string; + rowCount: number; + numSelected: number; + order: 'asc' | 'desc'; + onSort: (id: string) => void; + headLabel: Record[]; + onSelectAllRows: (checked: boolean) => void; +}; + +export function UserTableHead({ + order, + onSort, + orderBy, + rowCount, + headLabel, + numSelected, + onSelectAllRows, +}: UserTableHeadProps) { + return ( + + + + 0 && numSelected < rowCount} + checked={rowCount > 0 && numSelected === rowCount} + onChange={(event: React.ChangeEvent) => + onSelectAllRows(event.target.checked) + } + /> + + + {headLabel.map((headCell) => ( + + onSort(headCell.id)} + > + {headCell.label} + {orderBy === headCell.id ? ( + + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + + ))} + + + ); +} diff --git a/frontend/src/sections/user/user-table-row.tsx b/frontend/src/sections/user/user-table-row.tsx new file mode 100644 index 000000000..542942807 --- /dev/null +++ b/frontend/src/sections/user/user-table-row.tsx @@ -0,0 +1,124 @@ +import { useState, useCallback } from 'react'; + +import Box from '@mui/material/Box'; +import Avatar from '@mui/material/Avatar'; +import Popover from '@mui/material/Popover'; +import TableRow from '@mui/material/TableRow'; +import Checkbox from '@mui/material/Checkbox'; +import MenuList from '@mui/material/MenuList'; +import TableCell from '@mui/material/TableCell'; +import IconButton from '@mui/material/IconButton'; +import MenuItem, { menuItemClasses } from '@mui/material/MenuItem'; + +import { Label } from 'src/components/label'; +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +export type UserProps = { + id: string; + name: string; + role: string; + status: string; + company: string; + avatarUrl: string; + isVerified: boolean; +}; + +type UserTableRowProps = { + row: UserProps; + selected: boolean; + onSelectRow: () => void; +}; + +export function UserTableRow({ row, selected, onSelectRow }: UserTableRowProps) { + const [openPopover, setOpenPopover] = useState(null); + + const handleOpenPopover = useCallback((event: React.MouseEvent) => { + setOpenPopover(event.currentTarget); + }, []); + + const handleClosePopover = useCallback(() => { + setOpenPopover(null); + }, []); + + return ( + <> + + + + + + + + + {row.name} + + + + {row.company} + + {row.role} + + + {row.isVerified ? ( + + ) : ( + '-' + )} + + + + + + + + + + + + + + + + + + Edit + + + + + Delete + + + + + ); +} diff --git a/frontend/src/sections/user/user-table-toolbar.tsx b/frontend/src/sections/user/user-table-toolbar.tsx new file mode 100644 index 000000000..55bee2fd1 --- /dev/null +++ b/frontend/src/sections/user/user-table-toolbar.tsx @@ -0,0 +1,66 @@ +import Tooltip from '@mui/material/Tooltip'; +import Toolbar from '@mui/material/Toolbar'; +import Typography from '@mui/material/Typography'; +import IconButton from '@mui/material/IconButton'; +import OutlinedInput from '@mui/material/OutlinedInput'; +import InputAdornment from '@mui/material/InputAdornment'; + +import { Iconify } from 'src/components/iconify'; + +// ---------------------------------------------------------------------- + +type UserTableToolbarProps = { + numSelected: number; + filterName: string; + onFilterName: (event: React.ChangeEvent) => void; +}; + +export function UserTableToolbar({ numSelected, filterName, onFilterName }: UserTableToolbarProps) { + return ( + theme.spacing(0, 1, 0, 3), + ...(numSelected > 0 && { + color: 'primary.main', + bgcolor: 'primary.lighter', + }), + }} + > + {numSelected > 0 ? ( + + {numSelected} selected + + ) : ( + + + + } + sx={{ maxWidth: 320 }} + /> + )} + + {numSelected > 0 ? ( + + + + + + ) : ( + + + + + + )} + + ); +} diff --git a/frontend/src/sections/user/utils.ts b/frontend/src/sections/user/utils.ts new file mode 100644 index 000000000..162e24daf --- /dev/null +++ b/frontend/src/sections/user/utils.ts @@ -0,0 +1,79 @@ +import type { UserProps } from './user-table-row'; + +// ---------------------------------------------------------------------- + +export const visuallyHidden = { + border: 0, + margin: -1, + padding: 0, + width: '1px', + height: '1px', + overflow: 'hidden', + position: 'absolute', + whiteSpace: 'nowrap', + clip: 'rect(0 0 0 0)', +} as const; + +// ---------------------------------------------------------------------- + +export function emptyRows(page: number, rowsPerPage: number, arrayLength: number) { + return page ? Math.max(0, (1 + page) * rowsPerPage - arrayLength) : 0; +} + +// ---------------------------------------------------------------------- + +function descendingComparator(a: T, b: T, orderBy: keyof T) { + if (b[orderBy] < a[orderBy]) { + return -1; + } + if (b[orderBy] > a[orderBy]) { + return 1; + } + return 0; +} + +// ---------------------------------------------------------------------- + +export function getComparator( + order: 'asc' | 'desc', + orderBy: Key +): ( + a: { + [key in Key]: number | string; + }, + b: { + [key in Key]: number | string; + } +) => number { + return order === 'desc' + ? (a, b) => descendingComparator(a, b, orderBy) + : (a, b) => -descendingComparator(a, b, orderBy); +} + +// ---------------------------------------------------------------------- + +type ApplyFilterProps = { + inputData: UserProps[]; + filterName: string; + comparator: (a: any, b: any) => number; +}; + +export function applyFilter({ inputData, comparator, filterName }: ApplyFilterProps) { + const stabilizedThis = inputData.map((el, index) => [el, index] as const); + + stabilizedThis.sort((a, b) => { + const order = comparator(a[0], b[0]); + if (order !== 0) return order; + return a[1] - b[1]; + }); + + inputData = stabilizedThis.map((el) => el[0]); + + if (filterName) { + inputData = inputData.filter( + (user) => user.name.toLowerCase().indexOf(filterName.toLowerCase()) !== -1 + ); + } + + return inputData; +} diff --git a/frontend/src/sections/user/venue-details/index.tsx b/frontend/src/sections/user/venue-details/index.tsx new file mode 100644 index 000000000..f103a0b2b --- /dev/null +++ b/frontend/src/sections/user/venue-details/index.tsx @@ -0,0 +1,351 @@ +import { useQuery } from '@tanstack/react-query'; +import { useParams, useNavigate } from 'react-router-dom'; + +import { + Box, + Chip, + Grid, + Stack, + Button, + Divider, + Skeleton, + Container, + Typography, + Breadcrumbs, +} from '@mui/material'; + +import { VenuePublicApiService } from 'src/api/venue-public'; + +import { Iconify } from 'src/components/iconify'; + +import { VenueReviews } from './venue-reviews'; +import { VenueAmenities } from './venue-amenities'; +import { VenueBookingCard } from './venue-booking-card'; +import { VenueImageGallery } from './venue-image-gallery'; + +const VENUE_TYPE_LABELS: Record = { + BANQUET_HALL: 'Banquet Hall', + CONFERENCE_ROOM: 'Conference Room', + MEETING_ROOM: 'Meeting Room', + CAFE: 'CafĂ©', + RESTAURANT: 'Restaurant', + HOTEL: 'Hotel', + RESORT: 'Resort', + PARTY_HALL: 'Party Hall', + EVENT_SPACE: 'Event Space', + AUDITORIUM: 'Auditorium', + OTHER: 'Other', +}; + +export function VenueDetailsView() { + const { venueId } = useParams<{ venueId: string }>(); + const navigate = useNavigate(); + + const { data: venue, isLoading, isError } = useQuery({ + queryKey: ['venue-details', venueId], + queryFn: () => VenuePublicApiService.getVenueDetails(venueId!), + enabled: !!venueId, + retry: 1, + }); + + if (isLoading) { + return ( + + + + + + + + + + + + + ); + } + + if (isError || !venue) { + return ( + + + + Venue Not Found + + + This venue may not exist or is temporarily unavailable. + + + + ); + } + + return ( + + {/* Breadcrumbs */} + + }> + navigate('/')} + sx={{ cursor: 'pointer', '&:hover': { color: 'primary.main' } }} + > + Home + + navigate('/search')} + sx={{ cursor: 'pointer', '&:hover': { color: 'primary.main' } }} + > + Venues + + + {venue.title} + + + + + {/* Gallery */} + + + + + + + {/* Left Column */} + + + {/* Title & Key Info */} + + + + {venue.status === 'APPROVED' && ( + } + label="Verified" + size="small" + sx={{ bgcolor: 'success.lighter', color: 'success.dark', border: 'none' }} + /> + )} + + + + {venue.title} + + + + + + + {venue.city ?? venue.address?.city}, {venue.state ?? venue.address?.state} + + + + + {(venue.averageRating ?? 0).toFixed(1)} + ({venue.reviewCount ?? 0} reviews) + + + + Up to {venue.capacity} guests + + + + + + + {/* Host Info */} + {venue.owner && ( + + + {venue.owner.firstName.charAt(0)} + + + + Hosted by {venue.owner.firstName} {venue.owner.lastName} + + + {venue.owner.email} + + + + )} + + + + {/* Key Stats */} + + {[ + { icon: 'mdi:account-group', label: 'Max Capacity', value: `${venue.capacity} guests` }, + { icon: 'mdi:cash', label: 'Price Per Day', value: `â‚č${venue.pricePerDay.toLocaleString('en-IN')}` }, + { icon: 'mdi:map-marker', label: 'Location', value: `${venue.city ?? venue.address?.city}, ${venue.state ?? venue.address?.state}` }, + { icon: 'mdi:domain', label: 'Venue Type', value: VENUE_TYPE_LABELS[venue.venueType] ?? venue.venueType }, + ].map((stat) => ( + + + + + {stat.label} + + + {stat.value} + + + + ))} + + + + + {/* Description */} + + + About this venue + + + {venue.description} + + + + + + {/* Address */} + + + Location + + + + + {venue.addressLine1 ?? venue.address?.addressLine1} + {(venue.address?.addressLine2) && `, ${venue.address.addressLine2}`} + {', '}{venue.city ?? venue.address?.city}, {venue.state ?? venue.address?.state} - {venue.postalCode ?? venue.address?.postalCode} + + + + {/* Map Placeholder */} + + + {venue.city ?? venue.address?.city}, {venue.state ?? venue.address?.state} + + + + + + {/* Amenities */} + + + {venue.amenities.length > 0 && } + + {/* Reviews */} + + + + + {/* Right Column - Booking Card */} + + + + + + {/* Mobile Sticky Bottom Bar */} + + + + â‚č{venue.pricePerDay.toLocaleString('en-IN')} + /day + + + + {(venue.averageRating ?? 0).toFixed(1)} + + + + + + + ); +} diff --git a/frontend/src/sections/user/venue-details/venue-amenities.tsx b/frontend/src/sections/user/venue-details/venue-amenities.tsx new file mode 100644 index 000000000..1386e9e7a --- /dev/null +++ b/frontend/src/sections/user/venue-details/venue-amenities.tsx @@ -0,0 +1,94 @@ +import { useState } from 'react'; + +import { + Box, + Grid, + Stack, + Button, + Typography, +} from '@mui/material'; + +import { Iconify } from 'src/components/iconify'; + +const AMENITY_ICONS: Record = { + wifi: 'mdi:wifi', + parking: 'mdi:parking', + ac: 'mdi:air-conditioner', + projector: 'mdi:projector', + catering: 'mdi:silverware-fork-knife', + sound: 'mdi:music', + stage: 'mdi:theater', + security: 'mdi:shield-check', + generator: 'mdi:lightning-bolt', + dressing: 'mdi:hanger', + pool: 'mdi:pool', + garden: 'mdi:tree', + elevator: 'mdi:elevator', + accessibility: 'mdi:wheelchair-accessibility', +}; + +function getAmenityIcon(name: string): string { + const lower = name?.toLowerCase(); + for (const [key, icon] of Object.entries(AMENITY_ICONS)) { + if (lower?.includes(key)) return icon; + } + return 'mdi:check-circle-outline'; +} + +interface VenueAmenitiesProps { + amenities: string[]; +} + +export function VenueAmenities({ amenities }: VenueAmenitiesProps) { + const [showAll, setShowAll] = useState(false); + const INITIAL_COUNT = 8; + const displayedAmenities = showAll ? amenities : amenities.slice(0, INITIAL_COUNT); + + if (amenities.length === 0) return null; + + return ( + + + What this venue offers + + + + {displayedAmenities.map((amenity, index) => ( + + + + + + {amenity} + + + ))} + + + {amenities.length > INITIAL_COUNT && ( + + )} + + ); +} diff --git a/frontend/src/sections/user/venue-details/venue-booking-card.tsx b/frontend/src/sections/user/venue-details/venue-booking-card.tsx new file mode 100644 index 000000000..e34bd1038 --- /dev/null +++ b/frontend/src/sections/user/venue-details/venue-booking-card.tsx @@ -0,0 +1,262 @@ +import type { VenueDetails } from 'src/api/types/venue.type'; + +import dayjs from 'dayjs'; +import { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; + +import { + Box, + Chip, + Alert, + Paper, + Stack, + Button, + Rating, + Slider, + Divider, + Typography, +} from '@mui/material'; + +import { useAuth } from 'src/context/auth/use-auth'; + +import { Iconify } from 'src/components/iconify'; + +interface VenueBookingCardProps { + venue: VenueDetails; +} + +export function VenueBookingCard({ venue }: VenueBookingCardProps) { + const navigate = useNavigate(); + const { isAuthenticated } = useAuth(); + const [startDate, setStartDate] = useState(''); + const [endDate, setEndDate] = useState(''); + const [guests, setGuests] = useState(10); + + const nights = + startDate && endDate + ? Math.max(1, dayjs(endDate).diff(dayjs(startDate), 'day')) + : 0; + + const baseAmount = nights * venue.pricePerDay; + const serviceFee = Math.round(baseAmount * 0.1); + const total = baseAmount + serviceFee; + + const handleBook = () => { + if (!isAuthenticated) { + navigate('/sign-in'); + return; + } + const params = new URLSearchParams(); + if (startDate) params.set('startDate', startDate); + if (endDate) params.set('endDate', endDate); + params.set('guests', String(guests)); + navigate(`/booking/${venue.id}?${params.toString()}`); + }; + + const today = dayjs().format('YYYY-MM-DD'); + + return ( + + {/* Price */} + + + â‚č{venue.pricePerDay.toLocaleString('en-IN')} + + /day + + + {/* Rating */} + + + {(venue.averageRating ?? 0).toFixed(1)} + · {venue.reviewCount ?? 0} reviews + + + {/* Date Inputs */} + + + + + + CHECK-IN + + { + setStartDate(e.target.value); + if (endDate && e.target.value >= endDate) setEndDate(''); + }} + sx={{ + border: 'none', + outline: 'none', + width: '100%', + fontSize: 14, + fontWeight: 600, + cursor: 'pointer', + bgcolor: 'transparent', + color: 'text.primary', + fontFamily: 'inherit', + }} + /> + + + + CHECK-OUT + + setEndDate(e.target.value)} + sx={{ + border: 'none', + outline: 'none', + width: '100%', + fontSize: 14, + fontWeight: 600, + cursor: 'pointer', + bgcolor: 'transparent', + color: 'text.primary', + fontFamily: 'inherit', + }} + /> + + + + + {/* Guests */} + + + + GUESTS + + } + label={`${guests} guests`} + size="small" + color="primary" + variant="outlined" + /> + + setGuests(v as number)} + min={1} + max={venue.capacity} + step={1} + size="small" + sx={{ mx: 0.5 }} + /> + + 1 + {venue.capacity} max + + + + + {/* Book Button */} + + + {!isAuthenticated && ( + + Create a free account to book this venue + + )} + + {/* Price Breakdown */} + {nights > 0 && ( + <> + + + + + â‚č{venue.pricePerDay.toLocaleString('en-IN')} × {nights} day{nights !== 1 ? 's' : ''} + + + â‚č{baseAmount.toLocaleString('en-IN')} + + + + Service fee (10%) + â‚č{serviceFee.toLocaleString('en-IN')} + + + + Total + + â‚č{total.toLocaleString('en-IN')} + + + + + )} + + {/* Trust Badges */} + + + {[ + { icon: 'mdi:shield-check', text: 'Verified venue' }, + { icon: 'mdi:lock-check', text: 'Secure payment' }, + { icon: 'mdi:calendar-remove', text: 'Free cancellation (48hr)' }, + ].map((item) => ( + + + {item.text} + + ))} + + + ); +} diff --git a/frontend/src/sections/user/venue-details/venue-image-gallery.tsx b/frontend/src/sections/user/venue-details/venue-image-gallery.tsx new file mode 100644 index 000000000..b51270c14 --- /dev/null +++ b/frontend/src/sections/user/venue-details/venue-image-gallery.tsx @@ -0,0 +1,278 @@ +import { useState } from 'react'; + +import { + Box, + Grid, + Stack, + Dialog, + IconButton, + Typography, + DialogContent, +} from '@mui/material'; + +import { Iconify } from 'src/components/iconify'; + +interface VenueImageGalleryProps { + images: string[]; + title: string; +} + +const FALLBACK_IMAGES = [ + 'https://images.unsplash.com/photo-1519167758481-83f550bb49b3?w=900&q=80', + 'https://images.unsplash.com/photo-1464366400600-7168b8af9bc3?w=900&q=80', + 'https://images.unsplash.com/photo-1497366216548-37526070297c?w=900&q=80', + 'https://images.unsplash.com/photo-1511795409834-ef04bbd61622?w=900&q=80', + 'https://images.unsplash.com/photo-1414235077428-338989a2e8c0?w=900&q=80', +]; + +export function VenueImageGallery({ images, title }: VenueImageGalleryProps) { + const [lightboxOpen, setLightboxOpen] = useState(false); + const [activeIndex, setActiveIndex] = useState(0); + + const galleryImages = + images.length > 0 + ? images + : FALLBACK_IMAGES; + + const openLightbox = (index: number) => { + setActiveIndex(index); + setLightboxOpen(true); + }; + + const prev = () => setActiveIndex((i) => (i - 1 + galleryImages.length) % galleryImages.length); + const next = () => setActiveIndex((i) => (i + 1) % galleryImages.length); + + return ( + <> + {/* Gallery Grid */} + + + {/* Main Image */} + + openLightbox(0)} + sx={{ + height: '100%', + backgroundImage: `url(${galleryImages[0]})`, + backgroundSize: 'cover', + backgroundPosition: 'center', + cursor: 'pointer', + transition: 'filter 0.2s', + '&:hover': { filter: 'brightness(0.92)' }, + }} + /> + + + {/* Side Images */} + + + {galleryImages.slice(1, 3).map((img, i) => ( + openLightbox(i + 1)} + sx={{ + flex: 1, + backgroundImage: `url(${img})`, + backgroundSize: 'cover', + backgroundPosition: 'center', + cursor: 'pointer', + position: 'relative', + transition: 'filter 0.2s', + '&:hover': { filter: 'brightness(0.88)' }, + }} + > + {i === 1 && galleryImages.length > 3 && ( + { e.stopPropagation(); openLightbox(3); }} + sx={{ + position: 'absolute', + inset: 0, + bgcolor: 'rgba(0,0,0,0.45)', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + cursor: 'pointer', + '&:hover': { bgcolor: 'rgba(0,0,0,0.55)' }, + }} + > + + + + +{galleryImages.length - 3} more + + + + )} + + ))} + + + + + {/* Mobile Show All Button */} + + openLightbox(0)} + sx={{ + display: 'flex', + alignItems: 'center', + gap: 1, + bgcolor: 'rgba(255,255,255,0.92)', + backdropFilter: 'blur(8px)', + borderRadius: 2, + px: 2, + py: 1, + cursor: 'pointer', + fontWeight: 700, + fontSize: 13, + }} + > + + All Photos + + + + + {/* Lightbox Dialog */} + setLightboxOpen(false)} + maxWidth="lg" + fullWidth + PaperProps={{ + sx: { + bgcolor: 'rgba(0,0,0,0.95)', + borderRadius: 3, + m: { xs: 0, md: 4 }, + maxHeight: '95vh', + }, + }} + > + + {/* Close Button */} + setLightboxOpen(false)} + sx={{ + position: 'absolute', + top: 16, + right: 16, + zIndex: 10, + bgcolor: 'rgba(0,0,0,0.5)', + color: 'white', + '&:hover': { bgcolor: 'rgba(0,0,0,0.7)' }, + }} + > + + + + {/* Counter */} + + {activeIndex + 1} / {galleryImages.length} + + + {/* Main Image */} + + + {/* Navigation */} + + + + + + + + {/* Thumbnails */} + + {galleryImages.map((img, i) => ( + setActiveIndex(i)} + sx={{ + width: 64, + height: 48, + flexShrink: 0, + borderRadius: 1.5, + overflow: 'hidden', + border: i === activeIndex ? '2.5px solid white' : '2px solid transparent', + cursor: 'pointer', + opacity: i === activeIndex ? 1 : 0.6, + transition: 'all 0.2s', + '&:hover': { opacity: 0.9 }, + }} + > + + + ))} + + + + + ); +} diff --git a/frontend/src/sections/user/venue-details/venue-reviews.tsx b/frontend/src/sections/user/venue-details/venue-reviews.tsx new file mode 100644 index 000000000..03c0a9a4f --- /dev/null +++ b/frontend/src/sections/user/venue-details/venue-reviews.tsx @@ -0,0 +1,148 @@ +import type { VenueReview } from 'src/api/types/venue.type'; + +import dayjs from 'dayjs'; +import { useState } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import relativeTime from 'dayjs/plugin/relativeTime'; + +import { + Box, + Stack, + Avatar, + Button, + Rating, + Divider, + Skeleton, + Typography, +} from '@mui/material'; + +import { VenuePublicApiService } from 'src/api/venue-public'; + +import { Iconify } from 'src/components/iconify'; + +dayjs.extend(relativeTime); + +interface VenueReviewsProps { + venueId: string; + averageRating: number; + reviewCount: number; +} + +function ReviewCard({ review }: { review: VenueReview }) { + const initials = `${review.user.firstName.charAt(0)}${review.user.lastName?.charAt(0) ?? ''}`.toUpperCase(); + + return ( + + + + {initials} + + + + + + {review.user.firstName} {review.user.lastName} + + + {dayjs(review.createdAt).fromNow()} + + + + + {review.comment && ( + + {review.comment} + + )} + + + + ); +} + +function ReviewSkeleton() { + return ( + + + + + + + + + ); +} + +export function VenueReviews({ venueId, averageRating, reviewCount }: VenueReviewsProps) { + const [page, setPage] = useState(1); + + const { data, isLoading } = useQuery({ + queryKey: ['venue-reviews', venueId, page], + queryFn: () => VenuePublicApiService.getVenueReviews(venueId, page), + retry: false, + }); + + const RATING_BARS = [5, 4, 3, 2, 1]; + + if (reviewCount === 0) return null; + + return ( + + + ★ + {' '}{averageRating?.toFixed(1)} · {reviewCount} reviews + + + {/* Rating Breakdown */} + + {RATING_BARS.map((star) => ( + + {star} + + + + + + ))} + + + + + {/* Reviews */} + }> + {isLoading + ? Array.from({ length: 4 }).map((_, i) => ) + : (data?.data ?? []).map((review) => ( + + )) + } + + + {data && data.totalPages > 1 && ( + + )} + + ); +} diff --git a/frontend/src/sections/user/view/index.ts b/frontend/src/sections/user/view/index.ts new file mode 100644 index 000000000..9116ca733 --- /dev/null +++ b/frontend/src/sections/user/view/index.ts @@ -0,0 +1 @@ +export * from './user-view'; diff --git a/frontend/src/sections/user/view/user-view.tsx b/frontend/src/sections/user/view/user-view.tsx new file mode 100644 index 000000000..749d4a2e0 --- /dev/null +++ b/frontend/src/sections/user/view/user-view.tsx @@ -0,0 +1,203 @@ +import { useState, useCallback } from 'react'; + +import Box from '@mui/material/Box'; +import Card from '@mui/material/Card'; +import Table from '@mui/material/Table'; +import Button from '@mui/material/Button'; +import TableBody from '@mui/material/TableBody'; +import Typography from '@mui/material/Typography'; +import TableContainer from '@mui/material/TableContainer'; +import TablePagination from '@mui/material/TablePagination'; + +import { _users } from 'src/_mock'; +import { DashboardContent } from 'src/layouts/dashboard'; + +import { Iconify } from 'src/components/iconify'; +import { Scrollbar } from 'src/components/scrollbar'; + +import { TableNoData } from '../table-no-data'; +import { UserTableRow } from '../user-table-row'; +import { UserTableHead } from '../user-table-head'; +import { TableEmptyRows } from '../table-empty-rows'; +import { UserTableToolbar } from '../user-table-toolbar'; +import { emptyRows, applyFilter, getComparator } from '../utils'; + +import type { UserProps } from '../user-table-row'; + +// ---------------------------------------------------------------------- + +export function UserView() { + const table = useTable(); + + const [filterName, setFilterName] = useState(''); + + const dataFiltered: UserProps[] = applyFilter({ + inputData: _users, + comparator: getComparator(table.order, table.orderBy), + filterName, + }); + + const notFound = !dataFiltered.length && !!filterName; + + return ( + + + + Users + + + + + + ) => { + setFilterName(event.target.value); + table.onResetPage(); + }} + /> + + + + + + table.onSelectAllRows( + checked, + _users.map((user) => user.id) + ) + } + headLabel={[ + { id: 'name', label: 'Name' }, + { id: 'company', label: 'Company' }, + { id: 'role', label: 'Role' }, + { id: 'isVerified', label: 'Verified', align: 'center' }, + { id: 'status', label: 'Status' }, + { id: '' }, + ]} + /> + + {dataFiltered + .slice( + table.page * table.rowsPerPage, + table.page * table.rowsPerPage + table.rowsPerPage + ) + .map((row) => ( + table.onSelectRow(row.id)} + /> + ))} + + + + {notFound && } + +
    +
    +
    + + +
    +
    + ); +} + +// ---------------------------------------------------------------------- + +export function useTable() { + const [page, setPage] = useState(0); + const [orderBy, setOrderBy] = useState('name'); + const [rowsPerPage, setRowsPerPage] = useState(5); + const [selected, setSelected] = useState([]); + const [order, setOrder] = useState<'asc' | 'desc'>('asc'); + + const onSort = useCallback( + (id: string) => { + const isAsc = orderBy === id && order === 'asc'; + setOrder(isAsc ? 'desc' : 'asc'); + setOrderBy(id); + }, + [order, orderBy] + ); + + const onSelectAllRows = useCallback((checked: boolean, newSelecteds: string[]) => { + if (checked) { + setSelected(newSelecteds); + return; + } + setSelected([]); + }, []); + + const onSelectRow = useCallback( + (inputValue: string) => { + const newSelected = selected.includes(inputValue) + ? selected.filter((value) => value !== inputValue) + : [...selected, inputValue]; + + setSelected(newSelected); + }, + [selected] + ); + + const onResetPage = useCallback(() => { + setPage(0); + }, []); + + const onChangePage = useCallback((event: unknown, newPage: number) => { + setPage(newPage); + }, []); + + const onChangeRowsPerPage = useCallback( + (event: React.ChangeEvent) => { + setRowsPerPage(parseInt(event.target.value, 10)); + onResetPage(); + }, + [onResetPage] + ); + + return { + page, + order, + onSort, + orderBy, + selected, + rowsPerPage, + onSelectRow, + onResetPage, + onChangePage, + onSelectAllRows, + onChangeRowsPerPage, + }; +} diff --git a/frontend/src/sections/venue-owner/booking/details.tsx b/frontend/src/sections/venue-owner/booking/details.tsx new file mode 100644 index 000000000..5078c3c1a --- /dev/null +++ b/frontend/src/sections/venue-owner/booking/details.tsx @@ -0,0 +1,276 @@ +import { useParams } from 'react-router'; +import { useQuery } from '@tanstack/react-query'; + +import LoadingButton from '@mui/lab/LoadingButton'; +import { + Box, + Grid, + Card, + Chip, + Stack, + Avatar, + Divider, + Typography, + CardHeader, + CardContent, +} from '@mui/material'; + +import { BookingApiService } from 'src/api/booking'; +import { DashboardContent } from 'src/layouts/dashboard'; + + +export function BookingDetails() { + const { bookingId } = useParams(); + + const { data, isLoading } = useQuery({ + queryKey: ['booking', bookingId], + queryFn: () => + BookingApiService.getBookingDetailsForOwner( + bookingId! + ), + }); + + if (isLoading || !data) { + return null; + } + + + return ( + + + + + + Booking + + #{data?.id.toUpperCase()} + +
    } + action={ + + } + /> + + + + + + + + + + + + + + + + + + + Confirm Booking + + + + Cancel Booking + + + + + + + + + + ); +} + +function PaymentInfo({ data }: { data: any }) { + + return ( + + + + + + + Venue Fee + + + + â‚č + { + data?.totalAmount + } + + + + + + Platform Fee + + + + â‚č + { + data?.platformFee + } + + + + + + Tax + + + + â‚č + { + data?.taxAmount + } + + + + + + + + Total {data.totalAmount} + + + + â‚č + { + data?.grandTotal + } + + + + + + ) +} + +function VenueInfo({ data }: { data: any }) { + + return ( + + + Venue Information + + + + + + {data?.venue.title} + + + {data?.venue.address || 'some address near some place, some district and some state'} + + + + + ) +} + +function BookingInfo({ data }: { data: any }) { + + return ( + + + Booking Information + + + + + Start Date: + {' '} + { + new Date(data?.startDate).toDateString() + } + + + + End Date: + {' '} + { + new Date(data?.endDate).toDateString() + } + + + + ) +} + + +function CustomerInfo({ data }: { data: any }) { + + return ( + + + Customer Information + + + + Customer Name:{data?.user.firstName} {data?.user.lastName} + + + Customer Email: {data?.user.email} + + + Customer Phone {data?.user.phone} + + + + ) +} \ No newline at end of file diff --git a/frontend/src/sections/venue-owner/booking/list.tsx b/frontend/src/sections/venue-owner/booking/list.tsx new file mode 100644 index 000000000..e62906539 --- /dev/null +++ b/frontend/src/sections/venue-owner/booking/list.tsx @@ -0,0 +1,89 @@ +import { Link } from "react-router-dom"; + +import { Tooltip } from "@mui/material"; + +import { BookingApiService } from "src/api/booking"; +import { PaymentStatus } from "src/api/types/payment.type"; + +import { Label } from "src/components/label"; +import { Iconify } from "src/components/iconify"; +import { DataTable } from "src/components/data-table"; + + +export function ListBookings() { + + + return ( + {data.venue.title} + }, + }, + { + id: 'startDate', + label: 'Start Date', + component(data) { + return <>{new Date(data.startDate).toLocaleDateString()} + }, + }, + { + id: 'endDate', + label: 'End Date', + component(data) { + return <>{new Date(data.endDate).toLocaleDateString()} + }, + }, + { id: 'guestsCount', label: 'Guest count' }, + { id: 'totalAmount', label: 'Total Amount' }, + { + id: 'status', + label: "Status", + component(data) { + return + }, + }, + { + id: 'paymentStatus', + label: 'Payment Status', + component(data) { + const colorMap: Record = { + [PaymentStatus.PENDING]: 'warning', + [PaymentStatus.INITIATED]: 'info', + [PaymentStatus.PAID]: 'success', + [PaymentStatus.FAILED]: 'error', + [PaymentStatus.REFUNDED]: 'default', + } + + return ( + + ) + }, + }, + { + id: 'action', + label: 'Action', + component(data) { + return ( + + + + + + ) + }, + }, + ]} + /> + ) +} \ No newline at end of file diff --git a/frontend/src/sections/venue-owner/venues/create/index.tsx b/frontend/src/sections/venue-owner/venues/create/index.tsx new file mode 100644 index 000000000..c1a340a28 --- /dev/null +++ b/frontend/src/sections/venue-owner/venues/create/index.tsx @@ -0,0 +1,425 @@ +import { useRef, useState } from 'react'; +import { useMutation } from '@tanstack/react-query'; +import { useForm, Controller } from 'react-hook-form'; + +import LoadingButton from '@mui/lab/LoadingButton'; +import { + Box, + Card, + Grid, + Stack, + Alert, + Button, + MenuItem, + TextField, + CardHeader, + Typography, + CardContent, +} from '@mui/material'; + +import { VenueApiService } from 'src/api/venue'; +import { DashboardContent } from 'src/layouts/dashboard'; + +import { Iconify } from 'src/components/iconify'; + +export interface CreateVenueFormValues { + title: string; + description: string; + venueType: string; + + addressLine1: string; + city: string; + state: string; + country: string; + postalCode: string; + + latitude?: number; + longitude?: number; + + capacity: number; + pricePerDay: number; + + amenityIds: string[]; +} + +const DEFAULT_VALUES: CreateVenueFormValues = { + title: '', + description: '', + venueType: '', + addressLine1: '', + city: '', + state: '', + country: '', + postalCode: '', + capacity: 0, + pricePerDay: 0, + amenityIds: [], +}; + +const venueTypes = [ + 'HOTEL', + 'AUDITORIUM', + 'BANQUET_HALL', + 'RESORT', + 'CAFE', + 'MEETING_ROOM', +]; + +export function CreateVenueForm() { + const fileInputRef = useRef(null); + const [imageFiles, setImageFiles] = useState([]); + const [imageError, setImageError] = useState(''); + const [successMessage, setSuccessMessage] = useState(''); + + const { + control, + register, + reset, + handleSubmit, + formState: { errors }, + } = useForm({ + defaultValues: DEFAULT_VALUES, + }); + + const { mutateAsync, isPending } = useMutation({ + mutationFn: async ({ + venueData, + files, + }: { + venueData: Record; + files: File[]; + }) => { + const result = await VenueApiService.createVenue(venueData); + + if (files.length > 0) { + await VenueApiService.uploadVenueImages(result.venueId, files); + } + + return result; + }, + }); + + const onSubmit = async (data: CreateVenueFormValues) => { + setSuccessMessage(''); + + if (imageFiles.length === 0) { + setImageError('At least one image is required'); + return; + } + + const { amenityIds, ...rest } = data; + + await mutateAsync({ + venueData: { + ...rest, + amenities: amenityIds, + }, + files: imageFiles, + }); + + reset(DEFAULT_VALUES); + setImageFiles([]); + setImageError(''); + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + setSuccessMessage('Venue created successfully.'); + }; + + const handleFileChange = (event: React.ChangeEvent) => { + const selected = event.target.files; + if (!selected?.length) return; + + const nextFiles = [...imageFiles, ...Array.from(selected)].slice(0, 10); + setImageFiles(nextFiles); + setImageError(''); + event.target.value = ''; + }; + + const removeImage = (index: number) => { + setImageFiles((prev) => { + const next = prev.filter((_, i) => i !== index); + if (next.length === 0) { + setImageError('At least one image is required'); + } + return next; + }); + }; + + return ( + +
    + {successMessage && ( + + {successMessage} + + )} + + + + + + + + + + + + + ( + + {venueTypes.map((type) => ( + + {type.replace(/_/g, ' ')} + + ))} + + )} + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + At least 1 image required · up to 10 (JPG, PNG, WEBP) + + + {imageError && ( + + {imageError} + + )} + + {imageFiles.map((file, index) => ( + + + + + {file.name} + + + + + + ))} + + + + + + + + Create Venue + + + + + +
    +
    + ); +} diff --git a/frontend/src/sections/venue-owner/venues/list/index.tsx b/frontend/src/sections/venue-owner/venues/list/index.tsx new file mode 100644 index 000000000..3f11db9b7 --- /dev/null +++ b/frontend/src/sections/venue-owner/venues/list/index.tsx @@ -0,0 +1,58 @@ +import { VenueApiService } from "src/api/venue"; + +import { Label } from "src/components/label"; +import { DataTable } from "src/components/data-table"; + + +export function ListVenues() { + + + return ( + + {data.title} + <>{data.title} + + ) + }, + }, + { + id: 'venueType', + label: 'Venue Type', + component(data) { + return <>{data.venueType} + }, + }, + { + id: 'address', + label: 'Address', + component(data) { + return <>{data.addressLine1} + }, + }, + { + id: 'status', + label: "Status", + component(data) { + return + }, + }, + ]} + /> + ) +} \ No newline at end of file diff --git a/frontend/src/sections/venue-owner/view/dashboard.tsx b/frontend/src/sections/venue-owner/view/dashboard.tsx new file mode 100644 index 000000000..cb9decdcb --- /dev/null +++ b/frontend/src/sections/venue-owner/view/dashboard.tsx @@ -0,0 +1,306 @@ +import dayjs from 'dayjs'; +import { useNavigate } from 'react-router-dom'; +import { useQuery } from '@tanstack/react-query'; + +import { + Box, + Card, + Grid, + Stack, + Table, + Button, + Divider, + TableRow, + TableBody, + TableCell, + TableHead, + Typography, + CardContent, + TableContainer, + CircularProgress, +} from '@mui/material'; + +import { DashboardApiService } from 'src/api/dashboard'; +import { DashboardContent } from 'src/layouts/dashboard'; + +import { Iconify } from 'src/components/iconify'; +import { BlueButton } from 'src/components/buttons/blue-button'; + +// ─── Stat card ──────────────────────────────────────────────────────────────── + +function StatCard({ + label, + value, + icon, + color, + sub, +}: { + label: string; + value: string | number; + icon: string; + color: string; + sub?: string; +}) { + return ( + + + + + + {label} + + + {value} + + {sub && ( + + {sub} + + )} + + + + + + + + ); +} + +// ─── Main component ──────────────────────────────────────────────────────────── + +export function OwnerDashboard() { + const navigate = useNavigate(); + + const { data, isLoading } = useQuery({ + queryKey: ['owner-dashboard'], + queryFn: DashboardApiService.getOwnerDashboard, + retry: false, + }); + + const avgRevenuePerBooking = + data && data.bookingCount > 0 + ? Math.round(data.totalRevenue / data.bookingCount) + : 0; + + return ( + + {/* Header */} + + + Owner Dashboard + + Welcome back — {dayjs().format('dddd, D MMMM YYYY')} + + + + + + {isLoading ? ( + + + + ) : ( + <> + {/* Stat cards */} + + {[ + { + label: 'My Venues', + value: data?.venueCount ?? 0, + icon: 'mdi:domain', + color: 'primary', + sub: 'Active listings', + }, + { + label: 'Total Bookings', + value: data?.bookingCount ?? 0, + icon: 'mdi:calendar-check', + color: 'info', + sub: 'All time', + }, + { + label: 'Total Revenue', + value: `â‚č${(data?.totalRevenue ?? 0).toLocaleString('en-IN')}`, + icon: 'mdi:cash-multiple', + color: 'success', + sub: 'All time earnings', + }, + { + label: 'Avg. Per Booking', + value: `â‚č${avgRevenuePerBooking.toLocaleString('en-IN')}`, + icon: 'mdi:trending-up', + color: 'warning', + sub: 'Average booking value', + }, + ].map((s) => ( + + + + ))} + + + {/* Recent Bookings */} + + + + Recent Bookings + + Latest activity across your venues + + + + + + + {(data?.recentBookings?.length ?? 0) === 0 ? ( + + + + No bookings yet + + + Bookings will appear here once guests start reserving + + + ) : ( + + + + + Venue + Check-in + Check-out + Duration + Guests + Amount + Action + + + + {data?.recentBookings.map((booking) => { + const nights = Math.max( + 1, + dayjs(booking.endDate).diff(dayjs(booking.startDate), 'day'), + ); + return ( + + + + {booking.venueName} + + + + + {dayjs(booking.startDate).format('DD MMM YYYY')} + + + + + {dayjs(booking.endDate).format('DD MMM YYYY')} + + + + + {nights} day{nights !== 1 ? 's' : ''} + + + + {booking.guestsCount} + + + + â‚č{(booking.amount ?? 0).toLocaleString('en-IN')} + + + + + + + ); + })} + +
    +
    + )} +
    + + {/* Quick links */} + + {[ + { label: 'My Venues', sub: 'Manage your listings', icon: 'mdi:domain', path: '/owner/venues', color: 'primary' }, + { label: 'All Bookings', sub: 'View full booking history', icon: 'mdi:calendar-check', path: '/owner/bookings', color: 'info' }, + { label: 'Create Venue', sub: 'List a new venue', icon: 'mdi:plus-circle', path: '/owner/venues/create', color: 'success' }, + ].map((item) => ( + + navigate(item.path)} + sx={{ + border: '1.5px solid', + borderColor: 'divider', + borderRadius: 3, + p: 2.5, + cursor: 'pointer', + transition: 'all 0.2s', + '&:hover': { + borderColor: `${item.color}.main`, + boxShadow: '0 4px 20px rgba(0,0,0,0.08)', + }, + }} + > + + + + + + {item.label} + {item.sub} + + + + + + ))} + + + )} +
    + ); +} diff --git a/frontend/src/theme/core/components.tsx b/frontend/src/theme/core/components.tsx new file mode 100644 index 000000000..241b16ac8 --- /dev/null +++ b/frontend/src/theme/core/components.tsx @@ -0,0 +1,171 @@ +import type { Theme, Components } from '@mui/material/styles'; + +import { varAlpha } from 'minimal-shared/utils'; + +import SvgIcon from '@mui/material/SvgIcon'; + +// ---------------------------------------------------------------------- + +const MuiBackdrop: Components['MuiBackdrop'] = { + styleOverrides: { + root: ({ theme }) => ({ + backgroundColor: varAlpha(theme.vars.palette.grey['900Channel'], 0.8), + }), + invisible: { + background: 'transparent', + }, + }, +}; + +const MuiButton: Components['MuiButton'] = { + defaultProps: { + disableElevation: true, + }, + styleOverrides: { + containedInherit: ({ theme }) => ({ + color: theme.vars.palette.common.white, + backgroundColor: theme.vars.palette.grey[800], + '&:hover': { + color: theme.vars.palette.common.white, + backgroundColor: theme.vars.palette.grey[800], + }, + }), + sizeLarge: { + minHeight: 48, + }, + }, +}; + +const MuiCard: Components['MuiCard'] = { + styleOverrides: { + root: ({ theme }) => ({ + zIndex: 0, + position: 'relative', + boxShadow: theme.vars.customShadows.card, + borderRadius: theme.shape.borderRadius * 2, + }), + }, +}; + +const MuiCardHeader: Components['MuiCardHeader'] = { + defaultProps: { + titleTypographyProps: { variant: 'h6' }, + subheaderTypographyProps: { variant: 'body2' }, + }, + styleOverrides: { + root: ({ theme }) => ({ + padding: theme.spacing(3, 3, 0), + }), + }, +}; + +const MuiOutlinedInput: Components['MuiOutlinedInput'] = { + styleOverrides: { + notchedOutline: ({ theme }) => ({ + borderColor: varAlpha(theme.vars.palette.grey['500Channel'], 0.2), + }), + }, +}; + +const MuiPaper: Components['MuiPaper'] = { + defaultProps: { elevation: 0 }, + styleOverrides: { + root: { backgroundImage: 'none' }, + outlined: ({ theme }) => ({ + borderColor: varAlpha(theme.vars.palette.grey['500Channel'], 0.16), + }), + }, +}; + +const MuiTableCell: Components['MuiTableCell'] = { + styleOverrides: { + head: ({ theme }) => ({ + fontSize: theme.typography.pxToRem(14), + color: theme.vars.palette.text.secondary, + fontWeight: theme.typography.fontWeightSemiBold, + backgroundColor: theme.vars.palette.background.neutral, + }), + }, +}; + +const MuiMenuItem: Components['MuiMenuItem'] = { + styleOverrides: { + root: ({ theme }) => ({ + ...theme.typography.body2, + }), + }, +}; + +const MuiLink: Components['MuiLink'] = { + defaultProps: { underline: 'hover' }, +}; + +const MuiFormControlLabel: Components['MuiFormControlLabel'] = { + styleOverrides: { + label: ({ theme }) => ({ + ...theme.typography.body2, + }), + }, +}; + +const MuiCheckbox: Components['MuiCheckbox'] = { + defaultProps: { + size: 'small', + icon: ( + + + + ), + checkedIcon: ( + + + + ), + indeterminateIcon: ( + + + + ), + }, +}; + +const MuiRadio: Components['MuiRadio'] = { + defaultProps: { + size: 'small', + icon: ( + + + + ), + checkedIcon: ( + + + + ), + }, +}; + +// ---------------------------------------------------------------------- + +export const components = { + MuiCard, + MuiLink, + MuiPaper, + MuiRadio, + MuiButton, + MuiBackdrop, + MuiMenuItem, + MuiCheckbox, + MuiTableCell, + MuiCardHeader, + MuiOutlinedInput, + MuiFormControlLabel, +}; diff --git a/frontend/src/theme/core/custom-shadows.ts b/frontend/src/theme/core/custom-shadows.ts new file mode 100644 index 000000000..ec3c80525 --- /dev/null +++ b/frontend/src/theme/core/custom-shadows.ts @@ -0,0 +1,64 @@ +import { varAlpha } from 'minimal-shared/utils'; + +import { grey, info, error, common, primary, success, warning, secondary } from './palette'; + +import type { ThemeColorScheme } from '../types'; + +// ---------------------------------------------------------------------- + +/** + * TypeScript (type definition and extension) + * @to {@link file://./../extend-theme-types.d.ts} + */ + +export interface CustomShadows { + z1?: string; + z4?: string; + z8?: string; + z12?: string; + z16?: string; + z20?: string; + z24?: string; + primary?: string; + secondary?: string; + info?: string; + success?: string; + warning?: string; + error?: string; + card?: string; + dialog?: string; + dropdown?: string; +} + +// ---------------------------------------------------------------------- + +export function createShadowColor(colorChannel: string): string { + return `0 8px 16px 0 ${varAlpha(colorChannel, 0.24)}`; +} + +function createCustomShadows(colorChannel: string): CustomShadows { + return { + z1: `0 1px 2px 0 ${varAlpha(colorChannel, 0.16)}`, + z4: `0 4px 8px 0 ${varAlpha(colorChannel, 0.16)}`, + z8: `0 8px 16px 0 ${varAlpha(colorChannel, 0.16)}`, + z12: `0 12px 24px -4px ${varAlpha(colorChannel, 0.16)}`, + z16: `0 16px 32px -4px ${varAlpha(colorChannel, 0.16)}`, + z20: `0 20px 40px -4px ${varAlpha(colorChannel, 0.16)}`, + z24: `0 24px 48px 0 ${varAlpha(colorChannel, 0.16)}`, + /********/ + dialog: `-40px 40px 80px -8px ${varAlpha(common.blackChannel, 0.24)}`, + card: `0 0 2px 0 ${varAlpha(colorChannel, 0.2)}, 0 12px 24px -4px ${varAlpha(colorChannel, 0.12)}`, + dropdown: `0 0 2px 0 ${varAlpha(colorChannel, 0.24)}, -20px 20px 40px -4px ${varAlpha(colorChannel, 0.24)}`, + /********/ + primary: createShadowColor(primary.mainChannel), + secondary: createShadowColor(secondary.mainChannel), + info: createShadowColor(info.mainChannel), + success: createShadowColor(success.mainChannel), + warning: createShadowColor(warning.mainChannel), + error: createShadowColor(error.mainChannel), + }; +} + +export const customShadows: Partial> = { + light: createCustomShadows(grey['500Channel']), +}; diff --git a/frontend/src/theme/core/index.ts b/frontend/src/theme/core/index.ts new file mode 100644 index 000000000..1f6edd4e3 --- /dev/null +++ b/frontend/src/theme/core/index.ts @@ -0,0 +1,9 @@ +export * from './shadows'; + +export * from './palette'; + +export * from './typography'; + +export * from './components'; + +export * from './custom-shadows'; diff --git a/frontend/src/theme/core/palette.ts b/frontend/src/theme/core/palette.ts new file mode 100644 index 000000000..c5424f03c --- /dev/null +++ b/frontend/src/theme/core/palette.ts @@ -0,0 +1,146 @@ +import type { PaletteColor, ColorSystemOptions, PaletteColorChannel } from '@mui/material/styles'; + +import { varAlpha, createPaletteChannel } from 'minimal-shared/utils'; + +import { themeConfig } from '../theme-config'; + +import type { ThemeColorScheme } from '../types'; + +// ---------------------------------------------------------------------- + +/** + * TypeScript (type definition and extension) + * @to {@link file://./../extend-theme-types.d.ts} + */ + +// Keys for the palette colors +export type PaletteColorKey = 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'; + +// Palette color without additional channels +export type PaletteColorNoChannels = Omit; + +// Palette color with additional channels +export type PaletteColorWithChannels = PaletteColor & PaletteColorChannel; + +// Extended common colors +export type CommonColorsExtend = { + whiteChannel: string; + blackChannel: string; +}; + +// Extended text colors +export type TypeTextExtend = { + disabledChannel: string; +}; + +// Extended background colors +export type TypeBackgroundExtend = { + neutral: string; + neutralChannel: string; +}; + +// Extended palette colors +export type PaletteColorExtend = { + lighter: string; + darker: string; + lighterChannel: string; + darkerChannel: string; +}; + +// Extended grey channels +export type GreyExtend = { + '50Channel': string; + '100Channel': string; + '200Channel': string; + '300Channel': string; + '400Channel': string; + '500Channel': string; + '600Channel': string; + '700Channel': string; + '800Channel': string; + '900Channel': string; +}; + +// ---------------------------------------------------------------------- + +// Primary color +export const primary = createPaletteChannel(themeConfig.palette.primary); + +// Secondary color +export const secondary = createPaletteChannel(themeConfig.palette.secondary); + +// Info color +export const info = createPaletteChannel(themeConfig.palette.info); + +// Success color +export const success = createPaletteChannel(themeConfig.palette.success); + +// Warning color +export const warning = createPaletteChannel(themeConfig.palette.warning); + +// Error color +export const error = createPaletteChannel(themeConfig.palette.error); + +// Common color +export const common = createPaletteChannel(themeConfig.palette.common); + +// Grey color +export const grey = createPaletteChannel(themeConfig.palette.grey); + +// Text color +export const text = { + light: createPaletteChannel({ + primary: grey[800], + secondary: grey[600], + disabled: grey[500], + }), +}; + +// Background color +export const background = { + light: createPaletteChannel({ + paper: '#FFFFFF', + default: grey[100], + neutral: grey[200], + }), +}; + +// Base action color +export const baseAction = { + hover: varAlpha(grey['500Channel'], 0.08), + selected: varAlpha(grey['500Channel'], 0.16), + focus: varAlpha(grey['500Channel'], 0.24), + disabled: varAlpha(grey['500Channel'], 0.8), + disabledBackground: varAlpha(grey['500Channel'], 0.24), + hoverOpacity: 0.08, + disabledOpacity: 0.48, +}; + +// Action color +export const action = { + light: { ...baseAction, active: grey[600] }, +}; + +// ---------------------------------------------------------------------- + +// Base palette +export const basePalette = { + primary, + secondary, + info, + success, + warning, + error, + common, + grey, + divider: varAlpha(grey['500Channel'], 0.2), +}; + +export const palette: Partial> = { + light: { + ...basePalette, + text: text.light, + background: background.light, + action: action.light, + }, +}; diff --git a/frontend/src/theme/core/shadows.ts b/frontend/src/theme/core/shadows.ts new file mode 100644 index 000000000..4d1659ae2 --- /dev/null +++ b/frontend/src/theme/core/shadows.ts @@ -0,0 +1,47 @@ +import type { Shadows } from '@mui/material/styles'; + +import { varAlpha } from 'minimal-shared/utils'; + +import { grey } from './palette'; + +import type { ThemeColorScheme } from '../types'; + +// ---------------------------------------------------------------------- + +function createShadows(colorChannel: string): Shadows { + const color1 = varAlpha(colorChannel, 0.2); + const color2 = varAlpha(colorChannel, 0.14); + const color3 = varAlpha(colorChannel, 0.12); + + return [ + 'none', + `0px 2px 1px -1px ${color1},0px 1px 1px 0px ${color2},0px 1px 3px 0px ${color3}`, + `0px 3px 1px -2px ${color1},0px 2px 2px 0px ${color2},0px 1px 5px 0px ${color3}`, + `0px 3px 3px -2px ${color1},0px 3px 4px 0px ${color2},0px 1px 8px 0px ${color3}`, + `0px 2px 4px -1px ${color1},0px 4px 5px 0px ${color2},0px 1px 10px 0px ${color3}`, + `0px 3px 5px -1px ${color1},0px 5px 8px 0px ${color2},0px 1px 14px 0px ${color3}`, + `0px 3px 5px -1px ${color1},0px 6px 10px 0px ${color2},0px 1px 18px 0px ${color3}`, + `0px 4px 5px -2px ${color1},0px 7px 10px 1px ${color2},0px 2px 16px 1px ${color3}`, + `0px 5px 5px -3px ${color1},0px 8px 10px 1px ${color2},0px 3px 14px 2px ${color3}`, + `0px 5px 6px -3px ${color1},0px 9px 12px 1px ${color2},0px 3px 16px 2px ${color3}`, + `0px 6px 6px -3px ${color1},0px 10px 14px 1px ${color2},0px 4px 18px 3px ${color3}`, + `0px 6px 7px -4px ${color1},0px 11px 15px 1px ${color2},0px 4px 20px 3px ${color3}`, + `0px 7px 8px -4px ${color1},0px 12px 17px 2px ${color2},0px 5px 22px 4px ${color3}`, + `0px 7px 8px -4px ${color1},0px 13px 19px 2px ${color2},0px 5px 24px 4px ${color3}`, + `0px 7px 9px -4px ${color1},0px 14px 21px 2px ${color2},0px 5px 26px 4px ${color3}`, + `0px 8px 9px -5px ${color1},0px 15px 22px 2px ${color2},0px 6px 28px 5px ${color3}`, + `0px 8px 10px -5px ${color1},0px 16px 24px 2px ${color2},0px 6px 30px 5px ${color3}`, + `0px 8px 11px -5px ${color1},0px 17px 26px 2px ${color2},0px 6px 32px 5px ${color3}`, + `0px 9px 11px -5px ${color1},0px 18px 28px 2px ${color2},0px 7px 34px 6px ${color3}`, + `0px 9px 12px -6px ${color1},0px 19px 29px 2px ${color2},0px 7px 36px 6px ${color3}`, + `0px 10px 13px -6px ${color1},0px 20px 31px 3px ${color2},0px 8px 38px 7px ${color3}`, + `0px 10px 13px -6px ${color1},0px 21px 33px 3px ${color2},0px 8px 40px 7px ${color3}`, + `0px 10px 14px -6px ${color1},0px 22px 35px 3px ${color2},0px 8px 42px 7px ${color3}`, + `0px 11px 14px -7px ${color1},0px 23px 36px 3px ${color2},0px 9px 44px 8px ${color3}`, + `0px 11px 15px -7px ${color1},0px 24px 38px 3px ${color2},0px 9px 46px 8px ${color3}`, + ]; +} + +export const shadows: Partial> = { + light: createShadows(grey['500Channel']), +}; diff --git a/frontend/src/theme/core/typography.ts b/frontend/src/theme/core/typography.ts new file mode 100644 index 000000000..302dfc815 --- /dev/null +++ b/frontend/src/theme/core/typography.ts @@ -0,0 +1,127 @@ +import type { CSSObject, Breakpoint, TypographyVariantsOptions } from '@mui/material/styles'; + +import { pxToRem, setFont } from 'minimal-shared/utils'; + +import { createTheme as getTheme } from '@mui/material/styles'; + +import { themeConfig } from '../theme-config'; + +// ---------------------------------------------------------------------- + +/** + * TypeScript (type definition and extension) + * @to {@link file://./../extend-theme-types.d.ts} + */ +export type FontStyleExtend = { + fontWeightSemiBold: CSSObject['fontWeight']; + fontSecondaryFamily: CSSObject['fontFamily']; +}; + +export type ResponsiveFontSizesInput = Partial>; +export type ResponsiveFontSizesResult = Record; + +const defaultMuiTheme = getTheme(); + +function responsiveFontSizes(obj: ResponsiveFontSizesInput): ResponsiveFontSizesResult { + const breakpoints: Breakpoint[] = defaultMuiTheme.breakpoints.keys; + + return breakpoints.reduce((acc, breakpoint) => { + const value = obj[breakpoint]; + + if (value !== undefined && value >= 0) { + acc[defaultMuiTheme.breakpoints.up(breakpoint)] = { + fontSize: pxToRem(value), + }; + } + + return acc; + }, {} as ResponsiveFontSizesResult); +} + +// ---------------------------------------------------------------------- + +const primaryFont = setFont(themeConfig.fontFamily.primary); +const secondaryFont = setFont(themeConfig.fontFamily.secondary); + +export const typography: TypographyVariantsOptions = { + fontFamily: primaryFont, + fontSecondaryFamily: secondaryFont, + fontWeightLight: '300', + fontWeightRegular: '400', + fontWeightMedium: '500', + fontWeightSemiBold: '600', + fontWeightBold: '700', + h1: { + fontFamily: secondaryFont, + fontWeight: 800, + lineHeight: 80 / 64, + fontSize: pxToRem(40), + ...responsiveFontSizes({ sm: 52, md: 58, lg: 64 }), + }, + h2: { + fontFamily: secondaryFont, + fontWeight: 800, + lineHeight: 64 / 48, + fontSize: pxToRem(32), + ...responsiveFontSizes({ sm: 40, md: 44, lg: 48 }), + }, + h3: { + fontFamily: secondaryFont, + fontWeight: 700, + lineHeight: 1.5, + fontSize: pxToRem(24), + ...responsiveFontSizes({ sm: 26, md: 30, lg: 32 }), + }, + h4: { + fontWeight: 700, + lineHeight: 1.5, + fontSize: pxToRem(20), + ...responsiveFontSizes({ md: 24 }), + }, + h5: { + fontWeight: 700, + lineHeight: 1.5, + fontSize: pxToRem(18), + ...responsiveFontSizes({ sm: 19 }), + }, + h6: { + fontWeight: 600, + lineHeight: 28 / 18, + fontSize: pxToRem(17), + ...responsiveFontSizes({ sm: 18 }), + }, + subtitle1: { + fontWeight: 600, + lineHeight: 1.5, + fontSize: pxToRem(16), + }, + subtitle2: { + fontWeight: 600, + lineHeight: 22 / 14, + fontSize: pxToRem(14), + }, + body1: { + lineHeight: 1.5, + fontSize: pxToRem(16), + }, + body2: { + lineHeight: 22 / 14, + fontSize: pxToRem(14), + }, + caption: { + lineHeight: 1.5, + fontSize: pxToRem(12), + }, + overline: { + fontWeight: 700, + lineHeight: 1.5, + fontSize: pxToRem(12), + textTransform: 'uppercase', + }, + button: { + fontWeight: 700, + lineHeight: 24 / 14, + fontSize: pxToRem(14), + textTransform: 'unset', + }, +}; diff --git a/frontend/src/theme/create-classes.ts b/frontend/src/theme/create-classes.ts new file mode 100644 index 000000000..977771a22 --- /dev/null +++ b/frontend/src/theme/create-classes.ts @@ -0,0 +1,7 @@ +import { themeConfig } from './theme-config'; + +// ---------------------------------------------------------------------- + +export function createClasses(className: string): string { + return `${themeConfig.classesPrefix}__${className}`; +} diff --git a/frontend/src/theme/create-theme.ts b/frontend/src/theme/create-theme.ts new file mode 100644 index 000000000..70bee614d --- /dev/null +++ b/frontend/src/theme/create-theme.ts @@ -0,0 +1,40 @@ +import type { Theme } from '@mui/material/styles'; + +import { createTheme as createMuiTheme } from '@mui/material/styles'; + +import { shadows } from './core/shadows'; +import { palette } from './core/palette'; +import { themeConfig } from './theme-config'; +import { components } from './core/components'; +import { typography } from './core/typography'; +import { customShadows } from './core/custom-shadows'; + +import type { ThemeOptions } from './types'; + +// ---------------------------------------------------------------------- + +export const baseTheme: ThemeOptions = { + colorSchemes: { + light: { + palette: palette.light, + shadows: shadows.light, + customShadows: customShadows.light, + }, + }, + components, + typography, + shape: { borderRadius: 8 }, + cssVariables: themeConfig.cssVariables, +}; + +// ---------------------------------------------------------------------- + +type CreateThemeProps = { + themeOverrides?: ThemeOptions; +}; + +export function createTheme({ themeOverrides = {} }: CreateThemeProps = {}): Theme { + const theme = createMuiTheme(baseTheme, themeOverrides); + + return theme; +} diff --git a/frontend/src/theme/extend-theme-types.d.ts b/frontend/src/theme/extend-theme-types.d.ts new file mode 100644 index 000000000..42b84e1b5 --- /dev/null +++ b/frontend/src/theme/extend-theme-types.d.ts @@ -0,0 +1,66 @@ +import type {} from '@mui/lab/themeAugmentation'; +import type {} from '@mui/material/themeCssVarsAugmentation'; + +import type { FontStyleExtend } from './core/typography'; +import type { CustomShadows } from './core/custom-shadows'; +import type { + GreyExtend, + TypeTextExtend, + CommonColorsExtend, + PaletteColorExtend, + TypeBackgroundExtend, +} from './core/palette'; + +// ---------------------------------------------------------------------- + +/** ************************************** + * EXTEND CORE + * Palette, typography, shadows... + *************************************** */ + +/** + * Palette + * https://mui.com/customization/palette/ + * @from {@link file://./core/palette.ts} + */ +declare module '@mui/material/styles' { + // grey + interface Color extends GreyExtend {} + // text + interface TypeText extends TypeTextExtend {} + // black & white + interface CommonColors extends CommonColorsExtend {} + // background + interface TypeBackground extends TypeBackgroundExtend {} + // primary, secondary, info, success, warning, error + interface PaletteColor extends PaletteColorExtend {} + interface SimplePaletteColorOptions extends Partial {} +} + +/** + * Typography + * https://mui.com/customization/typography/ + * @from {@link file://./core/typography.ts} + */ +declare module '@mui/material/styles' { + interface TypographyVariants extends FontStyleExtend {} + interface TypographyVariantsOptions extends Partial {} +} + +declare module '@mui/material/styles' { + /** + * Custom shadows + * @from {@link file://./core/custom-shadows.ts} + */ + interface Theme { + customShadows: CustomShadows; + } + interface ThemeOptions { + customShadows?: CustomShadows; + } + interface ThemeVars { + customShadows: CustomShadows; + typography: Theme['typography']; + transitions: Theme['transitions']; + } +} diff --git a/frontend/src/theme/index.ts b/frontend/src/theme/index.ts new file mode 100644 index 000000000..26e759f8b --- /dev/null +++ b/frontend/src/theme/index.ts @@ -0,0 +1,7 @@ +export * from './core'; + +export * from './types'; + +export * from './theme-config'; + +export * from './theme-provider'; diff --git a/frontend/src/theme/theme-config.ts b/frontend/src/theme/theme-config.ts new file mode 100644 index 000000000..8805602b8 --- /dev/null +++ b/frontend/src/theme/theme-config.ts @@ -0,0 +1,109 @@ +import type { CommonColors } from '@mui/material/styles'; + +import type { ThemeCssVariables } from './types'; +import type { PaletteColorNoChannels } from './core/palette'; + +// ---------------------------------------------------------------------- + +type ThemeConfig = { + classesPrefix: string; + cssVariables: ThemeCssVariables; + fontFamily: Record<'primary' | 'secondary', string>; + palette: Record< + 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error', + PaletteColorNoChannels + > & { + common: Pick; + grey: Record< + '50' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900', + string + >; + }; +}; + +export const themeConfig: ThemeConfig = { + /** ************************************** + * Base + *************************************** */ + classesPrefix: 'minimal', + /** ************************************** + * Typography + *************************************** */ + fontFamily: { + primary: 'DM Sans Variable', + secondary: 'Barlow', + }, + /** ************************************** + * Palette + *************************************** */ + palette: { + primary: { + lighter: '#D0ECFE', + light: '#73BAFB', + main: '#1877F2', + dark: '#0C44AE', + darker: '#042174', + contrastText: '#FFFFFF', + }, + secondary: { + lighter: '#EFD6FF', + light: '#C684FF', + main: '#8E33FF', + dark: '#5119B7', + darker: '#27097A', + contrastText: '#FFFFFF', + }, + info: { + lighter: '#CAFDF5', + light: '#61F3F3', + main: '#00B8D9', + dark: '#006C9C', + darker: '#003768', + contrastText: '#FFFFFF', + }, + success: { + lighter: '#D3FCD2', + light: '#77ED8B', + main: '#22C55E', + dark: '#118D57', + darker: '#065E49', + contrastText: '#ffffff', + }, + warning: { + lighter: '#FFF5CC', + light: '#FFD666', + main: '#FFAB00', + dark: '#B76E00', + darker: '#7A4100', + contrastText: '#1C252E', + }, + error: { + lighter: '#FFE9D5', + light: '#FFAC82', + main: '#FF5630', + dark: '#B71D18', + darker: '#7A0916', + contrastText: '#FFFFFF', + }, + grey: { + '50': '#FCFDFD', + '100': '#F9FAFB', + '200': '#F4F6F8', + '300': '#DFE3E8', + '400': '#C4CDD5', + '500': '#919EAB', + '600': '#637381', + '700': '#454F5B', + '800': '#1C252E', + '900': '#141A21', + }, + common: { black: '#000000', white: '#FFFFFF' }, + }, + /** ************************************** + * Css variables + *************************************** */ + cssVariables: { + cssVarPrefix: '', + colorSchemeSelector: 'data-color-scheme', + }, +}; diff --git a/frontend/src/theme/theme-provider.tsx b/frontend/src/theme/theme-provider.tsx new file mode 100644 index 000000000..8b8de27fa --- /dev/null +++ b/frontend/src/theme/theme-provider.tsx @@ -0,0 +1,28 @@ +import type { ThemeProviderProps as MuiThemeProviderProps } from '@mui/material/styles'; + +import CssBaseline from '@mui/material/CssBaseline'; +import { ThemeProvider as ThemeVarsProvider } from '@mui/material/styles'; + +import { createTheme } from './create-theme'; + +import type {} from './extend-theme-types'; +import type { ThemeOptions } from './types'; + +// ---------------------------------------------------------------------- + +export type ThemeProviderProps = Partial & { + themeOverrides?: ThemeOptions; +}; + +export function ThemeProvider({ themeOverrides, children, ...other }: ThemeProviderProps) { + const theme = createTheme({ + themeOverrides, + }); + + return ( + + + {children} + + ); +} diff --git a/frontend/src/theme/types.ts b/frontend/src/theme/types.ts new file mode 100644 index 000000000..d3f28ad73 --- /dev/null +++ b/frontend/src/theme/types.ts @@ -0,0 +1,35 @@ +import type { + Shadows, + ColorSystemOptions, + CssVarsThemeOptions, + SupportedColorScheme, + ThemeOptions as MuiThemeOptions, +} from '@mui/material/styles'; + +import type { CustomShadows } from './core/custom-shadows'; + +// ---------------------------------------------------------------------- + +/** + * Theme options + * Extended type that includes additional properties for color schemes and CSS variables. + * + * @see https://github.com/mui/material-ui/blob/master/packages/mui-material/src/styles/createTheme.ts + */ + +export type ThemeColorScheme = SupportedColorScheme; +export type ThemeCssVariables = Pick< + CssVarsThemeOptions, + 'colorSchemeSelector' | 'disableCssColorScheme' | 'cssVarPrefix' | 'shouldSkipGeneratingVar' +>; + +type ColorSchemeOptionsExtended = ColorSystemOptions & { + shadows?: Shadows; + customShadows?: CustomShadows; +}; + +export type ThemeOptions = Omit & + Pick & { + colorSchemes?: Partial>; + cssVariables?: ThemeCssVariables; + }; diff --git a/frontend/src/utils/format-number.ts b/frontend/src/utils/format-number.ts new file mode 100644 index 000000000..33203acf8 --- /dev/null +++ b/frontend/src/utils/format-number.ts @@ -0,0 +1,86 @@ +/* + * Locales code + * https://gist.github.com/raushankrjha/d1c7e35cf87e69aa8b4208a8171a8416 + */ + +export type InputNumberValue = string | number | null | undefined; + +type Options = Intl.NumberFormatOptions; + +const DEFAULT_LOCALE = { code: 'en-US', currency: 'USD' }; + +function processInput(inputValue: InputNumberValue): number | null { + if (inputValue == null || Number.isNaN(inputValue)) return null; + return Number(inputValue); +} + +// ---------------------------------------------------------------------- + +export function fNumber(inputValue: InputNumberValue, options?: Options) { + const locale = DEFAULT_LOCALE; + + const number = processInput(inputValue); + if (number === null) return ''; + + const fm = new Intl.NumberFormat(locale.code, { + minimumFractionDigits: 0, + maximumFractionDigits: 2, + ...options, + }).format(number); + + return fm; +} + +// ---------------------------------------------------------------------- + +export function fCurrency(inputValue: InputNumberValue, options?: Options) { + const locale = DEFAULT_LOCALE; + + const number = processInput(inputValue); + if (number === null) return ''; + + const fm = new Intl.NumberFormat(locale.code, { + style: 'currency', + currency: locale.currency, + minimumFractionDigits: 0, + maximumFractionDigits: 2, + ...options, + }).format(number); + + return fm; +} + +// ---------------------------------------------------------------------- + +export function fPercent(inputValue: InputNumberValue, options?: Options) { + const locale = DEFAULT_LOCALE; + + const number = processInput(inputValue); + if (number === null) return ''; + + const fm = new Intl.NumberFormat(locale.code, { + style: 'percent', + minimumFractionDigits: 0, + maximumFractionDigits: 1, + ...options, + }).format(number / 100); + + return fm; +} + +// ---------------------------------------------------------------------- + +export function fShortenNumber(inputValue: InputNumberValue, options?: Options) { + const locale = DEFAULT_LOCALE; + + const number = processInput(inputValue); + if (number === null) return ''; + + const fm = new Intl.NumberFormat(locale.code, { + notation: 'compact', + maximumFractionDigits: 2, + ...options, + }).format(number); + + return fm.replace(/[A-Z]/g, (match) => match.toLowerCase()); +} diff --git a/frontend/src/utils/format-time.ts b/frontend/src/utils/format-time.ts new file mode 100644 index 000000000..71f1bc011 --- /dev/null +++ b/frontend/src/utils/format-time.ts @@ -0,0 +1,92 @@ +import type { Dayjs } from 'dayjs'; + +import dayjs from 'dayjs'; +import duration from 'dayjs/plugin/duration'; +import relativeTime from 'dayjs/plugin/relativeTime'; + +// ---------------------------------------------------------------------- + +/** + * @Docs + * https://day.js.org/docs/en/display/format + */ + +/** + * Default timezones + * https://day.js.org/docs/en/timezone/set-default-timezone#docsNav + * + */ + +/** + * UTC + * https://day.js.org/docs/en/plugin/utc + * @install + * import utc from 'dayjs/plugin/utc'; + * dayjs.extend(utc); + * @usage + * dayjs().utc().format() + * + */ + +dayjs.extend(duration); +dayjs.extend(relativeTime); + +// ---------------------------------------------------------------------- + +export type DatePickerFormat = Dayjs | Date | string | number | null | undefined; + +export const formatPatterns = { + dateTime: 'DD MMM YYYY h:mm a', // 17 Apr 2022 12:00 am + date: 'DD MMM YYYY', // 17 Apr 2022 + time: 'h:mm a', // 12:00 am + split: { + dateTime: 'DD/MM/YYYY h:mm a', // 17/04/2022 12:00 am + date: 'DD/MM/YYYY', // 17/04/2022 + }, + paramCase: { + dateTime: 'DD-MM-YYYY h:mm a', // 17-04-2022 12:00 am + date: 'DD-MM-YYYY', // 17-04-2022 + }, +}; + +const isValidDate = (date: DatePickerFormat) => + date !== null && date !== undefined && dayjs(date).isValid(); + +// ---------------------------------------------------------------------- + +/** + * @output 17 Apr 2022 12:00 am + */ +export function fDateTime(date: DatePickerFormat, template?: string): string { + if (!isValidDate(date)) { + return 'Invalid date'; + } + + return dayjs(date).format(template ?? formatPatterns.dateTime); +} + +// ---------------------------------------------------------------------- + +/** + * @output 17 Apr 2022 + */ +export function fDate(date: DatePickerFormat, template?: string): string { + if (!isValidDate(date)) { + return 'Invalid date'; + } + + return dayjs(date).format(template ?? formatPatterns.date); +} + +// ---------------------------------------------------------------------- + +/** + * @output a few seconds, 2 years + */ +export function fToNow(date: DatePickerFormat): string { + if (!isValidDate(date)) { + return 'Invalid date'; + } + + return dayjs(date).toNow(true); +} diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 000000000..019f239b1 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + /* Bundler */ + "baseUrl": ".", + "module": "ESNext", + "jsx": "react-jsx", + "allowJs": true, + "resolveJsonModule": true, + + /* Build */ + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "moduleResolution": "bundler", + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "incremental": true, + "skipLibCheck": true, + "esModuleInterop": true, + "isolatedModules": true, + + /* Linting */ + "strict": true, + "noEmit": true, + "strictNullChecks": true + }, + "include": ["src"], + "exclude": ["node_modules"], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json new file mode 100644 index 000000000..a535f7d4d --- /dev/null +++ b/frontend/tsconfig.node.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/frontend/vercel.json b/frontend/vercel.json new file mode 100644 index 000000000..408821b11 --- /dev/null +++ b/frontend/vercel.json @@ -0,0 +1,8 @@ +{ + "rewrites": [ + { + "source": "/(.*)", + "destination": "/" + } + ] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 000000000..37026a78f --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,36 @@ +import path from 'path'; +import checker from 'vite-plugin-checker'; +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react-swc'; + +// ---------------------------------------------------------------------- + +const PORT = 3039; + +export default defineConfig({ + plugins: [ + react(), + checker({ + typescript: true, + eslint: { + useFlatConfig: true, + lintCommand: 'eslint "./src/**/*.{js,jsx,ts,tsx}"', + dev: { logLevel: ['error'] }, + }, + overlay: { + position: 'tl', + initialIsOpen: false, + }, + }), + ], + resolve: { + alias: [ + { + find: /^src(.+)/, + replacement: path.resolve(process.cwd(), 'src/$1'), + }, + ], + }, + server: { port: PORT, host: true }, + preview: { port: PORT, host: true }, +}); diff --git a/frontend/yarn.lock b/frontend/yarn.lock new file mode 100644 index 000000000..aef18079d --- /dev/null +++ b/frontend/yarn.lock @@ -0,0 +1,3468 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.26.2": + version "7.26.2" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/generator@^7.27.0": + version "7.27.0" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz" + integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw== + dependencies: + "@babel/parser" "^7.27.0" + "@babel/types" "^7.27.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + +"@babel/helper-module-imports@^7.16.7": + version "7.25.9" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/parser@^7.27.0": + version "7.27.0" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz" + integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== + dependencies: + "@babel/types" "^7.27.0" + +"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.26.10", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": + version "7.27.0" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz" + integrity sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.27.0": + version "7.27.0" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz" + integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.27.0" + "@babel/types" "^7.27.0" + +"@babel/traverse@^7.25.9": + version "7.27.0" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz" + integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.27.0" + "@babel/parser" "^7.27.0" + "@babel/template" "^7.27.0" + "@babel/types" "^7.27.0" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.25.9", "@babel/types@^7.27.0": + version "7.27.0" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz" + integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + +"@corvu/utils@~0.4.0", "@corvu/utils@~0.4.1": + version "0.4.2" + resolved "https://registry.npmjs.org/@corvu/utils/-/utils-0.4.2.tgz" + integrity sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA== + dependencies: + "@floating-ui/dom" "^1.6.11" + +"@emotion/babel-plugin@^11.13.5": + version "11.13.5" + resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz" + integrity sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/serialize" "^1.3.3" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" + +"@emotion/cache@^11.13.5", "@emotion/cache@^11.14.0": + version "11.14.0" + resolved "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz" + integrity sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA== + dependencies: + "@emotion/memoize" "^0.9.0" + "@emotion/sheet" "^1.4.0" + "@emotion/utils" "^1.4.2" + "@emotion/weak-memoize" "^0.4.0" + stylis "4.2.0" + +"@emotion/hash@^0.9.2": + version "0.9.2" + resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz" + integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== + +"@emotion/is-prop-valid@^1.3.0": + version "1.3.1" + resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz" + integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw== + dependencies: + "@emotion/memoize" "^0.9.0" + +"@emotion/memoize@^0.9.0": + version "0.9.0" + resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz" + integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== + +"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.14.0", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0": + version "11.14.0" + resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz" + integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.13.5" + "@emotion/cache" "^11.14.0" + "@emotion/serialize" "^1.3.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.2.0" + "@emotion/utils" "^1.4.2" + "@emotion/weak-memoize" "^0.4.0" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.3.3": + version "1.3.3" + resolved "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz" + integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA== + dependencies: + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/unitless" "^0.10.0" + "@emotion/utils" "^1.4.2" + csstype "^3.0.2" + +"@emotion/sheet@^1.4.0": + version "1.4.0" + resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz" + integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== + +"@emotion/styled@^11.14.0", "@emotion/styled@^11.3.0": + version "11.14.0" + resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz" + integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.13.5" + "@emotion/is-prop-valid" "^1.3.0" + "@emotion/serialize" "^1.3.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.2.0" + "@emotion/utils" "^1.4.2" + +"@emotion/unitless@^0.10.0": + version "0.10.0" + resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz" + integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg== + +"@emotion/use-insertion-effect-with-fallbacks@^1.2.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz" + integrity sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg== + +"@emotion/utils@^1.4.2": + version "1.4.2" + resolved "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz" + integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA== + +"@emotion/weak-memoize@^0.4.0": + version "0.4.0" + resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz" + integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== + +"@esbuild/win32-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz" + integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== + +"@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.8.0": + version "4.9.1" + resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz" + integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": + version "4.12.1" + resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint/config-array@^0.21.2": + version "0.21.2" + resolved "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz" + integrity sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw== + dependencies: + "@eslint/object-schema" "^2.1.7" + debug "^4.3.1" + minimatch "^3.1.5" + +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== + dependencies: + "@eslint/core" "^0.17.0" + +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.3.5": + version "3.3.5" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz" + integrity sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg== + dependencies: + ajv "^6.14.0" + 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.1" + minimatch "^3.1.5" + strip-json-comments "^3.1.1" + +"@eslint/js@^9.23.0", "@eslint/js@9.39.4": + version "9.39.4" + resolved "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz" + integrity sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw== + +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== + +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== + dependencies: + "@eslint/core" "^0.17.0" + levn "^0.4.1" + +"@floating-ui/core@^1.7.5": + version "1.7.5" + resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz" + integrity sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ== + dependencies: + "@floating-ui/utils" "^0.2.11" + +"@floating-ui/dom@^1.5", "@floating-ui/dom@^1.5.1", "@floating-ui/dom@^1.6.11", "@floating-ui/dom@^1.6.13": + version "1.7.6" + resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz" + integrity sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ== + dependencies: + "@floating-ui/core" "^1.7.5" + "@floating-ui/utils" "^0.2.11" + +"@floating-ui/utils@^0.2.11": + version "0.2.11" + resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz" + integrity sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg== + +"@fontsource-variable/dm-sans@^5.2.5": + version "5.2.5" + resolved "https://registry.npmjs.org/@fontsource-variable/dm-sans/-/dm-sans-5.2.5.tgz" + integrity sha512-ynWdb1Ncn5ywUOE6OkTsvgjkiZKj+xM/GS2iVE47MBvS3AlfOSyOy3xynfkQsM3ngaxdCamT/06hZGAgPmao0A== + +"@fontsource/barlow@^5.2.5": + version "5.2.5" + resolved "https://registry.npmjs.org/@fontsource/barlow/-/barlow-5.2.5.tgz" + integrity sha512-p+2XXEM7v85kbn0Dh8g0YLMjTCDiRCAi9nHik6w/2owZ9CkT1yYGGgaUMshJRqykh7efv1gE0QxAkOhZHd8tEg== + +"@hookform/resolvers@^5.4.0": + version "5.4.0" + resolved "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.4.0.tgz" + integrity sha512-EIsqr/t/qbinPIhGjMdtvutIN1Kk4uwbROE9/UQ93CAVGR7GkA7Y92+fX80OzXi/OB67jVFYwKGO1WzkxmkFZw== + dependencies: + "@standard-schema/utils" "^0.3.0" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.2": + version "0.4.2" + resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz" + integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== + +"@iconify/react@^5.2.1": + version "5.2.1" + resolved "https://registry.npmjs.org/@iconify/react/-/react-5.2.1.tgz" + integrity sha512-37GDR3fYDZmnmUn9RagyaX+zca24jfVOMY8E1IXTqJuE8pxNtN51KWPQe3VODOWvuUurq7q9uUu3CFrpqj5Iqg== + dependencies: + "@iconify/types" "^2.0.0" + +"@iconify/types@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz" + integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== + +"@internationalized/number@^3.2.1": + version "3.6.7" + resolved "https://registry.npmjs.org/@internationalized/number/-/number-3.6.7.tgz" + integrity sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg== + dependencies: + "@swc/helpers" "^0.5.0" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.8" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@kobalte/core@^0.13.10": + version "0.13.12" + resolved "https://registry.npmjs.org/@kobalte/core/-/core-0.13.12.tgz" + integrity sha512-aumsbsPe99/z2igcX2+p+Mdhzw89uuZx8ZdgfEqSlVuuWeTvkoBtCId5sl/Y7sWvllIOFwPoMzE3u0rAzDNkvg== + dependencies: + "@floating-ui/dom" "^1.5.1" + "@internationalized/number" "^3.2.1" + "@kobalte/utils" "^0.9.2" + "@solid-primitives/props" "^3.1.8" + "@solid-primitives/resize-observer" "^2.0.26" + solid-presence "^0.1.8" + solid-prevent-scroll "^0.1.4" + +"@kobalte/utils@^0.9.2": + version "0.9.2" + resolved "https://registry.npmjs.org/@kobalte/utils/-/utils-0.9.2.tgz" + integrity sha512-jRVXr+zsVHxzDXRoh+CDeXzvCsFJ6uiHhqqNQ26Cw9ZsZ3D6nqPUBt1gGVtj2ZPmRL3a9Uk1v8D1aJ8/I12Dow== + dependencies: + "@solid-primitives/event-listener" "^2.2.14" + "@solid-primitives/keyed" "^1.2.0" + "@solid-primitives/map" "^0.4.7" + "@solid-primitives/media" "^2.2.4" + "@solid-primitives/props" "^3.1.8" + "@solid-primitives/refs" "^1.0.5" + "@solid-primitives/utils" "^6.2.1" + +"@motionone/animation@^10.18.0": + version "10.18.0" + resolved "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz" + integrity sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw== + dependencies: + "@motionone/easing" "^10.18.0" + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/dom@^10.17.0": + version "10.18.0" + resolved "https://registry.npmjs.org/@motionone/dom/-/dom-10.18.0.tgz" + integrity sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A== + dependencies: + "@motionone/animation" "^10.18.0" + "@motionone/generators" "^10.18.0" + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/easing@^10.18.0": + version "10.18.0" + resolved "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz" + integrity sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg== + dependencies: + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/generators@^10.18.0": + version "10.18.0" + resolved "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz" + integrity sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg== + dependencies: + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/types@^10.17.1": + version "10.17.1" + resolved "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz" + integrity sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A== + +"@motionone/utils@^10.17.0", "@motionone/utils@^10.18.0": + version "10.18.0" + resolved "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz" + integrity sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw== + dependencies: + "@motionone/types" "^10.17.1" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@mui/core-downloads-tracker@^7.0.1": + version "7.0.1" + resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.0.1.tgz" + integrity sha512-T5DNVnSD9pMbj4Jk/Uphz+yvj9dfpl2+EqsOuJtG12HxEihNG5pd3qzX5yM1Id4dDwKRvM3dPVcxyzavTFhJeA== + +"@mui/lab@^7.0.0-beta.10": + version "7.0.0-beta.10" + resolved "https://registry.npmjs.org/@mui/lab/-/lab-7.0.0-beta.10.tgz" + integrity sha512-ide9oABYRAvJAFtxjc+bAaeAR74yVZ4avV7Ffj/D5CbbgSp/d5ns9SQtuWIZ7oJ3S7l1fcR06dj8EZuPRTmo8A== + dependencies: + "@babel/runtime" "^7.26.10" + "@mui/system" "^7.0.1" + "@mui/types" "^7.4.0" + "@mui/utils" "^7.0.1" + clsx "^2.1.1" + prop-types "^15.8.1" + +"@mui/material@^7.0.1": + version "7.0.1" + resolved "https://registry.npmjs.org/@mui/material/-/material-7.0.1.tgz" + integrity sha512-tQwjIIsn/UUSCHoCIQVkANuLua67h7Ro9M9gIHoGWaFbJFuF6cSO4Oda2olDVqIs4SWG+PaDChuu6SngxsaoyQ== + dependencies: + "@babel/runtime" "^7.26.10" + "@mui/core-downloads-tracker" "^7.0.1" + "@mui/system" "^7.0.1" + "@mui/types" "^7.4.0" + "@mui/utils" "^7.0.1" + "@popperjs/core" "^2.11.8" + "@types/react-transition-group" "^4.4.12" + clsx "^2.1.1" + csstype "^3.1.3" + prop-types "^15.8.1" + react-is "^19.0.0" + react-transition-group "^4.4.5" + +"@mui/private-theming@^7.0.1": + version "7.0.1" + resolved "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.0.1.tgz" + integrity sha512-1kQ7REYjjzDukuMfTbAjm3pLEhD7gUMC2bWhg9VD6f6sHzyokKzX0XHzlr3IdzNWBjPytGkzHpPIRQrUOoPLCQ== + dependencies: + "@babel/runtime" "^7.26.10" + "@mui/utils" "^7.0.1" + prop-types "^15.8.1" + +"@mui/styled-engine@^7.0.1": + version "7.0.1" + resolved "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.0.1.tgz" + integrity sha512-BeGe4xZmF7tESKhmctYrL54Kl25kGHPKVdZYM5qj5Xz76WM/poY+d8EmAqUesT6k2rbJWPp2gtOAXXinNCGunQ== + dependencies: + "@babel/runtime" "^7.26.10" + "@emotion/cache" "^11.13.5" + "@emotion/serialize" "^1.3.3" + "@emotion/sheet" "^1.4.0" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/system@^7.0.1": + version "7.0.1" + resolved "https://registry.npmjs.org/@mui/system/-/system-7.0.1.tgz" + integrity sha512-pK+puz0hRPHEKGlcPd80mKYD3jpyi0uVIwWffox1WZgPTQMw2dCKLcD+9ndMDJADnrKzmKlpoH756PPFh2UvWA== + dependencies: + "@babel/runtime" "^7.26.10" + "@mui/private-theming" "^7.0.1" + "@mui/styled-engine" "^7.0.1" + "@mui/types" "^7.4.0" + "@mui/utils" "^7.0.1" + clsx "^2.1.1" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/types@^7.4.0": + version "7.4.0" + resolved "https://registry.npmjs.org/@mui/types/-/types-7.4.0.tgz" + integrity sha512-TxJ4ezEeedWHBjOmLtxI203a9DII9l4k83RXmz1PYSAmnyEcK2PglTNmJGxswC/wM5cdl9ap2h8lnXvt2swAGQ== + dependencies: + "@babel/runtime" "^7.26.10" + +"@mui/utils@^7.0.1": + version "7.0.1" + resolved "https://registry.npmjs.org/@mui/utils/-/utils-7.0.1.tgz" + integrity sha512-SJKrrebNpmK9rJCnVL29nGPhPXQYtBZmb7Dsp0f58uIUhQfAKcBXHE4Kjs06SX4CwqeCuwEVgcHY+MgAO6XQ/g== + dependencies: + "@babel/runtime" "^7.26.10" + "@mui/types" "^7.4.0" + "@types/prop-types" "^15.7.14" + clsx "^2.1.1" + prop-types "^15.8.1" + react-is "^19.0.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + version "2.0.5" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@novu/js@3.17.0": + version "3.17.0" + resolved "https://registry.npmjs.org/@novu/js/-/js-3.17.0.tgz" + integrity sha512-vZkGBROVwiIceengZlZyqeUisBVzvHCS99WqR763ki+qQFxjAMSRIMIWX+shU6EIjUPGhXR4OjLV6ob/4bN63Q== + dependencies: + "@floating-ui/dom" "^1.6.13" + "@kobalte/core" "^0.13.10" + "@types/json-logic-js" "^2.0.8" + class-variance-authority "^0.7.0" + clsx "^2.1.1" + event-target-polyfill "^0.0.4" + mitt "^3.0.1" + partysocket "^1.1.4" + socket.io-client "4.7.2" + solid-floating-ui "^0.3.1" + solid-js "^1.9.4" + solid-motionone "^1.0.3" + tailwind-merge "^2.4.0" + +"@novu/react@^3.17.0": + version "3.17.0" + resolved "https://registry.npmjs.org/@novu/react/-/react-3.17.0.tgz" + integrity sha512-9DdDxJo24mNx5xPETgi4yWVNJcI8MigQlwWrjLg2ySvm5SnBkUbIcz6kqjGtGhQ1NN3xiYNOHnIGrmKPMiic1A== + dependencies: + "@novu/js" "3.17.0" + +"@popperjs/core@^2.11.8": + version "2.11.8" + resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + +"@rollup/rollup-win32-x64-gnu@4.62.0": + version "4.62.0" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.0.tgz" + integrity sha512-SoTb6lPg25xZlA2ibwQ++ahCCnH+FP0qmEuafMJ4gznZKOlXioKEAeJLgCrqjM98ACziXM9V1amFjICVL4IFoA== + +"@rollup/rollup-win32-x64-msvc@4.62.0": + version "4.62.0" + resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.0.tgz" + integrity sha512-5L+T1fMX4RIEBoZzT0+sQ0PhTS36NULFmMXtl1TZo44TMAROIMHbZufSOjVWt/Y622BtxgxtaNOokbTDvfsrZA== + +"@rtsao/scc@^1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz" + integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== + +"@socket.io/component-emitter@~3.1.0": + version "3.1.2" + resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz" + integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== + +"@solid-primitives/event-listener@^2.2.14", "@solid-primitives/event-listener@^2.4.6": + version "2.4.6" + resolved "https://registry.npmjs.org/@solid-primitives/event-listener/-/event-listener-2.4.6.tgz" + integrity sha512-5I0YJcTVYIWoMmgBSROBZGcz+ymhew/pGTg2dHW74BUjFKsV8Li4bOZYl0YAGP4mHw5o4UBd9/BEesqBci3wxw== + dependencies: + "@solid-primitives/utils" "^6.4.1" + +"@solid-primitives/keyed@^1.2.0": + version "1.5.3" + resolved "https://registry.npmjs.org/@solid-primitives/keyed/-/keyed-1.5.3.tgz" + integrity sha512-zNadtyYBhJSOjXtogkGHmRxjGdz9KHc8sGGVAGlUABkE8BED2tbIZoxkwSqzOwde8OcUEH0bb5DLZUWIMvyBSA== + +"@solid-primitives/map@^0.4.7": + version "0.4.13" + resolved "https://registry.npmjs.org/@solid-primitives/map/-/map-0.4.13.tgz" + integrity sha512-B1zyFbsiTQvqPr+cuPCXO72sRuczG9Swncqk5P74NCGw1VE8qa/Ry9GlfI1e/VdeQYHjan+XkbE3rO2GW/qKew== + dependencies: + "@solid-primitives/trigger" "^1.1.0" + +"@solid-primitives/media@^2.2.4": + version "2.3.6" + resolved "https://registry.npmjs.org/@solid-primitives/media/-/media-2.3.6.tgz" + integrity sha512-pk49gPOq/UMRUJ+pTSrOfBiR8xJjRYHXIf1iR/jSnyQ/KroU+ZXhkZzavC7hvfp2vJeOTW5k2/HN0r3Q1VJ7Pw== + dependencies: + "@solid-primitives/event-listener" "^2.4.6" + "@solid-primitives/rootless" "^1.5.4" + "@solid-primitives/static-store" "^0.1.4" + "@solid-primitives/utils" "^6.4.1" + +"@solid-primitives/props@^3.1.11", "@solid-primitives/props@^3.1.8": + version "3.2.4" + resolved "https://registry.npmjs.org/@solid-primitives/props/-/props-3.2.4.tgz" + integrity sha512-MXXdvi2TSB6d+0N6ueA/HP1j/Kh9SEc4WdF1ZDMLwPagxW6pIHHSS9xbRO0RjqSVpNP4j0nxCWT1hx3CkJNhNA== + dependencies: + "@solid-primitives/utils" "^6.4.1" + +"@solid-primitives/refs@^1.0.5", "@solid-primitives/refs@^1.0.8": + version "1.1.4" + resolved "https://registry.npmjs.org/@solid-primitives/refs/-/refs-1.1.4.tgz" + integrity sha512-bLjwIs6ZPu8NQnuw04sU3Zc8qKSpbc0umUU/O4SHf6oWOdO4+dHY8vb1T7C4b/Tg103+9WGr6sEE0+NFlbaB/A== + dependencies: + "@solid-primitives/utils" "^6.4.1" + +"@solid-primitives/resize-observer@^2.0.26": + version "2.1.6" + resolved "https://registry.npmjs.org/@solid-primitives/resize-observer/-/resize-observer-2.1.6.tgz" + integrity sha512-GFj6b81KIahl5SBf35VlyClHshDhVEREeZz2WYkHHKBvam66mE5H5f1g3EralabAAjmcU1bBd18YYYETPv0Knw== + dependencies: + "@solid-primitives/event-listener" "^2.4.6" + "@solid-primitives/rootless" "^1.5.4" + "@solid-primitives/static-store" "^0.1.4" + "@solid-primitives/utils" "^6.4.1" + +"@solid-primitives/rootless@^1.5.4": + version "1.5.4" + resolved "https://registry.npmjs.org/@solid-primitives/rootless/-/rootless-1.5.4.tgz" + integrity sha512-TOIZa1VUfVJ+9nkCcRajw3U4t9vBOP1HxX1WHNTbXq32mXwlqTvUnC4CRIilohcryBkT9u2ZkhUDSHRTaGp55g== + dependencies: + "@solid-primitives/utils" "^6.4.1" + +"@solid-primitives/static-store@^0.1.4": + version "0.1.4" + resolved "https://registry.npmjs.org/@solid-primitives/static-store/-/static-store-0.1.4.tgz" + integrity sha512-LgtVaVBtB7EbmS4+M0b8xY5Iq6pUWXBsIC4VgtrFKDGDdyCaDt88sHk0fUlx1Enxm/XZnZyLXJABRoa39RjJqA== + dependencies: + "@solid-primitives/utils" "^6.4.1" + +"@solid-primitives/transition-group@^1.0.5": + version "1.1.2" + resolved "https://registry.npmjs.org/@solid-primitives/transition-group/-/transition-group-1.1.2.tgz" + integrity sha512-gnHS0OmcdjeoHN9n7Khu8KNrOlRc8a2weETDt2YT6o1zeW/XtUC6Db3Q9pkMU/9cCKdEmN4b0a/41MKAHRhzWA== + +"@solid-primitives/trigger@^1.1.0": + version "1.2.4" + resolved "https://registry.npmjs.org/@solid-primitives/trigger/-/trigger-1.2.4.tgz" + integrity sha512-Ju0e+ZOD7hpOp7nptJimvDSZHWFvIvF9iBWMvuwt30smX7c5wmB8Kmc0AdDuv0wOTi06PQ1J5IrP1WJbH2yUBQ== + dependencies: + "@solid-primitives/utils" "^6.4.1" + +"@solid-primitives/utils@^6.2.1", "@solid-primitives/utils@^6.4.1": + version "6.4.1" + resolved "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.4.1.tgz" + integrity sha512-ISSB5QX1qP2ynrheIpYwc4oKR5Ny4siNuUyf1qZniy+Il+p/PtDB0QK1Dnle8noiHpwRD3gpPdubOC3qI/Zamg== + +"@standard-schema/utils@^0.3.0": + version "0.3.0" + resolved "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz" + integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g== + +"@svgdotjs/svg.draggable.js@^3.0.4": + version "3.0.6" + resolved "https://registry.npmjs.org/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.6.tgz" + integrity sha512-7iJFm9lL3C40HQcqzEfezK2l+dW2CpoVY3b77KQGqc8GXWa6LhhmX5Ckv7alQfUXBuZbjpICZ+Dvq1czlGx7gA== + +"@svgdotjs/svg.filter.js@^3.0.8": + version "3.0.9" + resolved "https://registry.npmjs.org/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.9.tgz" + integrity sha512-/69XMRCDoam2HgC4ldHIaDgeQf1ViHIsa0Ld4uWgiXtZ+E24DWHe/9Ib6kbNiZ7WRIdlVokUDR1Fg0kjIpkfbw== + dependencies: + "@svgdotjs/svg.js" "^3.2.4" + +"@svgdotjs/svg.js@^3.2.4": + version "3.2.4" + resolved "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.4.tgz" + integrity sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg== + +"@svgdotjs/svg.resize.js@^2.0.2": + version "2.0.5" + resolved "https://registry.npmjs.org/@svgdotjs/svg.resize.js/-/svg.resize.js-2.0.5.tgz" + integrity sha512-4heRW4B1QrJeENfi7326lUPYBCevj78FJs8kfeDxn5st0IYPIRXoTtOSYvTzFWgaWWXd3YCDE6ao4fmv91RthA== + +"@svgdotjs/svg.select.js@^4.0.1": + version "4.0.2" + resolved "https://registry.npmjs.org/@svgdotjs/svg.select.js/-/svg.select.js-4.0.2.tgz" + integrity sha512-5gWdrvoQX3keo03SCmgaBbD+kFftq0F/f2bzCbNnpkkvW6tk4rl4MakORzFuNjvXPWwB4az9GwuvVxQVnjaK2g== + +"@swc/core-win32-x64-msvc@1.11.16": + version "1.11.16" + resolved "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.16.tgz" + integrity sha512-/ibq/YDc3B5AROkpOKPGxVkSyCKOg+ml8k11RxrW7FAPy6a9y5y9KPcWIqV74Ahq4RuaMNslTQqHWAGSm0xJsQ== + +"@swc/core@^1.11.11": + version "1.11.16" + resolved "https://registry.npmjs.org/@swc/core/-/core-1.11.16.tgz" + integrity sha512-wgjrJqVUss8Lxqilg0vkiE0tkEKU3mZkoybQM1Ehy+PKWwwB6lFAwKi20cAEFlSSWo8jFR8hRo19ZELAoLDowg== + dependencies: + "@swc/counter" "^0.1.3" + "@swc/types" "^0.1.21" + optionalDependencies: + "@swc/core-darwin-arm64" "1.11.16" + "@swc/core-darwin-x64" "1.11.16" + "@swc/core-linux-arm-gnueabihf" "1.11.16" + "@swc/core-linux-arm64-gnu" "1.11.16" + "@swc/core-linux-arm64-musl" "1.11.16" + "@swc/core-linux-x64-gnu" "1.11.16" + "@swc/core-linux-x64-musl" "1.11.16" + "@swc/core-win32-arm64-msvc" "1.11.16" + "@swc/core-win32-ia32-msvc" "1.11.16" + "@swc/core-win32-x64-msvc" "1.11.16" + +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/helpers@*", "@swc/helpers@^0.5.0": + version "0.5.23" + resolved "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz" + integrity sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw== + dependencies: + tslib "^2.8.0" + +"@swc/types@^0.1.21": + version "0.1.21" + resolved "https://registry.npmjs.org/@swc/types/-/types-0.1.21.tgz" + integrity sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ== + dependencies: + "@swc/counter" "^0.1.3" + +"@tanstack/query-core@5.101.0": + version "5.101.0" + resolved "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.0.tgz" + integrity sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow== + +"@tanstack/react-query@^5.101.0": + version "5.101.0" + resolved "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.0.tgz" + integrity sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg== + dependencies: + "@tanstack/query-core" "5.101.0" + +"@types/estree@^1.0.6", "@types/estree@1.0.9": + version "1.0.9" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz" + integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg== + +"@types/json-logic-js@^2.0.8": + version "2.0.8" + resolved "https://registry.npmjs.org/@types/json-logic-js/-/json-logic-js-2.0.8.tgz" + integrity sha512-WgNsDPuTPKYXl0Jh0IfoCoJoAGGYZt5qzpmjuLSEg7r0cKp/kWtWp0HAsVepyPSPyXiHo6uXp/B/kW/2J1fa2Q== + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/node@^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node@^22.14.0": + version "22.14.0" + resolved "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz" + integrity sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA== + dependencies: + undici-types "~6.21.0" + +"@types/parse-json@^4.0.0": + version "4.0.2" + resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== + +"@types/prop-types@^15.7.14": + version "15.7.14" + resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz" + integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ== + +"@types/react-dom@^19.1.1": + version "19.1.1" + resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.1.tgz" + integrity sha512-jFf/woGTVTjUJsl2O7hcopJ1r0upqoq/vIOoCj0yLh3RIXxWcljlpuZ+vEBRXsymD1jhfeJrlyTy/S1UW+4y1w== + +"@types/react-transition-group@^4.4.12": + version "4.4.12" + resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz" + integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w== + +"@types/react@*", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^19.0.0", "@types/react@^19.1.0": + version "19.1.0" + resolved "https://registry.npmjs.org/@types/react/-/react-19.1.0.tgz" + integrity sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w== + dependencies: + csstype "^3.0.2" + +"@typescript-eslint/eslint-plugin@^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", "@typescript-eslint/eslint-plugin@8.29.0": + version "8.29.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.0.tgz" + integrity sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.29.0" + "@typescript-eslint/type-utils" "8.29.0" + "@typescript-eslint/utils" "8.29.0" + "@typescript-eslint/visitor-keys" "8.29.0" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^2.0.1" + +"@typescript-eslint/parser@^8.0.0 || ^8.0.0-alpha.0", "@typescript-eslint/parser@^8.29.0", "@typescript-eslint/parser@8.29.0": + version "8.29.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.0.tgz" + integrity sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g== + dependencies: + "@typescript-eslint/scope-manager" "8.29.0" + "@typescript-eslint/types" "8.29.0" + "@typescript-eslint/typescript-estree" "8.29.0" + "@typescript-eslint/visitor-keys" "8.29.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.29.0": + version "8.29.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.0.tgz" + integrity sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw== + dependencies: + "@typescript-eslint/types" "8.29.0" + "@typescript-eslint/visitor-keys" "8.29.0" + +"@typescript-eslint/type-utils@8.29.0": + version "8.29.0" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.0.tgz" + integrity sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q== + dependencies: + "@typescript-eslint/typescript-estree" "8.29.0" + "@typescript-eslint/utils" "8.29.0" + debug "^4.3.4" + ts-api-utils "^2.0.1" + +"@typescript-eslint/types@^8.29.0", "@typescript-eslint/types@8.29.0": + version "8.29.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.0.tgz" + integrity sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg== + +"@typescript-eslint/typescript-estree@8.29.0": + version "8.29.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.0.tgz" + integrity sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow== + dependencies: + "@typescript-eslint/types" "8.29.0" + "@typescript-eslint/visitor-keys" "8.29.0" + 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.0.1" + +"@typescript-eslint/utils@^8.29.0", "@typescript-eslint/utils@8.29.0": + version "8.29.0" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.0.tgz" + integrity sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.29.0" + "@typescript-eslint/types" "8.29.0" + "@typescript-eslint/typescript-estree" "8.29.0" + +"@typescript-eslint/visitor-keys@8.29.0": + version "8.29.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.0.tgz" + integrity sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg== + dependencies: + "@typescript-eslint/types" "8.29.0" + eslint-visitor-keys "^4.2.0" + +"@unrs/resolver-binding-win32-x64-msvc@1.3.3": + version "1.3.3" + resolved "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.3.3.tgz" + integrity sha512-GraLbYqOJcmW1qY3osB+2YIiD62nVf2/bVLHZmrb4t/YSUwE03l7TwcDJl08T/Tm3SVhepX8RQkpzWbag/Sb4w== + +"@vitejs/plugin-react-swc@^3.8.1": + version "3.8.1" + resolved "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.8.1.tgz" + integrity sha512-aEUPCckHDcFyxpwFm0AIkbtv6PpUp3xTb9wYGFjtABynXjCYKkWoxX0AOK9NT9XCrdk6mBBUOeHQS+RKdcNO1A== + dependencies: + "@swc/core" "^1.11.11" + +"@yr/monotone-cubic-spline@^1.0.3": + version "1.0.3" + resolved "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz" + integrity sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.15.0: + version "8.17.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz" + integrity sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg== + +agent-base@6: + version "6.0.2" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.14.0: + version "6.15.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz" + integrity sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== + 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" + +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +apexcharts@^4.5.0, apexcharts@>=4.0.0: + version "4.5.0" + resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-4.5.0.tgz" + integrity sha512-E7ZkrVqPNBUWy/Rmg8DEIqHNBmElzICE/oxOX5Ekvs2ICQUOK/VkEkMH09JGJu+O/EA0NL31hxlmF+wrwrSLaQ== + dependencies: + "@svgdotjs/svg.draggable.js" "^3.0.4" + "@svgdotjs/svg.filter.js" "^3.0.8" + "@svgdotjs/svg.js" "^3.2.4" + "@svgdotjs/svg.resize.js" "^2.0.2" + "@svgdotjs/svg.select.js" "^4.0.1" + "@yr/monotone-cubic-spline" "^1.0.3" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + 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== + dependencies: + call-bound "^1.0.3" + is-array-buffer "^3.0.5" + +array-includes@^3.1.6, array-includes@^3.1.8: + version "3.1.8" + resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + is-string "^1.0.7" + +array.prototype.findlast@^1.2.5: + 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== + 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" + +array.prototype.findlastindex@^1.2.5: + 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== + 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" + +array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: + version "1.3.3" + resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz" + integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.flatmap@^1.3.2, array.prototype.flatmap@^1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + 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" + +arraybuffer.prototype.slice@^1.0.4: + 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== + 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" + +async-function@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz" + integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +available-typed-arrays@^1.0.7: + 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== + dependencies: + possible-typed-array-names "^1.0.0" + +axios@^1.18.0: + version "1.18.0" + resolved "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz" + integrity sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw== + dependencies: + follow-redirects "^1.16.0" + form-data "^4.0.5" + https-proxy-agent "^5.0.1" + proxy-from-env "^2.1.0" + +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.15" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz" + integrity sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.2: + version "2.1.1" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + 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== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + 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" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +class-variance-authority@^0.7.0: + version "0.7.1" + resolved "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz" + integrity sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg== + dependencies: + clsx "^2.1.1" + +clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^1.5.0: + version "1.9.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +cookie@^1.0.1: + version "1.1.1" + resolved "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz" + integrity sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ== + +cosmiconfig@^7.0.0: + version "7.1.0" + resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +csstype@^3.0.2, csstype@^3.1.0, csstype@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-length@^1.0.2: + 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== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-offset@^1.0.1: + 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== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +dayjs@^1.11.13: + version "1.11.13" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.0, debug@~4.4.1, debug@4: + version "4.4.3" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +debug@~4.3.1: + version "4.3.7" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +debug@~4.3.2: + version "4.3.7" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +deep-is@^0.1.3: + 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== + +define-data-property@^1.0.1, define-data-property@^1.1.4: + 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== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.1.3, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +dom-helpers@^5.0.1: + version "5.2.1" + resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +engine.io-client@~6.5.2: + version "6.5.4" + resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz" + integrity sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ== + 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.0.0" + +engine.io-parser@~5.2.1: + version "5.2.3" + resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9: + version "1.23.9" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz" + integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA== + 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.3" + 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.0.0" + es-set-tostringtag "^2.1.0" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.2.7" + get-proto "^1.0.0" + 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-regex "^1.2.1" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.0" + math-intrinsics "^1.1.0" + object-inspect "^1.13.3" + object-keys "^1.1.1" + object.assign "^4.1.7" + own-keys "^1.0.1" + regexp.prototype.flags "^1.5.3" + safe-array-concat "^1.1.3" + safe-push-apply "^1.0.0" + safe-regex-test "^1.1.0" + set-proto "^1.0.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.18" + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-iterator-helpers@^1.2.1: + 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== + 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" + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + 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== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: + 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== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +es-shim-unscopables@^1.0.2, es-shim-unscopables@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz" + integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== + dependencies: + hasown "^2.0.2" + +es-to-primitive@^1.3.0: + 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== + dependencies: + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" + +es-toolkit@^1.32.0, es-toolkit@^1.34.1: + version "1.34.1" + resolved "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.34.1.tgz" + integrity sha512-OA6cd94fJV9bm8dWhIySkWq4xV+rAQnBZUr2dnpXam0QJ8c+hurLbKA8/QooL9Mx4WCAxvIDsiEkid5KPQ5xgQ== + +esbuild@^0.25.0: + version "0.25.12" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz" + integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.12" + "@esbuild/android-arm" "0.25.12" + "@esbuild/android-arm64" "0.25.12" + "@esbuild/android-x64" "0.25.12" + "@esbuild/darwin-arm64" "0.25.12" + "@esbuild/darwin-x64" "0.25.12" + "@esbuild/freebsd-arm64" "0.25.12" + "@esbuild/freebsd-x64" "0.25.12" + "@esbuild/linux-arm" "0.25.12" + "@esbuild/linux-arm64" "0.25.12" + "@esbuild/linux-ia32" "0.25.12" + "@esbuild/linux-loong64" "0.25.12" + "@esbuild/linux-mips64el" "0.25.12" + "@esbuild/linux-ppc64" "0.25.12" + "@esbuild/linux-riscv64" "0.25.12" + "@esbuild/linux-s390x" "0.25.12" + "@esbuild/linux-x64" "0.25.12" + "@esbuild/netbsd-arm64" "0.25.12" + "@esbuild/netbsd-x64" "0.25.12" + "@esbuild/openbsd-arm64" "0.25.12" + "@esbuild/openbsd-x64" "0.25.12" + "@esbuild/openharmony-arm64" "0.25.12" + "@esbuild/sunos-x64" "0.25.12" + "@esbuild/win32-arm64" "0.25.12" + "@esbuild/win32-ia32" "0.25.12" + "@esbuild/win32-x64" "0.25.12" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-import-resolver-node@^0.3.9: + 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== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-import-resolver-typescript@^4.3.1: + version "4.3.1" + resolved "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-4.3.1.tgz" + integrity sha512-/dR9YMomeBlvfuvX5q0C3Y/2PHC9OCRdT2ijFwdfq/4Bq+4m5/lqstEp9k3P6ocha1pCbhoY9fkwVYLmOqR0VQ== + dependencies: + debug "^4.4.0" + get-tsconfig "^4.10.0" + is-bun-module "^2.0.0" + stable-hash "^0.0.5" + tinyglobby "^0.2.12" + unrs-resolver "^1.3.3" + +eslint-module-utils@^2.12.0: + version "2.12.0" + resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz" + integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg== + dependencies: + debug "^3.2.7" + +eslint-plugin-import@*, eslint-plugin-import@^2.31.0: + version "2.31.0" + resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz" + integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== + dependencies: + "@rtsao/scc" "^1.1.0" + array-includes "^3.1.8" + array.prototype.findlastindex "^1.2.5" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.12.0" + hasown "^2.0.2" + is-core-module "^2.15.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.8" + object.groupby "^1.0.3" + object.values "^1.2.0" + semver "^6.3.1" + string.prototype.trimend "^1.0.8" + tsconfig-paths "^3.15.0" + +eslint-plugin-perfectionist@^4.11.0: + version "4.11.0" + resolved "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.11.0.tgz" + integrity sha512-5s+ehXydnLPQpLDj5mJ0CnYj2fQe6v6gKA3tS+FZVBLzwMOh8skH+l+1Gni08rG0SdEcNhJyjQp/mEkDYK8czw== + dependencies: + "@typescript-eslint/types" "^8.29.0" + "@typescript-eslint/utils" "^8.29.0" + natural-orderby "^5.0.0" + +eslint-plugin-react-hooks@^5.2.0: + 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== + +eslint-plugin-react@^7.37.4: + version "7.37.4" + resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz" + integrity sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ== + 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.8" + 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-plugin-unused-imports@^4.1.4: + version "4.1.4" + resolved "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz" + integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== + +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.4.3: + 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== + +eslint-visitor-keys@^4.2.0, eslint-visitor-keys@^4.2.1: + 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== + +eslint@*, "eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", "eslint@^9.0.0 || ^8.0.0", eslint@^9.23.0, eslint@>=7, eslint@>=8.45.0: + version "9.39.4" + resolved "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz" + integrity sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.2" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.5" + "@eslint/js" "9.39.4" + "@eslint/plugin-kit" "^0.4.1" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + ajv "^6.14.0" + 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.5" + natural-compare "^1.4.0" + optionator "^0.9.3" + +espree@^10.0.1, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-target-polyfill@^0.0.4: + version "0.0.4" + resolved "https://registry.npmjs.org/event-target-polyfill/-/event-target-polyfill-0.0.4.tgz" + integrity sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + 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" + +fast-json-stable-stringify@^2.0.0: + 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== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fdir@^6.4.4, fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.4.2" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz" + integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA== + +follow-redirects@^1.16.0: + version "1.16.0" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz" + integrity sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw== + +for-each@^0.3.3, for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +form-data@^4.0.5: + version "4.0.6" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz" + integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.4" + mime-types "^2.1.35" + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== + 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" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + 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.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + +get-tsconfig@^4.10.0: + version "4.10.0" + resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz" + integrity sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globals@^16.0.0: + version "16.0.0" + resolved "https://registry.npmjs.org/globals/-/globals-16.0.0.tgz" + integrity sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A== + +globalthis@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2, hasown@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz" + integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A== + dependencies: + function-bind "^1.1.2" + +hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + +hoist-non-react-statics@^3.3.1: + version "3.3.2" + resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +ignore@^5.2.0, ignore@^5.3.1: + version "5.3.2" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +import-fresh@^3.2.1: + version "3.3.1" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.2" + side-channel "^1.1.0" + +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + 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== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-async-function@^2.0.0: + 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== + 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" + +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== + dependencies: + has-bigints "^1.0.2" + +is-boolean-object@^1.2.1: + version "1.2.2" + resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz" + integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-bun-module@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz" + integrity sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ== + dependencies: + semver "^7.7.1" + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0, is-core-module@^2.15.1, is-core-module@^2.16.0: + version "2.16.1" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-data-view@^1.0.1, is-data-view@^1.0.2: + 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== + dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + is-typed-array "^1.1.13" + +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== + dependencies: + call-bound "^1.0.3" + +is-generator-function@^1.0.10: + version "1.1.0" + resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz" + integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== + dependencies: + call-bound "^1.0.3" + get-proto "^1.0.0" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-map@^2.0.3: + 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== + +is-number-object@^1.1.1: + 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== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-regex@^1.2.1: + 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== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-set@^2.0.3: + 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== + +is-shared-array-buffer@^1.0.4: + 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== + dependencies: + call-bound "^1.0.3" + +is-string@^1.0.7, is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== + dependencies: + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" + +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2, is-weakref@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz" + integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== + dependencies: + call-bound "^1.0.3" + +is-weakset@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== + dependencies: + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +iterator.prototype@^1.1.4: + version "1.1.5" + resolved "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz" + integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== + 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" + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.1: + version "4.2.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz" + integrity sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw== + dependencies: + argparse "^2.0.1" + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + 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== + +json-stable-stringify-without-jsonify@^1.0.1: + 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== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.3.5" + resolved "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash@^4.17.21: + version "4.18.1" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz" + integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== + +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.35: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimal-shared@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/minimal-shared/-/minimal-shared-1.0.7.tgz" + integrity sha512-KP+8dQw43lTkE1vCqjV4dakapCP5sk5trFAo8d2kpJYBZQc3DrGoE1Q9uwKe0hDtbgSwE4zmVYdgmsatF9/JZw== + dependencies: + es-toolkit "^1.32.0" + +minimatch@^3.1.2: + version "3.1.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^3.1.5: + version "3.1.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.4: + version "9.0.9" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz" + integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== + dependencies: + brace-expansion "^2.0.2" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mitt@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz" + integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== + +ms@^2.1.1, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@^3.3.12: + version "3.3.12" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz" + integrity sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +natural-orderby@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz" + integrity sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg== + +npm-run-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz" + integrity sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA== + dependencies: + path-key "^4.0.0" + unicorn-magic "^0.3.0" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4, object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + 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" + +object.entries@^1.1.8: + version "1.1.9" + resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz" + integrity sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw== + 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: + version "2.0.8" + resolved "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +object.groupby@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz" + integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + +object.values@^1.1.6, object.values@^1.2.0, object.values@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz" + integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +optionator@^0.9.3, optionator@^0.9.4: + version "0.9.4" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + 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" + +own-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz" + integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + dependencies: + get-intrinsic "^1.2.6" + object-keys "^1.1.1" + safe-push-apply "^1.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + 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== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + 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== + dependencies: + callsites "^3.0.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +partysocket@^1.1.4: + version "1.3.0" + resolved "https://registry.npmjs.org/partysocket/-/partysocket-1.3.0.tgz" + integrity sha512-1zToNyolZFK/7nuAw/K2bZrNzFqaZyRoCEkS+9vG6WSC5ikrN6qWRe96q6ImU51uptz2r+dAwSkwhJVdQi4LiA== + dependencies: + event-target-polyfill "^0.0.4" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.3.1: + version "2.3.2" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz" + integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== + +"picomatch@^3 || ^4", picomatch@^4.0.2, picomatch@^4.0.4: + version "4.0.4" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz" + integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A== + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +postcss@^8.5.3: + version "8.5.15" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz" + integrity sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A== + dependencies: + nanoid "^3.3.12" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@^3.5.3: + version "3.5.3" + resolved "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz" + integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== + +prop-types@^15.6.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +proxy-from-env@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz" + integrity sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-apexcharts@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.7.0.tgz" + integrity sha512-03oScKJyNLRf0Oe+ihJxFZliBQM9vW3UWwomVn4YVRTN1jsIR58dLWt0v1sb8RwJVHDMbeHiKQueM0KGpn7nOA== + dependencies: + prop-types "^15.8.1" + +"react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18.0.0 || ^19.0.0 || ^19.0.0-0", react-dom@^19.1.0, react-dom@>=16.6.0, react-dom@>=18: + version "19.1.0" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz" + integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g== + dependencies: + scheduler "^0.26.0" + +react-hook-form@^7.55.0, react-hook-form@^7.79.0: + version "7.79.0" + resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.79.0.tgz" + integrity sha512-mhYp/MTmXvzYX6AJcJVko0rktoIhhmRnEouObj4wF5i/tCttgJvnp1+9wRkpITZjDTqpo4IOSJqu0dBlPlV/Lw== + +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^19.0.0: + version "19.1.0" + resolved "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz" + integrity sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg== + +react-router-dom@^7.4.1: + version "7.17.0" + resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.17.0.tgz" + integrity sha512-fyU2yjGups/hE6Xz0I5ZYbVL8Gx29eCjgpHaRaTaVU+OOAdfRX05KsvyRm0GO8YQwOkhpU3MurW1jyMUJn+zSw== + dependencies: + react-router "7.17.0" + +react-router@7.17.0: + version "7.17.0" + resolved "https://registry.npmjs.org/react-router/-/react-router-7.17.0.tgz" + integrity sha512-FDELK7rTMlCHO5+reyXsPlmfr7N1F91lPHsWYfMEGQm/KQ+F4JFM8jGoeQDmDvdTs93Fw9aSilH+uKRb4/jXvQ== + dependencies: + cookie "^1.0.1" + set-cookie-parser "^2.6.0" + +react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + +"react@^16.8.0 || ^17 || ^18 || ^19", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18 || ^19", "react@^18.0.0 || ^19.0.0", "react@^18.0.0 || ^19.0.0 || ^19.0.0-0", react@^19.1.0, react@>=0.13, react@>=16, react@>=16.6.0, react@>=16.8.0, react@>=17, react@>=18: + version "19.1.0" + resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz" + integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: + 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== + 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" + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +regexp.prototype.flags@^1.5.3: + 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== + 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: + version "4.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +resolve@^1.19.0, resolve@^1.22.4: + version "1.22.10" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== + dependencies: + is-core-module "^2.16.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rollup@^4.34.9: + version "4.62.0" + resolved "https://registry.npmjs.org/rollup/-/rollup-4.62.0.tgz" + integrity sha512-nc72Wgq62I7rtDV4izT5/aaS0zxy3kttkinf9586ApknY3jZO9NYsmtc24fUckA0X7Q2v+ML4a15pdUlV5V/jA== + dependencies: + "@types/estree" "1.0.9" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.62.0" + "@rollup/rollup-android-arm64" "4.62.0" + "@rollup/rollup-darwin-arm64" "4.62.0" + "@rollup/rollup-darwin-x64" "4.62.0" + "@rollup/rollup-freebsd-arm64" "4.62.0" + "@rollup/rollup-freebsd-x64" "4.62.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.62.0" + "@rollup/rollup-linux-arm-musleabihf" "4.62.0" + "@rollup/rollup-linux-arm64-gnu" "4.62.0" + "@rollup/rollup-linux-arm64-musl" "4.62.0" + "@rollup/rollup-linux-loong64-gnu" "4.62.0" + "@rollup/rollup-linux-loong64-musl" "4.62.0" + "@rollup/rollup-linux-ppc64-gnu" "4.62.0" + "@rollup/rollup-linux-ppc64-musl" "4.62.0" + "@rollup/rollup-linux-riscv64-gnu" "4.62.0" + "@rollup/rollup-linux-riscv64-musl" "4.62.0" + "@rollup/rollup-linux-s390x-gnu" "4.62.0" + "@rollup/rollup-linux-x64-gnu" "4.62.0" + "@rollup/rollup-linux-x64-musl" "4.62.0" + "@rollup/rollup-openbsd-x64" "4.62.0" + "@rollup/rollup-openharmony-arm64" "4.62.0" + "@rollup/rollup-win32-arm64-msvc" "4.62.0" + "@rollup/rollup-win32-ia32-msvc" "4.62.0" + "@rollup/rollup-win32-x64-gnu" "4.62.0" + "@rollup/rollup-win32-x64-msvc" "4.62.0" + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== + 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" + +safe-push-apply@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz" + integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== + dependencies: + es-errors "^1.3.0" + isarray "^2.0.5" + +safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +scheduler@^0.26.0: + version "0.26.0" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz" + integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.6.0, semver@^7.7.1: + version "7.7.1" + resolved "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + +seroval-plugins@~1.5.4: + version "1.5.4" + resolved "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.5.4.tgz" + integrity sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw== + +seroval@^1.0, seroval@~1.5.4: + version "1.5.4" + resolved "https://registry.npmjs.org/seroval/-/seroval-1.5.4.tgz" + integrity sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw== + +set-cookie-parser@^2.6.0: + version "2.7.2" + resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz" + integrity sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw== + +set-function-length@^1.2.2: + 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== + 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" + +set-function-name@^2.0.2: + 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== + 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: + version "1.0.0" + resolved "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz" + integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== + dependencies: + dunder-proto "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + 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== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + 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" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + 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" + +simplebar-core@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/simplebar-core/-/simplebar-core-1.3.0.tgz" + integrity sha512-LpWl3w0caz0bl322E68qsrRPpIn+rWBGAaEJ0lUJA7Xpr2sw92AkIhg6VWj988IefLXYh50ILatfAnbNoCFrlA== + dependencies: + lodash "^4.17.21" + +simplebar-react@^3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/simplebar-react/-/simplebar-react-3.3.0.tgz" + integrity sha512-sxzy+xRuU41He4tT4QLGYutchtOuye/xxVeq7xhyOiwMiHNK1ZpvbOTyy+7P0i7gfpXLGTJ8Bep8+4Mhdgtz/g== + dependencies: + simplebar-core "^1.3.0" + +socket.io-client@4.7.2: + version "4.7.2" + resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz" + integrity sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.2" + engine.io-client "~6.5.2" + socket.io-parser "~4.2.4" + +socket.io-parser@~4.2.4: + version "4.2.6" + resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz" + integrity sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.4.1" + +solid-floating-ui@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/solid-floating-ui/-/solid-floating-ui-0.3.1.tgz" + integrity sha512-o/QmGsWPS2Z3KidAxP0nDvN7alI7Kqy0kU+wd85Fz+au5SYcnYm7I6Fk3M60Za35azsPX0U+5fEtqfOuk6Ao0Q== + +solid-js@^1.6.12, solid-js@^1.8, solid-js@^1.8.0, solid-js@^1.8.15, solid-js@^1.8.8, solid-js@^1.9.4: + version "1.9.14" + resolved "https://registry.npmjs.org/solid-js/-/solid-js-1.9.14.tgz" + integrity sha512-sAEXC0Kk0S1EDg+8ysEWJDbYhA3RRoEjwuySUGlKIemeo0I5YZfOyumNjNs9Sv3y2nmhD+0rW66ag2HsMuQiGQ== + dependencies: + csstype "^3.1.0" + seroval "~1.5.4" + seroval-plugins "~1.5.4" + +solid-motionone@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/solid-motionone/-/solid-motionone-1.0.4.tgz" + integrity sha512-aqEjgecoO9raDFznu/dEci7ORSmA26Kjj9J4Cn1Gyr0GZuOVdvsNxdxClTL9J40Aq/uYFx4GLwC8n70fMLHiuA== + dependencies: + "@motionone/dom" "^10.17.0" + "@motionone/utils" "^10.17.0" + "@solid-primitives/props" "^3.1.11" + "@solid-primitives/refs" "^1.0.8" + "@solid-primitives/transition-group" "^1.0.5" + csstype "^3.1.3" + +solid-presence@^0.1.8: + version "0.1.8" + resolved "https://registry.npmjs.org/solid-presence/-/solid-presence-0.1.8.tgz" + integrity sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA== + dependencies: + "@corvu/utils" "~0.4.0" + +solid-prevent-scroll@^0.1.4: + version "0.1.10" + resolved "https://registry.npmjs.org/solid-prevent-scroll/-/solid-prevent-scroll-0.1.10.tgz" + integrity sha512-KplGPX2GHiWJLZ6AXYRql4M127PdYzfwvLJJXMkO+CMb8Np4VxqDAg5S8jLdwlEuBis/ia9DKw2M8dFx5u8Mhw== + dependencies: + "@corvu/utils" "~0.4.1" + +source-map-js@^1.2.1: + 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== + +source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +stable-hash@^0.0.5: + version "0.0.5" + resolved "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz" + integrity sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA== + +string.prototype.matchall@^4.0.12: + 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== + 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" + +string.prototype.repeat@^1.0.0: + 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== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trim@^1.2.10: + 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== + 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" + +string.prototype.trimend@^1.0.8, string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +strip-ansi@^7.1.0: + version "7.1.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-json-comments@^3.1.1: + 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== + +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + 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== + +tailwind-merge@^2.4.0: + version "2.6.1" + resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz" + integrity sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ== + +tiny-invariant@^1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== + +tinyglobby@^0.2.12, tinyglobby@^0.2.13: + version "0.2.17" + resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz" + integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + +to-regex-range@^5.0.1: + 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== + dependencies: + is-number "^7.0.0" + +ts-api-utils@^2.0.1: + 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== + +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^2.3.1, tslib@^2.8.0: + version "2.8.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" + +typed-array-byte-length@^1.0.3: + 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== + 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" + +typed-array-byte-offset@^1.0.4: + 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== + 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" + +typed-array-length@^1.0.7: + 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== + 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" + +typescript-eslint@^8.29.0: + version "8.29.0" + resolved "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.29.0.tgz" + integrity sha512-ep9rVd9B4kQsZ7ZnWCVxUE/xDLUUUsRzE0poAeNu+4CkFErLfuvPt/qtm2EpnSyfvsR0S6QzDFSrPCFBwf64fg== + dependencies: + "@typescript-eslint/eslint-plugin" "8.29.0" + "@typescript-eslint/parser" "8.29.0" + "@typescript-eslint/utils" "8.29.0" + +typescript@*, typescript@^5.8.2, typescript@>=4.8.4, "typescript@>=4.8.4 <5.9.0": + version "5.8.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz" + integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== + +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== + dependencies: + call-bound "^1.0.3" + has-bigints "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +unicorn-magic@^0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz" + integrity sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA== + +unrs-resolver@^1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.3.3.tgz" + integrity sha512-PFLAGQzYlyjniXdbmQ3dnGMZJXX5yrl2YS4DLRfR3BhgUsE1zpRIrccp9XMOGRfIHpdFvCn/nr5N1KMVda4x3A== + optionalDependencies: + "@unrs/resolver-binding-darwin-arm64" "1.3.3" + "@unrs/resolver-binding-darwin-x64" "1.3.3" + "@unrs/resolver-binding-freebsd-x64" "1.3.3" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.3.3" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.3.3" + "@unrs/resolver-binding-linux-arm64-gnu" "1.3.3" + "@unrs/resolver-binding-linux-arm64-musl" "1.3.3" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.3.3" + "@unrs/resolver-binding-linux-s390x-gnu" "1.3.3" + "@unrs/resolver-binding-linux-x64-gnu" "1.3.3" + "@unrs/resolver-binding-linux-x64-musl" "1.3.3" + "@unrs/resolver-binding-wasm32-wasi" "1.3.3" + "@unrs/resolver-binding-win32-arm64-msvc" "1.3.3" + "@unrs/resolver-binding-win32-ia32-msvc" "1.3.3" + "@unrs/resolver-binding-win32-x64-msvc" "1.3.3" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +vite-plugin-checker@^0.9.1: + version "0.9.1" + resolved "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.9.1.tgz" + integrity sha512-neH3CSNWdkZ+zi+WPt/0y5+IO2I0UAI0NX6MaXqU/KxN1Lz6np/7IooRB6VVAMBa4nigqm1GRF6qNa4+EL5jDQ== + dependencies: + "@babel/code-frame" "^7.26.2" + chokidar "^4.0.3" + npm-run-path "^6.0.0" + picocolors "^1.1.1" + picomatch "^4.0.2" + strip-ansi "^7.1.0" + tiny-invariant "^1.3.3" + tinyglobby "^0.2.12" + vscode-uri "^3.1.0" + +"vite@^4 || ^5 || ^6", vite@^6.2.5, vite@>=2.0.0: + version "6.4.3" + resolved "https://registry.npmjs.org/vite/-/vite-6.4.3.tgz" + integrity sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.4" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.13" + optionalDependencies: + fsevents "~2.3.3" + +vscode-uri@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz" + integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ== + +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== + 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" + +which-builtin-type@^1.2.1: + 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== + 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" + +which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-typed-array@^1.1.16, which-typed-array@^1.1.18: + version "1.1.19" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== + 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.1: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +ws@~8.17.1: + version "8.17.1" + resolved "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +xmlhttprequest-ssl@~2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz" + integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== + +yaml@^1.10.0: + version "1.10.3" + resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz" + integrity sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA== + +yaml@^2.4.2: + version "2.9.0" + resolved "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz" + integrity sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod@^4.4.3: + version "4.4.3" + resolved "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz" + integrity sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==