commit 11e73da69362c28c8fe39f84a86490fe73dc3922 Author: root Date: Sun Jul 5 13:59:41 2026 +0330 Initial commit - modstagram-next diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..517252d --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..5e4086a --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmmirror.com/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a046502 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +FROM node:18-alpine AS builder + +WORKDIR /app + +COPY package*.json ./ +RUN npm install + +COPY . . + +RUN npm run build + +FROM node:18-alpine AS runner + +WORKDIR /app + +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/public ./public +COPY --from=builder /app/package*.json ./ +COPY --from=builder /app/node_modules ./node_modules + +ENV NODE_ENV=production +ENV HOST=0.0.0.0 + +EXPOSE 3000 + +CMD ["npm", "start"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf26081 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/components.json b/components.json new file mode 100644 index 0000000..b7b9791 --- /dev/null +++ b/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..57929a3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3.8' + +services: + next-app: + build: . + container_name: modstagram-next + restart: unless-stopped + ports: + - "3004:3000" + environment: + - NODE_ENV=production + - HOST=0.0.0.0 + volumes: + - ./:/app + - /app/node_modules + - /app/.next diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..91b68f2 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,43 @@ + +import { dirname } from "path"; +import { fileURLToPath } from "url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), + { + ignores: [ + "node_modules/**", + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ], + }, +]; + +export default eslintConfig; + +// import { dirname } from "path"; +// import { fileURLToPath } from "url"; +// import { FlatCompat } from "@eslint/eslintrc"; + +// const __filename = fileURLToPath(import.meta.url); +// const __dirname = dirname(__filename); + +// const compat = new FlatCompat({ +// baseDirectory: __dirname, +// }); + +// const eslintConfig = [ +// ...compat.extends("next/core-web-vitals", "next/typescript"), +// ]; + +// export default eslintConfig; diff --git a/google04b13fd53edd8dd1.html b/google04b13fd53edd8dd1.html new file mode 100644 index 0000000..b96c9f4 --- /dev/null +++ b/google04b13fd53edd8dd1.html @@ -0,0 +1 @@ +google-site-verification: google04b13fd53edd8dd1.html \ No newline at end of file diff --git a/next-sitemap.config.js b/next-sitemap.config.js new file mode 100644 index 0000000..991bdfc --- /dev/null +++ b/next-sitemap.config.js @@ -0,0 +1,218 @@ +// next-sitemap.config.js +/** @type {import('next-sitemap').IConfig} */ +module.exports = { + siteUrl: 'https://modstagram.com', // دامنه اصلی سایت شما + generateRobotsTxt: true, // تولید فایل robots.txt + sitemapSize: 7000, // حداکثر تعداد URL در هر فایل سایت‌مپ + changefreq: 'daily', // فرکانس پیش‌فرض تغییر صفحات + priority: 0.7, // اولویت پیش‌فرض صفحات + + // تابع transform برای فیلتر کردن و تنظیمات خاص هر مسیر + transform: async (config, path) => { + // مسیرهایی که نباید در سایت‌مپ باشند و نیازی به ایندکس شدن ندارند + const excludedPaths = [ + '/settings', + '/auth', + '/new-post', + '/offer', + '/private/', // مسیرهای خصوصی + // صفحات مربوط به پرداخت و ثبت‌نام/ورود + '/projects/payment/success', + '/projects/payment/failed', + '/billboards/payment/success', + '/billboards/payment/failed', + '/forget-password', + '/change-passowrd', + '/login-with-username', + '/login', + '/register-otp', + '/verify-otp', + '/register', + '/forget-password-otp', + '/register/password', + '/register/fullname', + '/register/usertype', + '/register/username', + '/verify/avatar', + '/verify/auth', + '/verify/colors', + '/verify/confirm', + '/verify/expertise', + '/verify/gender', + '/verify/national-cart', + '/verify/location', + '/verify/public-relations', + '/verify/cooperation-type', + '/verify/services', + '/verify/sizes', + '/new-project', // اگر این یک صفحه فرم داخلی است که نیازی به ایندکس شدن ندارد + '/billboards/new', // اگر این یک صفحه فرم داخلی است که نیازی به ایندکس شدن ندارد + '/search', // اگر صفحه جستجو محتوای قابل ایندکس ندارد + ]; + + // اگر مسیر در لیست excludedPaths باشد، آن را از سایت‌مپ حذف کن + if (excludedPaths.some(p => path.startsWith(p))) { + return null; + } + + let pageChangefreq = config.changefreq; + let pagePriority = config.priority; + + // تنظیمات خاص برای مسیرهای مختلف + if (path.startsWith('/users/')) { // مسیر برای پروفایل‌های کاربران + pageChangefreq = 'weekly'; + pagePriority = 0.6; + } + if (path.startsWith('/projects/') || path.startsWith('/billboards/')) { + pageChangefreq = 'daily'; + pagePriority = 0.8; + } + if (path === '/') { // صفحه اصلی + pageChangefreq = 'daily'; + pagePriority = 1.0; + } + if (path === '/about-us') { // صفحه درباره ما + pageChangefreq = 'monthly'; + pagePriority = 0.8; + } + + return { + loc: path, // آدرس کامل صفحه + changefreq: pageChangefreq, // فرکانس تغییر صفحه + priority: pagePriority, // اولویت صفحه + lastmod: config.autoLastmod ? new Date().toISOString() : undefined, // تاریخ آخرین تغییر + alternateRefs: config.alternateRefs ?? [], + }; + }, + + // تابع additionalPaths برای اضافه کردن مسیرهای داینامیک از API + additionalPaths: async (config) => { + const paths = []; + const BASE_URL_API = "https://app.modstagram.ir/api/v1"; // آدرس پایه API شما + paths.push({ + loc: '/', + changefreq: 'daily', + priority: 1.0 + }); + paths.push({ + loc: '/projects', + changefreq: 'daily', + priority: 0.9 + }); + paths.push({ + loc: '/billboards', + changefreq: 'daily', // یا weekly بسته به میزان تغییر محتوا + priority: 0.9 + }); + try { + // واکشی داده‌های پروژه‌ها + const projectsRes = await fetch(`${BASE_URL_API}/projects?limit=500`); + const projectsData = await projectsRes.json(); + if (projectsData && Array.isArray(projectsData.projects)) { + projectsData.projects.forEach((project) => { + if (project.id && project.title) { + paths.push({ + // مسیر پروژه‌ها (با استفاده از تمپلیت لیتِرال صحیح) + loc: `/projects/${project.id}/${encodeURIComponent(project.title)}`, + changefreq: 'daily', + priority: 0.8 + }); + } + }); + } + + // واکشی داده‌های بیلبوردها + const billboardsRes = await fetch(`${BASE_URL_API}/advertising/web?limit=500`); + const billboardsData = await billboardsRes.json(); + if (billboardsData && Array.isArray(billboardsData.advertisings)) { + billboardsData.advertisings.forEach((billboard) => { + if (billboard._id && billboard.title) { + paths.push({ + // مسیر بیلبوردها (با استفاده از تمپلیت لیتِرال صحیح) + loc: `/billboards/${billboard._id}/${encodeURIComponent(billboard.title)}`, + changefreq: 'daily', + priority: 0.8 + }); + } + }); + } + + // واکشی داده‌های کاربران (مدل‌ها) + const usersRes = await fetch(`${BASE_URL_API}/users/web?limit=500`); + const usersData = await usersRes.json(); + if (usersData && Array.isArray(usersData.users)) { + usersData.users.forEach((user) => { + if (user.user_name) { + paths.push({ + // مسیر پروفایل کاربران (مسیر در Next.js شما /users/[username] است) + loc: `/users/${encodeURIComponent(user.user_name)}`, + changefreq: 'weekly', + priority: 0.6 + }); + } + }); + } + + } catch (error) { + // لاگ کردن خطا در صورت مشکل در واکشی داده‌ها از API + console.error('Error fetching additional paths for sitemap:', error); + } + + return paths; // بازگرداندن آرایه‌ای از مسیرهای داینامیک + }, + + // تنظیمات مربوط به فایل robots.txt + robotsTxtOptions: { + policies: [ + { + userAgent: '*', // اعمال سیاست‌ها برای همه ربات‌ها + allow: '/', // اجازه دسترسی به کل سایت + disallow: [ + '/api/', // مسیرهای API + '/_next/', // فایل‌های داخلی Next.js + '/settings', // صفحات تنظیمات + '/auth', // صفحات احراز هویت (ورود، ثبت‌نام) + '/private/', // مسیرهای خصوصی موجود + '/new-post', // صفحات ایجاد پست جدید + '/offer', // صفحات پیشنهاد + // اضافه کردن مسیرهای پرداخت و ثبت‌نام/ورود به disallow + '/projects/payment/success', + '/projects/payment/failed', + '/billboards/payment/success', + '/billboards/payment/failed', + '/forget-password', + '/change-passowrd', + '/login-with-username', + '/login', + '/register-otp', + '/verify-otp', + '/register', + '/forget-password-otp', + '/register/password', + '/register/fullname', + '/register/usertype', + '/register/username', + '/verify/avatar', + '/verify/auth', + '/verify/colors', + '/verify/confirm', + '/verify/expertise', + '/verify/gender', + '/verify/national-cart', + '/verify/location', + '/verify/public-relations', + '/verify/cooperation-type', + '/verify/services', + '/verify/sizes', + '/new-project', + '/billboards/new', + '/search', // اگر این صفحه برای ایندکس شدن نامناسب است + ], + }, + ], + // اضافه کردن آدرس سایت‌مپ به robots.txt + additionalSitemaps: [ + 'https://modstagram.com/sitemap.xml', + ], + }, +}; \ No newline at end of file diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..4254575 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,74 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + // ۱. نادیده گرفتن خطاهای بیلد + eslint: { + ignoreDuringBuilds: true, + }, + typescript: { + ignoreBuildErrors: true, + }, + + // ۲. تنظیمات تصاویر + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'app.modstagram.ir', + port: '', + pathname: '/**', + }, + { + protocol: 'https', + hostname: 'blog.modstagram.com', // اجازه دادن به نمایش تصاویر وبلاگ + port: '', + pathname: '/**', + }, + { + protocol: 'http', + hostname: 'localhost', + port: '', + pathname: '/**', + }, + ], + formats: ['image/avif', 'image/webp'], + deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], + imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], + minimumCacheTTL: 31536000, + }, + + // ۳. هدایت ترافیک ساب‌فولدر به وردپرس (بخش جدید) + async rewrites() { + return [ + { + source: '/blog', + destination: 'https://blog.modstagram.com/blog', + }, + { + source: '/blog/:path*', + destination: 'https://blog.modstagram.com/blog/:path*', + }, + ]; + }, + + // ۴. تنظیمات هدرها + async headers() { + return [ + { + source: '/(.*)', + headers: [ + { key: 'X-DNS-Prefetch-Control', value: 'on' }, + { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' }, + { key: 'X-XSS-Protection', value: '1; mode=block' }, + { key: 'X-Frame-Options', value: 'SAMEORIGIN' }, + { key: 'X-Content-Type-Options', value: 'nosniff' }, + { key: 'Referrer-Policy', value: 'origin-when-cross-origin' }, + { key: 'Cache-Control', value: 'public, s-maxage=1, stale-while-revalidate=59' }, + ], + }, + ]; + }, + + reactStrictMode: false, +}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..56a7d7c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,12575 @@ +{ + "name": "modstagram-next", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "modstagram-next", + "version": "0.1.0", + "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", + "@headlessui/react": "^2.2.8", + "@hookform/resolvers": "^5.2.2", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-navigation-menu": "^1.2.14", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "^1.3.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.6", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.2.6", + "@radix-ui/react-tabs": "^1.1.13", + "@radix-ui/react-toast": "^1.2.15", + "@radix-ui/react-toggle": "^1.1.10", + "@radix-ui/react-toggle-group": "^1.1.11", + "@radix-ui/react-tooltip": "^1.2.8", + "@radix-ui/themes": "^3.2.1", + "@shadcn/ui": "^0.0.4", + "@tabler/icons-react": "^3.34.1", + "@tanstack/react-query": "^5.87.1", + "@tanstack/react-table": "^8.21.3", + "@vitalets/google-translate-api": "^9.2.1", + "axios": "^1.7.9", + "chart.js": "^4.5.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "embla-carousel-react": "^8.6.0", + "formik": "^2.4.6", + "framer-motion": "^12.23.12", + "i18next": "^25.3.6", + "i18next-browser-languagedetector": "^8.2.0", + "i18next-http-backend": "^3.0.2", + "jalali-moment": "^3.3.11", + "js-cookie": "^3.0.5", + "jszip": "^3.10.1", + "leaflet": "^1.9.4", + "lodash": "^4.17.21", + "lucide-react": "^0.541.0", + "mapbox-gl": "^3.9.3", + "next": "^15.5.2", + "next-i18next": "^15.4.2", + "next-seo": "^6.8.0", + "next-sitemap": "^4.2.3", + "next-themes": "^0.4.6", + "node-fetch": "^3.3.2", + "openai": "^5.21.0", + "radix-ui": "^1.4.3", + "rc-rate": "^2.13.0", + "react": "^18.3.1", + "react-chartjs-2": "^5.3.0", + "react-confetti": "^6.4.0", + "react-dom": "^18.3.1", + "react-easy-crop": "^5.5.0", + "react-hook-form": "^7.65.0", + "react-hot-toast": "^2.5.1", + "react-i18next": "^15.6.1", + "react-icons": "^5.5.0", + "react-leaflet": "^4.2.1", + "react-map-gl": "^7.1.8", + "react-modal": "^3.16.3", + "react-multi-date-picker": "^4.5.2", + "react-otp-input": "^3.1.1", + "react-slick": "^0.31.0", + "react-use": "^17.6.0", + "recharts": "^2.15.4", + "sharp": "^0.34.5", + "slick-carousel": "^1.8.1", + "socket.io-client": "^4.8.1", + "sonner": "^2.0.7", + "swiper": "^11.2.2", + "tailwind-merge": "^3.3.1", + "tailwindcss-rtl": "^0.9.0", + "three": "^0.180.0", + "translate-google": "^1.5.0", + "uuid": "^11.1.0", + "vaul": "^1.1.2", + "yet-another-react-lightbox": "^3.25.0", + "yup": "^1.7.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@ffmpeg/ffmpeg": "^0.12.10", + "@ffmpeg/util": "^0.12.1", + "@tailwindcss/postcss": "^4.2.4", + "@types/js-cookie": "^3.0.6", + "@types/leaflet": "^1.9.20", + "@types/lodash": "^4.17.20", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "@types/react-modal": "^3.16.3", + "@types/react-slick": "^0.23.13", + "autoprefixer": "^10.4.21", + "eslint": "^9", + "eslint-config-next": "15.1.5", + "postcss": "^8.5.14", + "tailwindcss": "^4.2.4", + "ts-node": "^10.9.2", + "tw-animate-css": "^1.3.8", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@corex/deepmerge": { + "version": "4.0.43", + "resolved": "https://registry.npmjs.org/@corex/deepmerge/-/deepmerge-4.0.43.tgz", + "integrity": "sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ==" + }, + "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/@dnd-kit/accessibility": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", + "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz", + "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", + "license": "MIT", + "dependencies": { + "@dnd-kit/accessibility": "^3.1.1", + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/modifiers": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz", + "integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/sortable": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", + "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", + "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "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, + "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, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "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, + "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.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "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, + "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, + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@ffmpeg/ffmpeg": { + "version": "0.12.15", + "resolved": "https://registry.npmjs.org/@ffmpeg/ffmpeg/-/ffmpeg-0.12.15.tgz", + "integrity": "sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ffmpeg/types": "^0.12.4" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@ffmpeg/types": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@ffmpeg/types/-/types-0.12.4.tgz", + "integrity": "sha512-k9vJQNBGTxE5AhYDtOYR5rO5fKsspbg51gbcwtbkw2lCdoIILzklulcjJfIDwrtn7XhDeF2M+THwJ2FGrLeV6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.x" + } + }, + "node_modules/@ffmpeg/util": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@ffmpeg/util/-/util-0.12.2.tgz", + "integrity": "sha512-ouyoW+4JB7WxjeZ2y6KpRvB+dLp7Cp4ro8z0HIVpZVCM7AwFlHa0c4R8Y/a4M3wMqATpYKhC7lSFHQ0T11MEDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.x" + } + }, + "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/react": { + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "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/@headlessui/react": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.10.tgz", + "integrity": "sha512-5pVLNK9wlpxTUTy9GpgbX/SdcRh+HBnPktjM2wbiLTH4p+2EPHBO1aoSryUCuKUIItdDWO9ITlhUL8UnUN/oIA==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.20.2", + "@react-aria/interactions": "^3.25.0", + "@tanstack/react-virtual": "^3.13.9", + "use-sync-external-store": "^1.5.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@hookform/resolvers": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz", + "integrity": "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==", + "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, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "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, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "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==", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@internationalized/date": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.1.tgz", + "integrity": "sha512-6IedsVWXyq4P9Tj+TxuU8WGWM70hYLl12nbYU8jkikVpa6WXapFazPUcHUMDMoWftIDE2ILDkFFte6W2nFCkRQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.6.6", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.6.tgz", + "integrity": "sha512-iFgmQaXHE0vytNfpLZWOC2mEJCBRzcUxt53Xf/yCXG93lRvqas237i3r7X4RKMwO3txiyZD4mQjKAByFv6UGSQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/string": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.8.tgz", + "integrity": "sha512-NdbMQUSfXLYIQol5VyMtinm9pZDciiMfN7RtmSuSB78io1hqwJ0naYfxyW6vgxWBkzWymQa/3uLDlbfmshtCaA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.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, + "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, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==" + }, + "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, + "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==", + "license": "MIT" + }, + "node_modules/@mapbox/jsonlint-lines-primitives": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz", + "integrity": "sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@mapbox/mapbox-gl-supported": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-3.0.0.tgz", + "integrity": "sha512-2XghOwu16ZwPJLOFVuIOaLbN0iKMn867evzXFyf0P22dqugezfJwLmdanAgU25ITvz1TvOfVP4jsDImlDJzcWg==" + }, + "node_modules/@mapbox/point-geometry": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-1.1.0.tgz", + "integrity": "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==" + }, + "node_modules/@mapbox/tiny-sdf": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.7.tgz", + "integrity": "sha512-25gQLQMcpivjOSA40g3gO6qgiFPDpWRoMfd+G/GoppPIeP6JDaMMkMrEJnMZhKyyS6iKwVt5YKu02vCUyJM3Ug==" + }, + "node_modules/@mapbox/unitbezier": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz", + "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==" + }, + "node_modules/@mapbox/vector-tile": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-2.0.4.tgz", + "integrity": "sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg==", + "dependencies": { + "@mapbox/point-geometry": "~1.1.0", + "@types/geojson": "^7946.0.16", + "pbf": "^4.0.1" + } + }, + "node_modules/@mapbox/whoots-js": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz", + "integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@maplibre/maplibre-gl-style-spec": { + "version": "19.3.3", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz", + "integrity": "sha512-cOZZOVhDSulgK0meTsTkmNXb1ahVvmTmWmfx9gRBwc6hq98wS9JP35ESIoNq3xqEan+UN+gn8187Z6E4NKhLsw==", + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "~2.0.2", + "@mapbox/unitbezier": "^0.0.1", + "json-stringify-pretty-compact": "^3.0.0", + "minimist": "^1.2.8", + "rw": "^1.3.3", + "sort-object": "^3.0.3" + }, + "bin": { + "gl-style-format": "dist/gl-style-format.mjs", + "gl-style-migrate": "dist/gl-style-migrate.mjs", + "gl-style-validate": "dist/gl-style-validate.mjs" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "15.5.9", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.9.tgz", + "integrity": "sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.1.5", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.5.tgz", + "integrity": "sha512-3cCrXBybsqe94UxD6DBQCYCCiP9YohBMgZ5IzzPYHmPzj8oqNlhBii5b6o1HDDaRHdz2pVnSsAROCtrczy8O0g==", + "dev": true, + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.7.tgz", + "integrity": "sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.7.tgz", + "integrity": "sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.7.tgz", + "integrity": "sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.7.tgz", + "integrity": "sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.7.tgz", + "integrity": "sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.7.tgz", + "integrity": "sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.7.tgz", + "integrity": "sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.7.tgz", + "integrity": "sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "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==", + "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==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@radix-ui/colors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/colors/-/colors-3.0.0.tgz", + "integrity": "sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg==", + "license": "MIT" + }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-accessible-icon": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accessible-icon/-/react-accessible-icon-1.1.7.tgz", + "integrity": "sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-visually-hidden": "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-accordion": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@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-alert-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", + "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@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-alert-dialog/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==", + "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-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.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-aspect-ratio": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.7.tgz", + "integrity": "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.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-avatar": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz", + "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.3", + "@radix-ui/react-primitive": "2.1.4", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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-avatar/node_modules/@radix-ui/react-context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "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-avatar/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "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-checkbox": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "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-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@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-collection/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==", + "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-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==", + "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-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "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-context-menu": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", + "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@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-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.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-dialog/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==", + "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-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "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-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "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-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@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-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "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-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "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-form": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-form/-/react-form-0.1.8.tgz", + "integrity": "sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-primitive": "2.1.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-form/node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.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-hover-card": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz", + "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@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-icons": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz", + "integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==", + "license": "MIT", + "peerDependencies": { + "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "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-label": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz", + "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "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-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "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-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.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-menu/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==", + "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-menubar": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz", + "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@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-navigation-menu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz", + "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "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-one-time-password-field": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-one-time-password-field/-/react-one-time-password-field-0.1.8.tgz", + "integrity": "sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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-password-toggle-field": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-password-toggle-field/-/react-password-toggle-field-0.1.3.tgz", + "integrity": "sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-is-hydrated": "0.1.0" + }, + "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-popover": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.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-popover/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==", + "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-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "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-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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-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==", + "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-primitive/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==", + "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-progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz", + "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.3", + "@radix-ui/react-primitive": "2.1.4" + }, + "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-progress/node_modules/@radix-ui/react-context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "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-progress/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "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-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "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-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@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-scroll-area": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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-select": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.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-select/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==", + "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-separator": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", + "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "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-separator/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "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-slider": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", + "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "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.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "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-switch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "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-tabs": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@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-toast": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz", + "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-visually-hidden": "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-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==", + "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-toggle-group": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz", + "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-toggle": "1.1.10", + "@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-toolbar": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toolbar/-/react-toolbar-1.1.11.tgz", + "integrity": "sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-separator": "1.1.7", + "@radix-ui/react-toggle-group": "1.1.11" + }, + "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-toolbar/node_modules/@radix-ui/react-separator": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.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-tooltip": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "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-tooltip/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==", + "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-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "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-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==", + "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==", + "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-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "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-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "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==", + "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-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "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-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "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-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "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-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.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/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@radix-ui/themes": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@radix-ui/themes/-/themes-3.3.0.tgz", + "integrity": "sha512-I0/h2CRNTpYNB7Mi3xFIvSsQq5a108d7kK8dTO5zp5b9HR5QJXKag6B8tjpz2ITkVYkFdkGk45doNkSr7OxwNw==", + "license": "MIT", + "dependencies": { + "@radix-ui/colors": "^3.0.0", + "classnames": "^2.3.2", + "radix-ui": "^1.1.3", + "react-remove-scroll-bar": "^2.3.8" + }, + "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/@react-aria/focus": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.22.0.tgz", + "integrity": "sha512-ZfDOVuVhqDsM9mkNji3QUZ/d40JhlVgXrDkrfXylM1035QCrcTHN7m2DpbE95sU2A8EQb4wikvt5jM6K/73BPg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0", + "react-aria": "3.48.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.28.0.tgz", + "integrity": "sha512-OXwdU1EWFdMxmr/K1CXNGJzmNlCClByb+PuCaqUyzBymHPCGVhawirLIon/CrIN5psh3AiWpHSh4H0WeJdVpng==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.34.0", + "@swc/helpers": "^0.5.0", + "react-aria": "3.48.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-leaflet/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@react-types/shared": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.34.0.tgz", + "integrity": "sha512-gp6xo/s2lX54AlTjOiqwDnxA7UW79BNvI9dB9pr3LZTzRKCd1ZA+ZbgKw/ReIiWuvvVw/8QFJpnqeeFyLocMcQ==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "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 + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", + "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==", + "dev": true + }, + "node_modules/@shadcn/ui": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@shadcn/ui/-/ui-0.0.4.tgz", + "integrity": "sha512-0dtu/5ApsOZ24qgaZwtif8jVwqol7a4m1x5AxPuM1k5wxhqU7t/qEfBGtaSki1R8VlbTQfCj5PAlO45NKCa7Gg==", + "license": "MIT", + "dependencies": { + "chalk": "5.2.0", + "commander": "^10.0.0", + "execa": "^7.0.0", + "fs-extra": "^11.1.0", + "node-fetch": "^3.3.0", + "ora": "^6.1.2", + "prompts": "^2.4.2", + "zod": "^3.20.2" + }, + "bin": { + "ui": "dist/index.js" + } + }, + "node_modules/@shadcn/ui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@shadcn/ui/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@shadcn/ui/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@shadcn/ui/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@shadcn/ui/node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@shadcn/ui/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@shadcn/ui/node_modules/log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "license": "MIT", + "dependencies": { + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@shadcn/ui/node_modules/ora": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.3.1.tgz", + "integrity": "sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.0.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.6.1", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.1.0", + "log-symbols": "^5.1.0", + "stdin-discarder": "^0.1.0", + "strip-ansi": "^7.0.1", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@shadcn/ui/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@shadcn/ui/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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "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==" + }, + "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/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tabler/icons": { + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.42.0.tgz", + "integrity": "sha512-h0nFIRgwrE/9iVgN+GuLijbiLIBWJ3chNvIWhqUZhy4D9fv3tkoQ3EYFAvxvfdvQUNNVAhJhj+ar54y6t016Vg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + } + }, + "node_modules/@tabler/icons-react": { + "version": "3.42.0", + "resolved": "https://registry.npmjs.org/@tabler/icons-react/-/icons-react-3.42.0.tgz", + "integrity": "sha512-WvKhHYLdJaZbiY4Jm31fmTbzIwxokXcE1HM/m9rmXvh7UoHG4mM8n+9NOB6xEwB5SZQ+G/Z102eMj1F3NqDMVg==", + "license": "MIT", + "dependencies": { + "@tabler/icons": "3.42.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + }, + "peerDependencies": { + "react": ">= 16" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.4.tgz", + "integrity": "sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.19.0", + "jiti": "^2.6.1", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.2.4" + } + }, + "node_modules/@tailwindcss/node/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==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.4.tgz", + "integrity": "sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.2.4", + "@tailwindcss/oxide-darwin-arm64": "4.2.4", + "@tailwindcss/oxide-darwin-x64": "4.2.4", + "@tailwindcss/oxide-freebsd-x64": "4.2.4", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.4", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.4", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.4", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.4", + "@tailwindcss/oxide-linux-x64-musl": "4.2.4", + "@tailwindcss/oxide-wasm32-wasi": "4.2.4", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.4", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.4" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.4.tgz", + "integrity": "sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.4.tgz", + "integrity": "sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.4.tgz", + "integrity": "sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.4.tgz", + "integrity": "sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.4.tgz", + "integrity": "sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.4.tgz", + "integrity": "sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.4.tgz", + "integrity": "sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.4.tgz", + "integrity": "sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.4.tgz", + "integrity": "sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.4.tgz", + "integrity": "sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.8.1", + "@emnapi/runtime": "^1.8.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.1", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.4.tgz", + "integrity": "sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.4.tgz", + "integrity": "sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/@tailwindcss/postcss/-/postcss-4.2.4.tgz", + "integrity": "sha512-wgAVj6nUWAolAu8YFvzT2cTBIElWHkjZwFYovF+xsqKsW2ADxM/X2opxj5NsF/qVccAOjRNe8X2IdPzMsWyHTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.2.4", + "@tailwindcss/oxide": "4.2.4", + "postcss": "^8.5.6", + "tailwindcss": "4.2.4" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.90.12", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.12.tgz", + "integrity": "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.90.12", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.12.tgz", + "integrity": "sha512-graRZspg7EoEaw0a8faiUASCyJrqjKPdqJ9EwuDRUF9mEYJ1YPczI9H+/agJ0mOJkPCJDk0lsz5QTrLZ/jQ2rg==", + "dependencies": { + "@tanstack/query-core": "5.90.12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@tanstack/react-table": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", + "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", + "license": "MIT", + "dependencies": { + "@tanstack/table-core": "8.21.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/@tanstack/react-virtual": { + "version": "3.13.24", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.24.tgz", + "integrity": "sha512-aIJvz5OSkhNIhZIpYivrxrPTKYsjW9Uzy+sP/mx0S3sev2HyvPb7xmjbYvokzEpfgYHy/HjzJ2zFAETuUfgCpg==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.14.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", + "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.14.0.tgz", + "integrity": "sha512-JLANqGy/D6k4Ujmh8Tr25lGimuOXNiaVyXaCAZS0W+1390sADdGnyUdSWNIfd49gebtIxGMij4IktRVzrdr12Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "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.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==" + }, + "node_modules/@types/geojson-vt": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/geojson-vt/-/geojson-vt-3.2.5.tgz", + "integrity": "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz", + "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==", + "dependencies": { + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", + "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==", + "license": "MIT" + }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "dev": true + }, + "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 + }, + "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 + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/leaflet": { + "version": "1.9.21", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz", + "integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==", + "dev": true + }, + "node_modules/@types/mapbox__point-geometry": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz", + "integrity": "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==" + }, + "node_modules/@types/mapbox-gl": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-3.4.1.tgz", + "integrity": "sha512-NsGKKtgW93B+UaLPti6B7NwlxYlES5DpV5Gzj9F75rK5ALKsqSk15CiEHbOnTr09RGbr6ZYiCdI+59NNNcAImg==", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/node": { + "version": "20.19.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.26.tgz", + "integrity": "sha512-0l6cjgF0XnihUpndDhk+nyD3exio3iKaYROSgvh/qSevPXax3L8p5DBRFjbvalnwatGgHEQn2R88y2fA3g4irg==", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/pbf": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz", + "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==" + }, + "node_modules/@types/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", + "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "devOptional": true, + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/react-modal": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.3.tgz", + "integrity": "sha512-xXuGavyEGaFQDgBv4UVm8/ZsG+qxeQ7f77yNrW3n+1J6XAstUy5rYHeIHPh1KzsGc6IkCIdu6lQ2xWzu1jBTLg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-slick": { + "version": "0.23.13", + "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.13.tgz", + "integrity": "sha512-bNZfDhe/L8t5OQzIyhrRhBr/61pfBcWaYJoq6UDqFtv5LMwfg4NsVDD2J8N01JqdAdxLjOt66OZEp6PX+dGs/A==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/supercluster": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz", + "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.49.0.tgz", + "integrity": "sha512-JXij0vzIaTtCwu6SxTh8qBc66kmf1xs7pI4UOiMDFVct6q86G0Zs7KRcEoJgY3Cav3x5Tq0MF5jwgpgLqgKG3A==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.49.0", + "@typescript-eslint/type-utils": "8.49.0", + "@typescript-eslint/utils": "8.49.0", + "@typescript-eslint/visitor-keys": "8.49.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.49.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.49.0.tgz", + "integrity": "sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.49.0", + "@typescript-eslint/types": "8.49.0", + "@typescript-eslint/typescript-estree": "8.49.0", + "@typescript-eslint/visitor-keys": "8.49.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 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.49.0.tgz", + "integrity": "sha512-/wJN0/DKkmRUMXjZUXYZpD1NEQzQAAn9QWfGwo+Ai8gnzqH7tvqS7oNVdTjKqOcPyVIdZdyCMoqN66Ia789e7g==", + "dev": true, + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.49.0", + "@typescript-eslint/types": "^8.49.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": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.49.0.tgz", + "integrity": "sha512-npgS3zi+/30KSOkXNs0LQXtsg9ekZ8OISAOLGWA/ZOEn0ZH74Ginfl7foziV8DT+D98WfQ5Kopwqb/PZOaIJGg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.49.0", + "@typescript-eslint/visitor-keys": "8.49.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.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.49.0.tgz", + "integrity": "sha512-8prixNi1/6nawsRYxet4YOhnbW+W9FK/bQPxsGB1D3ZrDzbJ5FXw5XmzxZv82X3B+ZccuSxo/X8q9nQ+mFecWA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.49.0.tgz", + "integrity": "sha512-KTExJfQ+svY8I10P4HdxKzWsvtVnsuCifU5MvXrRwoP2KOlNZ9ADNEWWsQTJgMxLzS5VLQKDjkCT/YzgsnqmZg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.49.0", + "@typescript-eslint/typescript-estree": "8.49.0", + "@typescript-eslint/utils": "8.49.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.49.0.tgz", + "integrity": "sha512-e9k/fneezorUo6WShlQpMxXh8/8wfyc+biu6tnAqA81oWrEic0k21RHzP9uqqpyBBeBKu4T+Bsjy9/b8u7obXQ==", + "dev": true, + "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.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.49.0.tgz", + "integrity": "sha512-jrLdRuAbPfPIdYNppHJ/D0wN+wwNfJ32YTAm10eJVsFmrVpXQnDWBn8niCSMlWjvml8jsce5E/O+86IQtTbJWA==", + "dev": true, + "dependencies": { + "@typescript-eslint/project-service": "8.49.0", + "@typescript-eslint/tsconfig-utils": "8.49.0", + "@typescript-eslint/types": "8.49.0", + "@typescript-eslint/visitor-keys": "8.49.0", + "debug": "^4.3.4", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.49.0.tgz", + "integrity": "sha512-N3W7rJw7Rw+z1tRsHZbK395TWSYvufBXumYtEGzypgMUthlg0/hmCImeA8hgO2d2G4pd7ftpxxul2J8OdtdaFA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.49.0", + "@typescript-eslint/types": "8.49.0", + "@typescript-eslint/typescript-estree": "8.49.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.49.0.tgz", + "integrity": "sha512-LlKaciDe3GmZFphXIc79THF/YYBugZ7FS1pO581E/edlVVNbZKDy93evqmrfQ9/Y4uN0vVhX4iuchq26mK/iiA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.49.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vitalets/google-translate-api": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@vitalets/google-translate-api/-/google-translate-api-9.2.1.tgz", + "integrity": "sha512-zlwQWSjXUZhbZQ6qwtIQ7GdYXFQmJ4wYqzcrYJUxtvzQQwUP+uKUb/SRJaBOQuBntjBjzcdcJoLFrpCKUbIkOg==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "^1.8.2", + "http-errors": "^2.0.0", + "node-fetch": "^2.6.7" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@vitalets/google-translate-api/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@xobotyi/scrollbar-width": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", + "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.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/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-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==", + "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==", + "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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "engines": { + "node": ">=0.10.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, + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "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, + "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, + "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, + "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, + "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, + "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/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "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, + "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==" + }, + "node_modules/autoprefixer": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz", + "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.27", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.27.tgz", + "integrity": "sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "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==", + "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/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytewise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", + "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==", + "dependencies": { + "bytewise-core": "^1.2.2", + "typewise": "^1.0.3" + } + }, + "node_modules/bytewise-core": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", + "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", + "dependencies": { + "typewise-core": "^1.2" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "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==", + "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, + "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, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001791", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001791.tgz", + "integrity": "sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==", + "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==", + "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/chardet": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==" + }, + "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==", + "license": "MIT", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, + "node_modules/cheap-ruler": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cheap-ruler/-/cheap-ruler-4.0.0.tgz", + "integrity": "sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==" + }, + "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/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, + "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==", + "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==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "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==" + }, + "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==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "license": "BSD-2-Clause", + "dependencies": { + "dot-prop": "^6.0.1", + "graceful-fs": "^4.2.6", + "unique-string": "^3.0.0", + "write-file-atomic": "^3.0.3", + "xdg-basedir": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" + } + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/core-js": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "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-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-fetch/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "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" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "license": "MIT", + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "license": "MIT", + "dependencies": { + "hyphenate-style-name": "^1.0.3" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csscolorparser": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz", + "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==" + }, + "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==" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "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, + "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, + "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, + "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/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "engines": { + "node": ">=0.10.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==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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, + "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, + "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==", + "engines": { + "node": ">=0.4.0" + } + }, + "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/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "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/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "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/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/earcut": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", + "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.351", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.351.tgz", + "integrity": "sha512-9D7Iqx8RImSvCnOsj86rCH6eQjZFQoM04Jn6HnZVM0Nu/G58/gmKYQ1d12MZTbjQbQSTGI8nwEy07ErsA2slLA==", + "dev": true, + "license": "ISC" + }, + "node_modules/embla-carousel": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", + "license": "MIT" + }, + "node_modules/embla-carousel-react": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz", + "integrity": "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==", + "license": "MIT", + "dependencies": { + "embla-carousel": "8.6.0", + "embla-carousel-reactive-utils": "8.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/embla-carousel-reactive-utils": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz", + "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==", + "license": "MIT", + "peerDependencies": { + "embla-carousel": "8.6.0" + } + }, + "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 + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-client/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/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==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz", + "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "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==", + "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, + "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==", + "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==", + "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, + "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, + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@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.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "15.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.5.tgz", + "integrity": "sha512-Awm7iUJY8toOR+fU8yTxZnA7/LyOGUGOd6cENCuDfJ3gucHOSmLdOSGJ4u+nlrs8p5qXemua42bZmq+uOzxl6Q==", + "dev": true, + "dependencies": { + "@next/eslint-plugin-next": "15.1.5", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.0.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "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, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "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, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "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/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, + "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, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "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, + "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, + "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, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-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==", + "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 + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-shallow-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", + "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" + }, + "node_modules/fastest-stable-stringify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", + "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==", + "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==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "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, + "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==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "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, + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/formik": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.9.tgz", + "integrity": "sha512-5nI94BMnlFDdQRBY4Sz39WkhxajZJ57Fzs8wVbtsQlm5ScKIR1QLYqv/ultBnobObtlUyxpxoLodpixrsf36Og==", + "funding": [ + { + "type": "individual", + "url": "https://opencollective.com/formik" + } + ], + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.1", + "deepmerge": "^2.1.1", + "hoist-non-react-statics": "^3.3.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "react-fast-compare": "^2.0.1", + "tiny-warning": "^1.0.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/framer-motion": { + "version": "12.38.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz", + "integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.38.0", + "motion-utils": "^12.36.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fs-extra": { + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "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==", + "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, + "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, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/geojson-vt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz", + "integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==" + }, + "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==", + "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-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "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.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gl-matrix": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", + "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==" + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "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, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/goober": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", + "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/grid-index": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz", + "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==" + }, + "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, + "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==", + "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, + "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, + "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==", + "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==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "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/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "license": "BSD-3-Clause" + }, + "node_modules/i18next": { + "version": "25.10.10", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.10.10.tgz", + "integrity": "sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==", + "funding": [ + { + "type": "individual", + "url": "https://www.locize.com/i18next" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + }, + { + "type": "individual", + "url": "https://www.locize.com" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.29.2" + }, + "peerDependencies": { + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz", + "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-fs-backend": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.6.5.tgz", + "integrity": "sha512-+7HBrlaj3UFnNC9HqiXaIlNkwNINYkgQ2PS4h7qW/WGHC9/+OU9Xi0/tdvjjXATw3YCcpmNV7S3zDD9e10pTWg==", + "license": "MIT" + }, + "node_modules/i18next-http-backend": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.6.tgz", + "integrity": "sha512-mBOqy8993jtqAoj6XaI1XeC/8/9v6EPS+681ziegrPvTB0DoaCY7PpTS0SpY56qLMoS4OI1TZEM2Zf59zNh05w==", + "license": "MIT", + "dependencies": { + "cross-fetch": "4.1.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", + "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "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" + } + ] + }, + "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, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, + "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, + "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==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inline-style-prefixer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", + "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", + "license": "MIT", + "dependencies": { + "css-in-js-utils": "^3.1.0" + } + }, + "node_modules/inquirer": { + "version": "8.2.7", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.7.tgz", + "integrity": "sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==", + "dependencies": { + "@inquirer/external-editor": "^1.0.0", + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "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, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "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, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "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, + "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, + "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, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "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, + "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, + "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-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "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, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "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-glob": { + "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" + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-keyword-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-keyword-js/-/is-keyword-js-1.0.3.tgz", + "integrity": "sha512-EW8wNCNvomPa/jsH1g0DmLfPakkRCRTcTML1v1fZMLiVCvQ/1YB+tKsRzShBiWQhqrYCi5a+WsepA4Z8TA9iaA==", + "license": "MIT", + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "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==", + "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, + "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-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "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, + "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, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "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, + "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, + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, + "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, + "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, + "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, + "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 + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "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/jalali-moment": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/jalali-moment/-/jalali-moment-3.3.11.tgz", + "integrity": "sha512-tdSaRs9cjWjOIaWhcsGFZMhZQhfgok5J0TwqFpBIZPudZxxa6yjUPoLCOwuvbAtRpiZn7k/mvazAJh+vEN5suw==", + "dependencies": { + "commander": "^7.0.0", + "inquirer": "^8.0.0", + "moment": "^2.26.0" + }, + "bin": { + "jalalim": "cli.js" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "peer": true + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, + "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==" + }, + "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==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-pretty-compact": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-3.0.0.tgz", + "integrity": "sha512-Rc2suX5meI0S3bfdZuA7JMFBGkJ875ApfVyq2WHELjBiiG22My/l7/8zPpH/CfFVQHuVLd8NLR0nv6vi0BYYKA==" + }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "dependencies": { + "string-convert": "^0.2.0" + } + }, + "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, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "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, + "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/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jszip/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/jszip/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/jszip/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/kdbush": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz", + "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==" + }, + "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==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/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==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lucide-react": { + "version": "0.541.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.541.0.tgz", + "integrity": "sha512-s0Vircsu5WaGv2KoJZ5+SoxiAJ3UXV5KqEM3eIFDHaHkcLIFdIWgXtZ412+Gh02UsdS7Was+jvEpBvPCWQISlg==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "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/mapbox-gl": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.17.0.tgz", + "integrity": "sha512-nCrDKRlr5di6xUksUDslNWwxroJ5yv1hT8pyVFtcpWJOOKsYQxF/wOFTMie8oxMnXeFkrz1Tl1TwA1XN1yX0KA==", + "dependencies": { + "@mapbox/jsonlint-lines-primitives": "^2.0.2", + "@mapbox/mapbox-gl-supported": "^3.0.0", + "@mapbox/point-geometry": "^1.1.0", + "@mapbox/tiny-sdf": "^2.0.6", + "@mapbox/unitbezier": "^0.0.1", + "@mapbox/vector-tile": "^2.0.4", + "@mapbox/whoots-js": "^3.1.0", + "@types/geojson": "^7946.0.16", + "@types/geojson-vt": "^3.2.5", + "@types/mapbox__point-geometry": "^0.1.4", + "@types/pbf": "^3.0.5", + "@types/supercluster": "^7.1.3", + "cheap-ruler": "^4.0.0", + "csscolorparser": "~1.0.3", + "earcut": "^3.0.1", + "geojson-vt": "^4.0.2", + "gl-matrix": "^3.4.4", + "grid-index": "^1.1.0", + "kdbush": "^4.0.2", + "martinez-polygon-clipping": "^0.7.4", + "murmurhash-js": "^1.0.0", + "pbf": "^4.0.1", + "potpack": "^2.0.0", + "quickselect": "^3.0.0", + "supercluster": "^8.0.1", + "tinyqueue": "^3.0.0" + } + }, + "node_modules/martinez-polygon-clipping": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/martinez-polygon-clipping/-/martinez-polygon-clipping-0.7.4.tgz", + "integrity": "sha512-jBEwrKtA0jTagUZj2bnmb4Yg2s4KnJGRePStgI7bAVjtcipKiF39R4LZ2V/UT61jMYWrTcBhPazexeqd6JAVtw==", + "dependencies": { + "robust-predicates": "^2.0.4", + "splaytree": "^0.1.4", + "tinyqueue": "^1.2.0" + } + }, + "node_modules/martinez-polygon-clipping/node_modules/tinyqueue": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-1.2.3.tgz", + "integrity": "sha512-Qz9RgWuO9l8lT+Y9xvbzhPT2efIUIFd69N7eF7tJ9lnQl0iLj1M7peK7IoUGZL9DJHw9XftqLreccfxcQgYLxA==" + }, + "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==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "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==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "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==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/motion-dom": { + "version": "12.38.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz", + "integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.36.0" + } + }, + "node_modules/motion-utils": { + "version": "12.36.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz", + "integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==", + "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==" + }, + "node_modules/murmurhash-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", + "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/nano-css": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", + "integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==", + "license": "Unlicense", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "css-tree": "^1.1.2", + "csstype": "^3.1.2", + "fastest-stable-stringify": "^2.0.2", + "inline-style-prefixer": "^7.0.1", + "rtl-css-js": "^1.16.1", + "stacktrace-js": "^2.0.2", + "stylis": "^4.3.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "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, + "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 + }, + "node_modules/next": { + "version": "15.5.9", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.9.tgz", + "integrity": "sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==", + "dependencies": { + "@next/env": "15.5.9", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.5.7", + "@next/swc-darwin-x64": "15.5.7", + "@next/swc-linux-arm64-gnu": "15.5.7", + "@next/swc-linux-arm64-musl": "15.5.7", + "@next/swc-linux-x64-gnu": "15.5.7", + "@next/swc-linux-x64-musl": "15.5.7", + "@next/swc-win32-arm64-msvc": "15.5.7", + "@next/swc-win32-x64-msvc": "15.5.7", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next-i18next": { + "version": "15.4.3", + "resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-15.4.3.tgz", + "integrity": "sha512-ZRmiz72o1Jvh2ZghCUQX1Ua5F/f2W1/Ila/L1ZeKVuSWiH7J4zfUedfDxNBEhj9lajREC7aoJuPXMFtKi2bdIg==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + }, + { + "type": "individual", + "url": "https://locize.com" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@types/hoist-non-react-statics": "^3.3.6", + "core-js": "^3", + "hoist-non-react-statics": "^3.3.2", + "i18next-fs-backend": "^2.6.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "i18next": ">= 23.7.13", + "next": ">= 12.0.0", + "react": ">= 17.0.2", + "react-i18next": ">= 13.5.0" + } + }, + "node_modules/next-seo": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/next-seo/-/next-seo-6.8.0.tgz", + "integrity": "sha512-zcxaV67PFXCSf8e6SXxbxPaOTgc8St/esxfsYXfQXMM24UESUVSXFm7f2A9HMkAwa0Gqn4s64HxYZAGfdF4Vhg==", + "peerDependencies": { + "next": "^8.1.1-canary.54 || >=9.0.0", + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/next-sitemap": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.2.3.tgz", + "integrity": "sha512-vjdCxeDuWDzldhCnyFCQipw5bfpl4HmZA7uoo3GAaYGjGgfL4Cxb1CiztPuWGmS+auYs7/8OekRS8C2cjdAsjQ==", + "funding": [ + { + "url": "https://github.com/iamvishnusankar/next-sitemap.git" + } + ], + "dependencies": { + "@corex/deepmerge": "^4.0.43", + "@next/env": "^13.4.3", + "fast-glob": "^3.2.12", + "minimist": "^1.2.8" + }, + "bin": { + "next-sitemap": "bin/next-sitemap.mjs", + "next-sitemap-cjs": "bin/next-sitemap.cjs" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "next": "*" + } + }, + "node_modules/next-sitemap/node_modules/@next/env": { + "version": "13.5.11", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.11.tgz", + "integrity": "sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg==" + }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/node-releases": { + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/normalize-wheel": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz", + "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==" + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/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==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/num-or-not": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/num-or-not/-/num-or-not-1.0.1.tgz", + "integrity": "sha512-IMyEpYE7hBjD/fKvZu7/jhy05scXUYy0KXOoKVjoFNU6di56wpGjCok3SoC9k51993v9N7GSLPf+9PuWq220cg==", + "license": "MIT", + "dependencies": { + "trim": "0.0.1" + } + }, + "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==", + "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, + "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, + "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, + "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, + "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, + "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, + "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, + "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/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==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openai": { + "version": "5.23.2", + "resolved": "https://registry.npmjs.org/openai/-/openai-5.23.2.tgz", + "integrity": "sha512-MQBzmTulj+MM5O8SKEk/gL8a7s5mktS9zUtAkU257WjvobGc9nKcBuVwjyEEcb9SI8a8Y2G/mzn3vm9n1Jlleg==", + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "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==", + "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/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, + "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-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/pbf": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz", + "integrity": "sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==", + "dependencies": { + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/potpack": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.1.0.tgz", + "integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", + "license": "MIT" + }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", + "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/quickselect": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==" + }, + "node_modules/radix-ui": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/radix-ui/-/radix-ui-1.4.3.tgz", + "integrity": "sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-accessible-icon": "1.1.7", + "@radix-ui/react-accordion": "1.2.12", + "@radix-ui/react-alert-dialog": "1.1.15", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-aspect-ratio": "1.1.7", + "@radix-ui/react-avatar": "1.1.10", + "@radix-ui/react-checkbox": "1.3.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-context-menu": "2.2.16", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-dropdown-menu": "2.1.16", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-form": "0.1.8", + "@radix-ui/react-hover-card": "1.1.15", + "@radix-ui/react-label": "2.1.7", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-menubar": "1.1.16", + "@radix-ui/react-navigation-menu": "1.2.14", + "@radix-ui/react-one-time-password-field": "0.1.8", + "@radix-ui/react-password-toggle-field": "0.1.3", + "@radix-ui/react-popover": "1.1.15", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-progress": "1.1.7", + "@radix-ui/react-radio-group": "1.3.8", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-scroll-area": "1.2.10", + "@radix-ui/react-select": "2.2.6", + "@radix-ui/react-separator": "1.1.7", + "@radix-ui/react-slider": "1.3.6", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-switch": "1.2.6", + "@radix-ui/react-tabs": "1.1.13", + "@radix-ui/react-toast": "1.2.15", + "@radix-ui/react-toggle": "1.1.10", + "@radix-ui/react-toggle-group": "1.1.11", + "@radix-ui/react-toolbar": "1.1.11", + "@radix-ui/react-tooltip": "1.2.8", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-escape-keydown": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/react-visually-hidden": "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/node_modules/@radix-ui/react-avatar": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "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/node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.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/node_modules/@radix-ui/react-progress": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", + "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.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/node_modules/@radix-ui/react-separator": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.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/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==", + "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/rc-rate": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz", + "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/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==" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-aria": { + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/react-aria/-/react-aria-3.48.0.tgz", + "integrity": "sha512-jQjd4rBEIMqecBaAKYJbVGK6EqIHLa5znVQ7jwFyK5vCyljoj6KhgtiahmcIPsG5vG5vEDLw+ba+bEWn6A2P4w==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.12.1", + "@internationalized/number": "^3.6.6", + "@internationalized/string": "^3.2.8", + "@react-types/shared": "^3.34.0", + "@swc/helpers": "^0.5.0", + "aria-hidden": "^1.2.3", + "clsx": "^2.0.0", + "react-stately": "3.46.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/react-chartjs-2": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz", + "integrity": "sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A==", + "license": "MIT", + "peerDependencies": { + "chart.js": "^4.1.1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-confetti": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.4.0.tgz", + "integrity": "sha512-5MdGUcqxrTU26I2EU7ltkWPwxvucQTuqMm8dUz72z2YMqTD6s9vMcDUysk7n9jnC+lXuCPeJJ7Knf98VEYE9Rg==", + "license": "MIT", + "dependencies": { + "tween-functions": "^1.2.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.1 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-date-object": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/react-date-object/-/react-date-object-2.1.9.tgz", + "integrity": "sha512-BHxD/quWOTo9fLKV/cfL/M31ePoj4a1JaJ/CnOf8Ndg3mrkh4x9wEMMkCfTrzduxDOgU8ZgR8uarhqI5G71sTg==" + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-easy-crop": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/react-easy-crop/-/react-easy-crop-5.5.6.tgz", + "integrity": "sha512-Jw3/ozs8uXj3NpL511Suc4AHY+mLRO23rUgipXvNYKqezcFSYHxe4QXibBymkOoY6oOtLVMPO2HNPRHYvMPyTw==", + "dependencies": { + "normalize-wheel": "^1.0.1", + "tslib": "^2.0.1" + }, + "peerDependencies": { + "react": ">=16.4.0", + "react-dom": ">=16.4.0" + } + }, + "node_modules/react-element-popper": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-element-popper/-/react-element-popper-2.1.7.tgz", + "integrity": "sha512-tuM2OxKlW32h+6uFSK6EENHPeZ2OGgOipHfOAl+VLWEv9/j3QkSGbD+ADX3A9uJlmq24i37n28RjJmAbGTfpEg==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-fast-compare": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", + "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==" + }, + "node_modules/react-hook-form": { + "version": "7.75.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.75.0.tgz", + "integrity": "sha512-Ovv94H+0p3sJ7B9B5QxPuCP1u8V/cHuVGyH55cSwodYDtoJwK+fqk3vjfIgSX59I2U/bU4z0nRJ9HMLpNiWEmw==", + "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-hot-toast": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", + "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-i18next": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.7.4.tgz", + "integrity": "sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.4.0", + "react": ">= 16.8.0", + "typescript": "^5" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "peerDependencies": { + "react": "*" + } + }, + "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==" + }, + "node_modules/react-leaflet": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", + "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==", + "dependencies": { + "@react-leaflet/core": "^2.1.0" + }, + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-map-gl": { + "version": "7.1.9", + "resolved": "https://registry.npmjs.org/react-map-gl/-/react-map-gl-7.1.9.tgz", + "integrity": "sha512-KsCc8Gyn05wVGlHZoopaiiCr0RCAQ6LDISo5sEy1/pV/d7RlozkF946tiX7IgyijJQMRujHol5QdwUPESjh73w==", + "dependencies": { + "@maplibre/maplibre-gl-style-spec": "^19.2.1", + "@types/mapbox-gl": ">=1.0.0" + }, + "peerDependencies": { + "mapbox-gl": ">=1.13.0", + "maplibre-gl": ">=1.13.0 <5.0.0", + "react": ">=16.3.0", + "react-dom": ">=16.3.0" + }, + "peerDependenciesMeta": { + "mapbox-gl": { + "optional": true + }, + "maplibre-gl": { + "optional": true + } + } + }, + "node_modules/react-modal": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.3.tgz", + "integrity": "sha512-yCYRJB5YkeQDQlTt17WGAgFJ7jr2QYcWa1SHqZ3PluDmnKJ/7+tVU+E6uKyZ0nODaeEj+xCpK4LcSnKXLMC0Nw==", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-multi-date-picker": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/react-multi-date-picker/-/react-multi-date-picker-4.5.2.tgz", + "integrity": "sha512-FgWjZB3Z6IA6XpcWiLPk85PwcRUhOiYhKK42o5k672gD/n2I6rzPfQ8bUrldOIiF/Z7FfOCdH7a6FeubzqteLg==", + "dependencies": { + "react-date-object": "^2.1.8", + "react-element-popper": "^2.1.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-otp-input": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-otp-input/-/react-otp-input-3.1.1.tgz", + "integrity": "sha512-bjPavgJ0/Zmf/AYi4onj8FbH93IjeD+e8pWwxIJreDEWsU1ILR5fs8jEJmMGWSBe/yyvPP6X/W6Mk9UkOCkTPw==", + "peerDependencies": { + "react": ">=16.8.6 || ^17.0.0 || ^18.0.0", + "react-dom": ">=16.8.6 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-slick": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.31.0.tgz", + "integrity": "sha512-zo6VLT8wuSBJffg/TFPbzrw2dEnfZ/cUKmYsKByh3AgatRv29m2LoFbq5vRMa3R3A4wp4d8gwbJKO2fWZFaI3g==", + "dependencies": { + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "lodash.debounce": "^4.0.8", + "resize-observer-polyfill": "^1.5.0" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-stately": { + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/react-stately/-/react-stately-3.46.0.tgz", + "integrity": "sha512-OdxhWvHgs2L4OJGIs7hnuTr5WjjMM6enhNEAMRqiekhF8+ITvA2LRwNftOZwcogaoCslGYq5S2VQTQwnm0GbCA==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.12.1", + "@internationalized/number": "^3.6.6", + "@internationalized/string": "^3.2.8", + "@react-types/shared": "^3.34.0", + "@swc/helpers": "^0.5.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "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/react-universal-interface": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", + "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==", + "peerDependencies": { + "react": "*", + "tslib": "*" + } + }, + "node_modules/react-use": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.6.0.tgz", + "integrity": "sha512-OmedEScUMKFfzn1Ir8dBxiLLSOzhKe/dPZwVxcujweSj45aNM7BEGPb9BEVIgVEqEXx6f3/TsXzwIktNgUR02g==", + "license": "Unlicense", + "dependencies": { + "@types/js-cookie": "^2.2.6", + "@xobotyi/scrollbar-width": "^1.9.5", + "copy-to-clipboard": "^3.3.1", + "fast-deep-equal": "^3.1.3", + "fast-shallow-equal": "^1.0.0", + "js-cookie": "^2.2.1", + "nano-css": "^5.6.2", + "react-universal-interface": "^0.6.2", + "resize-observer-polyfill": "^1.5.1", + "screenfull": "^5.1.0", + "set-harmonic-interval": "^1.0.1", + "throttle-debounce": "^3.0.1", + "ts-easing": "^0.2.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/react-use/node_modules/@types/js-cookie": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", + "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==", + "license": "MIT" + }, + "node_modules/react-use/node_modules/js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", + "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==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/recharts": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", + "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.4", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts/node_modules/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==", + "license": "MIT" + }, + "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, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "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/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.16.1", + "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-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/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, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/robust-predicates": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-2.0.4.tgz", + "integrity": "sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==" + }, + "node_modules/rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "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-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" + } + ] + }, + "node_modules/safe-eval": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/safe-eval/-/safe-eval-0.4.1.tgz", + "integrity": "sha512-wmiu4RSYVZ690RP1+cv/LxfPK1dIlEN35aW7iv4SMYdqDrHbkll4+NJcHmKm7PbCuI1df1otOcPwgcc2iFR85g==", + "license": "MIT" + }, + "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, + "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, + "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/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/screenfull": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "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, + "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-harmonic-interval": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", + "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==", + "license": "Unlicense", + "engines": { + "node": ">=6.9" + } + }, + "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, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "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/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "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, + "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, + "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, + "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": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slick-carousel": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/slick-carousel/-/slick-carousel-1.8.1.tgz", + "integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==", + "peerDependencies": { + "jquery": ">=1.8.0" + } + }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/sonner": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", + "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", + "license": "MIT", + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/sort-asc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", + "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-desc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz", + "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-object": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz", + "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==", + "dependencies": { + "bytewise": "^1.1.0", + "get-value": "^2.0.2", + "is-extendable": "^0.1.1", + "sort-asc": "^0.2.0", + "sort-desc": "^0.2.0", + "union-value": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/splaytree": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/splaytree/-/splaytree-0.1.4.tgz", + "integrity": "sha512-D50hKrjZgBzqD3FT2Ek53f2dcDLAQT8SSGrzj3vidNH5ISRgceeGVJ2dQIthKOuayqFXfFjXheHNo4bbt9LhRQ==" + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "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 + }, + "node_modules/stack-generator": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", + "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-gps": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz", + "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==", + "license": "MIT", + "dependencies": { + "source-map": "0.5.6", + "stackframe": "^1.3.4" + } + }, + "node_modules/stacktrace-gps/node_modules/source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stacktrace-js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", + "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", + "license": "MIT", + "dependencies": { + "error-stack-parser": "^2.0.6", + "stack-generator": "^2.0.5", + "stacktrace-gps": "^3.0.4" + } + }, + "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/stdin-discarder": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz", + "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==", + "license": "MIT", + "dependencies": { + "bl": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stdin-discarder/node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/stdin-discarder/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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.2.1" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" + }, + "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==", + "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/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==" + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "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, + "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, + "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, + "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, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, + "node_modules/supercluster": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz", + "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==", + "dependencies": { + "kdbush": "^4.0.2" + } + }, + "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==", + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swiper": { + "version": "11.2.10", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-11.2.10.tgz", + "integrity": "sha512-RMeVUUjTQH+6N3ckimK93oxz6Sn5la4aDlgPzB+rBrG/smPdCTicXyhxa+woIpopz+jewEloiEE3lKo1h9w2YQ==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "engines": { + "node": ">= 4.7.0" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, + "node_modules/tailwind-merge": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz", + "integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/tailwindcss/-/tailwindcss-4.2.4.tgz", + "integrity": "sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tailwindcss-rtl": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/tailwindcss-rtl/-/tailwindcss-rtl-0.9.0.tgz", + "integrity": "sha512-y7yC8QXjluDBEFMSX33tV6xMYrf0B3sa+tOB5JSQb6/G6laBU313a+Z+qxu55M1Qyn8tDMttjomsA8IsJD+k+w==", + "license": "MIT" + }, + "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/three": { + "version": "0.180.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.180.0.tgz", + "integrity": "sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w==", + "license": "MIT" + }, + "node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", + "license": "MIT" + }, + "node_modules/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==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinyqueue": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==" + }, + "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==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, + "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/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/translate-google": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/translate-google/-/translate-google-1.5.0.tgz", + "integrity": "sha512-wI/oX3U3t78PthVkvO7BdvKRcjb03JaUs53oAhs0NVmzFJUEm5ROiYWH7gomRHFZ5bL7LKxrFRx8Qy/l1eB46g==", + "license": "MIT", + "dependencies": { + "configstore": "^6.0.0", + "got": "^11.8.2", + "is-keyword-js": "^1.0.3", + "is-url": "^1.2.4", + "lodash": "^4.17.21", + "num-or-not": "^1.0.1", + "safe-eval": "^0.4.1", + "user-agents": "^1.0.779" + } + }, + "node_modules/trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", + "deprecated": "Use String.prototype.trim() instead" + }, + "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, + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-easing": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz", + "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==", + "license": "Unlicense" + }, + "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/ts-node/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/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, + "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==" + }, + "node_modules/tw-animate-css": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/tw-animate-css/-/tw-animate-css-1.3.8.tgz", + "integrity": "sha512-Qrk3PZ7l7wUcGYhwZloqfkWCmaXZAoqjkdbIDvzfGshwGtexa/DAs9koXxIkrpEasyevandomzCBAV1Yyop5rw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Wombosvideo" + } + }, + "node_modules/tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", + "license": "BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "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, + "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, + "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, + "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/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typewise": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", + "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==", + "dependencies": { + "typewise-core": "^1.2.0" + } + }, + "node_modules/typewise-core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", + "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==" + }, + "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, + "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==" + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.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, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/user-agents": { + "version": "1.1.675", + "resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.1.675.tgz", + "integrity": "sha512-ZQnegGfKf083joYjEZuLgjJtpDHW5IhOXWCw/25yx82ZvctDcYp/PQsWNShH4Dq00SuDYaPm0qndVBn6axBpvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=18" + } + }, + "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==" + }, + "node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "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/vaul": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz", + "integrity": "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-dialog": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/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, + "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, + "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, + "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, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "license": "MIT", + "optional": true, + "peer": true, + "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/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/yet-another-react-lightbox": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yet-another-react-lightbox/-/yet-another-react-lightbox-3.32.0.tgz", + "integrity": "sha512-FWODOMrE07i3O5MeWRcYlcnAUk518zkUYKAe307pVW5pkey3hKMcAIWn8yMIURzGvbd3m9eghWO9CocEZmQPIg==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/igordanchenko" + }, + "peerDependencies": { + "@types/react": "^16 || ^17 || ^18 || ^19", + "@types/react-dom": "^16 || ^17 || ^18 || ^19", + "react": "^16.8.0 || ^17 || ^18 || ^19", + "react-dom": "^16.8.0 || ^17 || ^18 || ^19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yup": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", + "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==", + "license": "MIT", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3b9165f --- /dev/null +++ b/package.json @@ -0,0 +1,127 @@ +{ + "name": "modstagram-next", + "version": "0.1.0", + "private": true, + "scripts": { + "start": "next start -p 3000 -H 0.0.0.0", + "dev": "next dev -p 3000 -H 0.0.0.0", + "build": "next build", + "lint": "next lint", + "postbuild": "next-sitemap" + }, + "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", + "@headlessui/react": "^2.2.8", + "@hookform/resolvers": "^5.2.2", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-navigation-menu": "^1.2.14", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "^1.3.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.6", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.2.6", + "@radix-ui/react-tabs": "^1.1.13", + "@radix-ui/react-toast": "^1.2.15", + "@radix-ui/react-toggle": "^1.1.10", + "@radix-ui/react-toggle-group": "^1.1.11", + "@radix-ui/react-tooltip": "^1.2.8", + "@radix-ui/themes": "^3.2.1", + "@shadcn/ui": "^0.0.4", + "@tabler/icons-react": "^3.34.1", + "@tanstack/react-query": "^5.87.1", + "@tanstack/react-table": "^8.21.3", + "@vitalets/google-translate-api": "^9.2.1", + "axios": "^1.7.9", + "chart.js": "^4.5.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "embla-carousel-react": "^8.6.0", + "formik": "^2.4.6", + "framer-motion": "^12.23.12", + "i18next": "^25.3.6", + "i18next-browser-languagedetector": "^8.2.0", + "i18next-http-backend": "^3.0.2", + "jalali-moment": "^3.3.11", + "js-cookie": "^3.0.5", + "jszip": "^3.10.1", + "leaflet": "^1.9.4", + "lodash": "^4.17.21", + "lucide-react": "^0.541.0", + "mapbox-gl": "^3.9.3", + "next": "^15.5.2", + "next-i18next": "^15.4.2", + "next-seo": "^6.8.0", + "next-sitemap": "^4.2.3", + "next-themes": "^0.4.6", + "node-fetch": "^3.3.2", + "openai": "^5.21.0", + "radix-ui": "^1.4.3", + "rc-rate": "^2.13.0", + "react": "^18.3.1", + "react-chartjs-2": "^5.3.0", + "react-confetti": "^6.4.0", + "react-dom": "^18.3.1", + "react-easy-crop": "^5.5.0", + "react-hook-form": "^7.65.0", + "react-hot-toast": "^2.5.1", + "react-i18next": "^15.6.1", + "react-icons": "^5.5.0", + "react-leaflet": "^4.2.1", + "react-map-gl": "^7.1.8", + "react-modal": "^3.16.3", + "react-multi-date-picker": "^4.5.2", + "react-otp-input": "^3.1.1", + "react-slick": "^0.31.0", + "react-use": "^17.6.0", + "recharts": "^2.15.4", + "sharp": "^0.34.5", + "slick-carousel": "^1.8.1", + "socket.io-client": "^4.8.1", + "sonner": "^2.0.7", + "swiper": "^11.2.2", + "tailwind-merge": "^3.3.1", + "tailwindcss-rtl": "^0.9.0", + "three": "^0.180.0", + "translate-google": "^1.5.0", + "uuid": "^11.1.0", + "vaul": "^1.1.2", + "yet-another-react-lightbox": "^3.25.0", + "yup": "^1.7.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@ffmpeg/ffmpeg": "^0.12.10", + "@ffmpeg/util": "^0.12.1", + "@tailwindcss/postcss": "^4.2.4", + "@types/js-cookie": "^3.0.6", + "@types/leaflet": "^1.9.20", + "@types/lodash": "^4.17.20", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "@types/react-modal": "^3.16.3", + "@types/react-slick": "^0.23.13", + "autoprefixer": "^10.4.21", + "eslint": "^9", + "eslint-config-next": "15.1.5", + "postcss": "^8.5.14", + "tailwindcss": "^4.2.4", + "ts-node": "^10.9.2", + "tw-animate-css": "^1.3.8", + "typescript": "^5" + } +} diff --git a/package.jsonغ b/package.jsonغ new file mode 100644 index 0000000..e3b2d50 --- /dev/null +++ b/package.jsonغ @@ -0,0 +1,127 @@ +{ + "name": "modstagram-next", + "version": "0.1.0", + "private": true, + "scripts": { + "start": "next start -p 3000 -H 0.0.0.0", + "dev": "next dev -p 3000 -H 0.0.0.0", + "build": "next build" + "lint": "next lint", + "postbuild": "next-sitemap" + }, + "dependencies": { + "@dnd-kit/core": "^6.3.1", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", + "@dnd-kit/utilities": "^3.2.2", + "@headlessui/react": "^2.2.8", + "@hookform/resolvers": "^5.2.2", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-label": "^2.1.7", + "@radix-ui/react-navigation-menu": "^1.2.14", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "^1.3.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.7", + "@radix-ui/react-slider": "^1.3.6", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.2.6", + "@radix-ui/react-tabs": "^1.1.13", + "@radix-ui/react-toast": "^1.2.15", + "@radix-ui/react-toggle": "^1.1.10", + "@radix-ui/react-toggle-group": "^1.1.11", + "@radix-ui/react-tooltip": "^1.2.8", + "@radix-ui/themes": "^3.2.1", + "@shadcn/ui": "^0.0.4", + "@tabler/icons-react": "^3.34.1", + "@tanstack/react-query": "^5.87.1", + "@tanstack/react-table": "^8.21.3", + "@vitalets/google-translate-api": "^9.2.1", + "axios": "^1.7.9", + "chart.js": "^4.5.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "embla-carousel-react": "^8.6.0", + "formik": "^2.4.6", + "framer-motion": "^12.23.12", + "i18next": "^25.3.6", + "i18next-browser-languagedetector": "^8.2.0", + "i18next-http-backend": "^3.0.2", + "jalali-moment": "^3.3.11", + "js-cookie": "^3.0.5", + "jszip": "^3.10.1", + "leaflet": "^1.9.4", + "lodash": "^4.17.21", + "lucide-react": "^0.541.0", + "mapbox-gl": "^3.9.3", + "next": "^15.5.2", + "next-i18next": "^15.4.2", + "next-seo": "^6.8.0", + "next-sitemap": "^4.2.3", + "next-themes": "^0.4.6", + "node-fetch": "^3.3.2", + "openai": "^5.21.0", + "radix-ui": "^1.4.3", + "rc-rate": "^2.13.0", + "react": "^18.3.1", + "react-chartjs-2": "^5.3.0", + "react-confetti": "^6.4.0", + "react-dom": "^18.3.1", + "react-easy-crop": "^5.5.0", + "react-hook-form": "^7.65.0", + "react-hot-toast": "^2.5.1", + "react-i18next": "^15.6.1", + "react-icons": "^5.5.0", + "react-leaflet": "^4.2.1", + "react-map-gl": "^7.1.8", + "react-modal": "^3.16.3", + "react-multi-date-picker": "^4.5.2", + "react-otp-input": "^3.1.1", + "react-slick": "^0.31.0", + "react-use": "^17.6.0", + "recharts": "^2.15.4", + "sharp": "^0.34.5", + "slick-carousel": "^1.8.1", + "socket.io-client": "^4.8.1", + "sonner": "^2.0.7", + "swiper": "^11.2.2", + "tailwind-merge": "^3.3.1", + "tailwindcss-rtl": "^0.9.0", + "three": "^0.180.0", + "translate-google": "^1.5.0", + "uuid": "^11.1.0", + "vaul": "^1.1.2", + "yet-another-react-lightbox": "^3.25.0", + "yup": "^1.7.1", + "zod": "^3.25.76" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@ffmpeg/ffmpeg": "^0.12.10", + "@ffmpeg/util": "^0.12.1", + "@tailwindcss/postcss": "^4.2.4", + "@types/js-cookie": "^3.0.6", + "@types/leaflet": "^1.9.20", + "@types/lodash": "^4.17.20", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "@types/react-modal": "^3.16.3", + "@types/react-slick": "^0.23.13", + "autoprefixer": "^10.4.21", + "eslint": "^9", + "eslint-config-next": "15.1.5", + "postcss": "^8.5.14", + "tailwindcss": "^4.2.4", + "ts-node": "^10.9.2", + "tw-animate-css": "^1.3.8", + "typescript": "^5" + } +} diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..5ba0f7a --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,5 @@ +export default { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; \ No newline at end of file diff --git a/public/fonts/IRANSansX-Black.woff b/public/fonts/IRANSansX-Black.woff new file mode 100644 index 0000000..2849a98 Binary files /dev/null and b/public/fonts/IRANSansX-Black.woff differ diff --git a/public/fonts/IRANSansX-Bold.woff b/public/fonts/IRANSansX-Bold.woff new file mode 100644 index 0000000..1109807 Binary files /dev/null and b/public/fonts/IRANSansX-Bold.woff differ diff --git a/public/fonts/IRANSansX-DemiBold.woff b/public/fonts/IRANSansX-DemiBold.woff new file mode 100644 index 0000000..5576265 Binary files /dev/null and b/public/fonts/IRANSansX-DemiBold.woff differ diff --git a/public/fonts/IRANSansX-ExtraBold.woff b/public/fonts/IRANSansX-ExtraBold.woff new file mode 100644 index 0000000..900ba63 Binary files /dev/null and b/public/fonts/IRANSansX-ExtraBold.woff differ diff --git a/public/fonts/IRANSansX-Light.woff b/public/fonts/IRANSansX-Light.woff new file mode 100644 index 0000000..34adea8 Binary files /dev/null and b/public/fonts/IRANSansX-Light.woff differ diff --git a/public/fonts/IRANSansX-Medium.woff b/public/fonts/IRANSansX-Medium.woff new file mode 100644 index 0000000..eea2a64 Binary files /dev/null and b/public/fonts/IRANSansX-Medium.woff differ diff --git a/public/fonts/IRANSansX-Regular.woff b/public/fonts/IRANSansX-Regular.woff new file mode 100644 index 0000000..5cf63c1 Binary files /dev/null and b/public/fonts/IRANSansX-Regular.woff differ diff --git a/public/fonts/IRANSansX-Thin.woff b/public/fonts/IRANSansX-Thin.woff new file mode 100644 index 0000000..14dafdf Binary files /dev/null and b/public/fonts/IRANSansX-Thin.woff differ diff --git a/public/fonts/IRANSansX-UltraLight.woff b/public/fonts/IRANSansX-UltraLight.woff new file mode 100644 index 0000000..cdb8537 Binary files /dev/null and b/public/fonts/IRANSansX-UltraLight.woff differ diff --git a/public/images/eyes/01.png b/public/images/eyes/01.png new file mode 100644 index 0000000..45b73eb Binary files /dev/null and b/public/images/eyes/01.png differ diff --git a/public/images/eyes/02.png b/public/images/eyes/02.png new file mode 100644 index 0000000..6195520 Binary files /dev/null and b/public/images/eyes/02.png differ diff --git a/public/images/eyes/03.png b/public/images/eyes/03.png new file mode 100644 index 0000000..9c75f5e Binary files /dev/null and b/public/images/eyes/03.png differ diff --git a/public/images/eyes/04.png b/public/images/eyes/04.png new file mode 100644 index 0000000..4fce668 Binary files /dev/null and b/public/images/eyes/04.png differ diff --git a/public/images/eyes/05.png b/public/images/eyes/05.png new file mode 100644 index 0000000..c2c4fc3 Binary files /dev/null and b/public/images/eyes/05.png differ diff --git a/public/images/eyes/06.png b/public/images/eyes/06.png new file mode 100644 index 0000000..9953439 Binary files /dev/null and b/public/images/eyes/06.png differ diff --git a/public/images/eyes/07.png b/public/images/eyes/07.png new file mode 100644 index 0000000..01d3178 Binary files /dev/null and b/public/images/eyes/07.png differ diff --git a/public/images/eyes/08.png b/public/images/eyes/08.png new file mode 100644 index 0000000..5bc1624 Binary files /dev/null and b/public/images/eyes/08.png differ diff --git a/public/images/eyes/09.png b/public/images/eyes/09.png new file mode 100644 index 0000000..a081d7a Binary files /dev/null and b/public/images/eyes/09.png differ diff --git a/public/images/eyes/10.png b/public/images/eyes/10.png new file mode 100644 index 0000000..97f6a52 Binary files /dev/null and b/public/images/eyes/10.png differ diff --git a/public/images/eyes/11.png b/public/images/eyes/11.png new file mode 100644 index 0000000..d4bd5a4 Binary files /dev/null and b/public/images/eyes/11.png differ diff --git a/public/images/eyes/12.png b/public/images/eyes/12.png new file mode 100644 index 0000000..54a0e6d Binary files /dev/null and b/public/images/eyes/12.png differ diff --git a/public/images/eyes/13.png b/public/images/eyes/13.png new file mode 100644 index 0000000..59572da Binary files /dev/null and b/public/images/eyes/13.png differ diff --git a/public/images/eyes/14.png b/public/images/eyes/14.png new file mode 100644 index 0000000..1783b46 Binary files /dev/null and b/public/images/eyes/14.png differ diff --git a/public/images/eyes/15.png b/public/images/eyes/15.png new file mode 100644 index 0000000..d2663c7 Binary files /dev/null and b/public/images/eyes/15.png differ diff --git a/public/images/eyes/16.png b/public/images/eyes/16.png new file mode 100644 index 0000000..27438a6 Binary files /dev/null and b/public/images/eyes/16.png differ diff --git a/public/images/eyes/17.png b/public/images/eyes/17.png new file mode 100644 index 0000000..a035fbf Binary files /dev/null and b/public/images/eyes/17.png differ diff --git a/public/images/eyes/18.png b/public/images/eyes/18.png new file mode 100644 index 0000000..c5271c7 Binary files /dev/null and b/public/images/eyes/18.png differ diff --git a/public/images/eyes/19.png b/public/images/eyes/19.png new file mode 100644 index 0000000..9404b0c Binary files /dev/null and b/public/images/eyes/19.png differ diff --git a/public/images/eyes/20.png b/public/images/eyes/20.png new file mode 100644 index 0000000..8587ebc Binary files /dev/null and b/public/images/eyes/20.png differ diff --git a/public/images/eyes/21.png b/public/images/eyes/21.png new file mode 100644 index 0000000..8a4eb5e Binary files /dev/null and b/public/images/eyes/21.png differ diff --git a/public/images/eyes/22.png b/public/images/eyes/22.png new file mode 100644 index 0000000..8127ae9 Binary files /dev/null and b/public/images/eyes/22.png differ diff --git a/public/images/eyes/23.png b/public/images/eyes/23.png new file mode 100644 index 0000000..b0b3bfd Binary files /dev/null and b/public/images/eyes/23.png differ diff --git a/public/images/eyes/24.png b/public/images/eyes/24.png new file mode 100644 index 0000000..cf299a2 Binary files /dev/null and b/public/images/eyes/24.png differ diff --git a/public/images/eyes/25.png b/public/images/eyes/25.png new file mode 100644 index 0000000..f9136db Binary files /dev/null and b/public/images/eyes/25.png differ diff --git a/public/images/eyes/26.png b/public/images/eyes/26.png new file mode 100644 index 0000000..14760e3 Binary files /dev/null and b/public/images/eyes/26.png differ diff --git a/public/images/fake-avatar.png b/public/images/fake-avatar.png new file mode 100644 index 0000000..648996e Binary files /dev/null and b/public/images/fake-avatar.png differ diff --git a/public/images/hairs/01.png b/public/images/hairs/01.png new file mode 100644 index 0000000..0a9e530 Binary files /dev/null and b/public/images/hairs/01.png differ diff --git a/public/images/hairs/02.png b/public/images/hairs/02.png new file mode 100644 index 0000000..2819b7a Binary files /dev/null and b/public/images/hairs/02.png differ diff --git a/public/images/hairs/03.png b/public/images/hairs/03.png new file mode 100644 index 0000000..699e16a Binary files /dev/null and b/public/images/hairs/03.png differ diff --git a/public/images/hairs/04.png b/public/images/hairs/04.png new file mode 100644 index 0000000..f723eba Binary files /dev/null and b/public/images/hairs/04.png differ diff --git a/public/images/hairs/05.png b/public/images/hairs/05.png new file mode 100644 index 0000000..5c0bb48 Binary files /dev/null and b/public/images/hairs/05.png differ diff --git a/public/images/hairs/06.png b/public/images/hairs/06.png new file mode 100644 index 0000000..dee135f Binary files /dev/null and b/public/images/hairs/06.png differ diff --git a/public/images/hairs/07.png b/public/images/hairs/07.png new file mode 100644 index 0000000..a21522c Binary files /dev/null and b/public/images/hairs/07.png differ diff --git a/public/images/hairs/08.png b/public/images/hairs/08.png new file mode 100644 index 0000000..204ce73 Binary files /dev/null and b/public/images/hairs/08.png differ diff --git a/public/images/hairs/09.png b/public/images/hairs/09.png new file mode 100644 index 0000000..052debf Binary files /dev/null and b/public/images/hairs/09.png differ diff --git a/public/images/hairs/10.png b/public/images/hairs/10.png new file mode 100644 index 0000000..3b2428f Binary files /dev/null and b/public/images/hairs/10.png differ diff --git a/public/images/hairs/11.png b/public/images/hairs/11.png new file mode 100644 index 0000000..06453a4 Binary files /dev/null and b/public/images/hairs/11.png differ diff --git a/public/images/hairs/12.png b/public/images/hairs/12.png new file mode 100644 index 0000000..8d65f7a Binary files /dev/null and b/public/images/hairs/12.png differ diff --git a/public/images/hairs/13.png b/public/images/hairs/13.png new file mode 100644 index 0000000..c3798c2 Binary files /dev/null and b/public/images/hairs/13.png differ diff --git a/public/images/hairs/14.png b/public/images/hairs/14.png new file mode 100644 index 0000000..edeab60 Binary files /dev/null and b/public/images/hairs/14.png differ diff --git a/public/images/hairs/15.png b/public/images/hairs/15.png new file mode 100644 index 0000000..f448cc0 Binary files /dev/null and b/public/images/hairs/15.png differ diff --git a/public/images/hairs/16.png b/public/images/hairs/16.png new file mode 100644 index 0000000..47c1e24 Binary files /dev/null and b/public/images/hairs/16.png differ diff --git a/public/images/hairs/17.png b/public/images/hairs/17.png new file mode 100644 index 0000000..e87eee9 Binary files /dev/null and b/public/images/hairs/17.png differ diff --git a/public/images/hairs/18.png b/public/images/hairs/18.png new file mode 100644 index 0000000..4608b00 Binary files /dev/null and b/public/images/hairs/18.png differ diff --git a/public/images/hairs/19.png b/public/images/hairs/19.png new file mode 100644 index 0000000..8f583de Binary files /dev/null and b/public/images/hairs/19.png differ diff --git a/public/images/hairs/20.png b/public/images/hairs/20.png new file mode 100644 index 0000000..08f37e5 Binary files /dev/null and b/public/images/hairs/20.png differ diff --git a/public/images/hairs/21.png b/public/images/hairs/21.png new file mode 100644 index 0000000..d39ef87 Binary files /dev/null and b/public/images/hairs/21.png differ diff --git a/public/images/hairs/22.png b/public/images/hairs/22.png new file mode 100644 index 0000000..26dca44 Binary files /dev/null and b/public/images/hairs/22.png differ diff --git a/public/images/hairs/23.png b/public/images/hairs/23.png new file mode 100644 index 0000000..9d03f25 Binary files /dev/null and b/public/images/hairs/23.png differ diff --git a/public/images/hairs/24.png b/public/images/hairs/24.png new file mode 100644 index 0000000..3ef2698 Binary files /dev/null and b/public/images/hairs/24.png differ diff --git a/public/images/hairs/25.png b/public/images/hairs/25.png new file mode 100644 index 0000000..8240bdb Binary files /dev/null and b/public/images/hairs/25.png differ diff --git a/public/images/hairs/26.png b/public/images/hairs/26.png new file mode 100644 index 0000000..b663463 Binary files /dev/null and b/public/images/hairs/26.png differ diff --git a/public/images/hairs/27.png b/public/images/hairs/27.png new file mode 100644 index 0000000..6b861fb Binary files /dev/null and b/public/images/hairs/27.png differ diff --git a/public/images/hairs/28.png b/public/images/hairs/28.png new file mode 100644 index 0000000..ec3cbc0 Binary files /dev/null and b/public/images/hairs/28.png differ diff --git a/public/images/hairs/29.png b/public/images/hairs/29.png new file mode 100644 index 0000000..26c2604 Binary files /dev/null and b/public/images/hairs/29.png differ diff --git a/public/images/hairs/30.png b/public/images/hairs/30.png new file mode 100644 index 0000000..dedc937 Binary files /dev/null and b/public/images/hairs/30.png differ diff --git a/public/images/hairs/31.png b/public/images/hairs/31.png new file mode 100644 index 0000000..a8a4a23 Binary files /dev/null and b/public/images/hairs/31.png differ diff --git a/public/images/hairs/32.png b/public/images/hairs/32.png new file mode 100644 index 0000000..f236624 Binary files /dev/null and b/public/images/hairs/32.png differ diff --git a/public/images/hairs/33.png b/public/images/hairs/33.png new file mode 100644 index 0000000..03a6dbc Binary files /dev/null and b/public/images/hairs/33.png differ diff --git a/public/images/hairs/34.png b/public/images/hairs/34.png new file mode 100644 index 0000000..1bd627d Binary files /dev/null and b/public/images/hairs/34.png differ diff --git a/public/images/hairs/35.png b/public/images/hairs/35.png new file mode 100644 index 0000000..d5baf8b Binary files /dev/null and b/public/images/hairs/35.png differ diff --git a/public/images/hairs/36.png b/public/images/hairs/36.png new file mode 100644 index 0000000..06d7b70 Binary files /dev/null and b/public/images/hairs/36.png differ diff --git a/public/images/hairs/37.png b/public/images/hairs/37.png new file mode 100644 index 0000000..c85c62e Binary files /dev/null and b/public/images/hairs/37.png differ diff --git a/public/images/hairs/38.png b/public/images/hairs/38.png new file mode 100644 index 0000000..073f2cb Binary files /dev/null and b/public/images/hairs/38.png differ diff --git a/public/images/hairs/39.png b/public/images/hairs/39.png new file mode 100644 index 0000000..247d078 Binary files /dev/null and b/public/images/hairs/39.png differ diff --git a/public/images/hairs/40.png b/public/images/hairs/40.png new file mode 100644 index 0000000..88727ee Binary files /dev/null and b/public/images/hairs/40.png differ diff --git a/public/images/hairs/41.png b/public/images/hairs/41.png new file mode 100644 index 0000000..08d9479 Binary files /dev/null and b/public/images/hairs/41.png differ diff --git a/public/images/hairs/42.png b/public/images/hairs/42.png new file mode 100644 index 0000000..16ddc45 Binary files /dev/null and b/public/images/hairs/42.png differ diff --git a/public/images/hairs/43.png b/public/images/hairs/43.png new file mode 100644 index 0000000..cd131cd Binary files /dev/null and b/public/images/hairs/43.png differ diff --git a/public/images/hairs/44.png b/public/images/hairs/44.png new file mode 100644 index 0000000..5192f8b Binary files /dev/null and b/public/images/hairs/44.png differ diff --git a/public/images/hairs/45.png b/public/images/hairs/45.png new file mode 100644 index 0000000..a06497a Binary files /dev/null and b/public/images/hairs/45.png differ diff --git a/public/images/hairs/46.png b/public/images/hairs/46.png new file mode 100644 index 0000000..bc02470 Binary files /dev/null and b/public/images/hairs/46.png differ diff --git a/public/images/hairs/47.png b/public/images/hairs/47.png new file mode 100644 index 0000000..83af560 Binary files /dev/null and b/public/images/hairs/47.png differ diff --git a/public/images/hairs/48.png b/public/images/hairs/48.png new file mode 100644 index 0000000..46bb33a Binary files /dev/null and b/public/images/hairs/48.png differ diff --git a/public/images/hairs/49.png b/public/images/hairs/49.png new file mode 100644 index 0000000..dee8289 Binary files /dev/null and b/public/images/hairs/49.png differ diff --git a/public/images/hairs/50.png b/public/images/hairs/50.png new file mode 100644 index 0000000..1636809 Binary files /dev/null and b/public/images/hairs/50.png differ diff --git a/public/images/hairs/51.png b/public/images/hairs/51.png new file mode 100644 index 0000000..d9a5a46 Binary files /dev/null and b/public/images/hairs/51.png differ diff --git a/public/images/hairs/52.png b/public/images/hairs/52.png new file mode 100644 index 0000000..25161f9 Binary files /dev/null and b/public/images/hairs/52.png differ diff --git a/public/images/hairs/53.png b/public/images/hairs/53.png new file mode 100644 index 0000000..9f51695 Binary files /dev/null and b/public/images/hairs/53.png differ diff --git a/public/images/hairs/54.png b/public/images/hairs/54.png new file mode 100644 index 0000000..4d58d4c Binary files /dev/null and b/public/images/hairs/54.png differ diff --git a/public/images/hairs/55.png b/public/images/hairs/55.png new file mode 100644 index 0000000..87ba426 Binary files /dev/null and b/public/images/hairs/55.png differ diff --git a/public/images/hairs/56.png b/public/images/hairs/56.png new file mode 100644 index 0000000..07c7fe1 Binary files /dev/null and b/public/images/hairs/56.png differ diff --git a/public/images/hairs/57.png b/public/images/hairs/57.png new file mode 100644 index 0000000..0b8045e Binary files /dev/null and b/public/images/hairs/57.png differ diff --git a/public/images/hairs/58.png b/public/images/hairs/58.png new file mode 100644 index 0000000..0098174 Binary files /dev/null and b/public/images/hairs/58.png differ diff --git a/public/images/hairs/59.png b/public/images/hairs/59.png new file mode 100644 index 0000000..17db756 Binary files /dev/null and b/public/images/hairs/59.png differ diff --git a/public/images/hairs/60.png b/public/images/hairs/60.png new file mode 100644 index 0000000..abd0b9e Binary files /dev/null and b/public/images/hairs/60.png differ diff --git a/public/images/hairs/61.png b/public/images/hairs/61.png new file mode 100644 index 0000000..faef96c Binary files /dev/null and b/public/images/hairs/61.png differ diff --git a/public/images/hairs/62.png b/public/images/hairs/62.png new file mode 100644 index 0000000..d035bdd Binary files /dev/null and b/public/images/hairs/62.png differ diff --git a/public/images/hairs/63.png b/public/images/hairs/63.png new file mode 100644 index 0000000..ec43760 Binary files /dev/null and b/public/images/hairs/63.png differ diff --git a/public/images/hairs/64.png b/public/images/hairs/64.png new file mode 100644 index 0000000..555a738 Binary files /dev/null and b/public/images/hairs/64.png differ diff --git a/public/images/hairs/65.png b/public/images/hairs/65.png new file mode 100644 index 0000000..cbcf9b4 Binary files /dev/null and b/public/images/hairs/65.png differ diff --git a/public/images/hairs/66.png b/public/images/hairs/66.png new file mode 100644 index 0000000..d2754a4 Binary files /dev/null and b/public/images/hairs/66.png differ diff --git a/public/images/hairs/67.png b/public/images/hairs/67.png new file mode 100644 index 0000000..72d8f97 Binary files /dev/null and b/public/images/hairs/67.png differ diff --git a/public/images/hairs/68.png b/public/images/hairs/68.png new file mode 100644 index 0000000..f901a49 Binary files /dev/null and b/public/images/hairs/68.png differ diff --git a/public/images/hairs/69.png b/public/images/hairs/69.png new file mode 100644 index 0000000..bd53358 Binary files /dev/null and b/public/images/hairs/69.png differ diff --git a/public/images/hairs/70.png b/public/images/hairs/70.png new file mode 100644 index 0000000..056f8ee Binary files /dev/null and b/public/images/hairs/70.png differ diff --git a/public/images/hairs/71.png b/public/images/hairs/71.png new file mode 100644 index 0000000..b8ab412 Binary files /dev/null and b/public/images/hairs/71.png differ diff --git a/public/images/hairs/72.png b/public/images/hairs/72.png new file mode 100644 index 0000000..e87aaee Binary files /dev/null and b/public/images/hairs/72.png differ diff --git a/public/images/hairs/73.png b/public/images/hairs/73.png new file mode 100644 index 0000000..ada7d27 Binary files /dev/null and b/public/images/hairs/73.png differ diff --git a/public/images/hairs/74.png b/public/images/hairs/74.png new file mode 100644 index 0000000..398fb42 Binary files /dev/null and b/public/images/hairs/74.png differ diff --git a/public/images/hairs/75.png b/public/images/hairs/75.png new file mode 100644 index 0000000..f4b79b6 Binary files /dev/null and b/public/images/hairs/75.png differ diff --git a/public/images/hairs/76.png b/public/images/hairs/76.png new file mode 100644 index 0000000..0306575 Binary files /dev/null and b/public/images/hairs/76.png differ diff --git a/public/images/hairs/77.png b/public/images/hairs/77.png new file mode 100644 index 0000000..4912c90 Binary files /dev/null and b/public/images/hairs/77.png differ diff --git a/public/images/hairs/78.png b/public/images/hairs/78.png new file mode 100644 index 0000000..a0d2a5c Binary files /dev/null and b/public/images/hairs/78.png differ diff --git a/public/images/hairs/79.png b/public/images/hairs/79.png new file mode 100644 index 0000000..1938125 Binary files /dev/null and b/public/images/hairs/79.png differ diff --git a/public/images/hairs/80.png b/public/images/hairs/80.png new file mode 100644 index 0000000..13f4838 Binary files /dev/null and b/public/images/hairs/80.png differ diff --git a/public/images/hairs/81.png b/public/images/hairs/81.png new file mode 100644 index 0000000..64dfe00 Binary files /dev/null and b/public/images/hairs/81.png differ diff --git a/public/images/hairs/82.png b/public/images/hairs/82.png new file mode 100644 index 0000000..e42f5cb Binary files /dev/null and b/public/images/hairs/82.png differ diff --git a/public/images/hairs/83.png b/public/images/hairs/83.png new file mode 100644 index 0000000..f1fe801 Binary files /dev/null and b/public/images/hairs/83.png differ diff --git a/public/images/hairs/84.png b/public/images/hairs/84.png new file mode 100644 index 0000000..234bfa2 Binary files /dev/null and b/public/images/hairs/84.png differ diff --git a/public/images/hairs/85.png b/public/images/hairs/85.png new file mode 100644 index 0000000..de3e7aa Binary files /dev/null and b/public/images/hairs/85.png differ diff --git a/public/images/icons/256x256.png b/public/images/icons/256x256.png new file mode 100644 index 0000000..92ed3bd Binary files /dev/null and b/public/images/icons/256x256.png differ diff --git a/public/images/icons/512x512.png b/public/images/icons/512x512.png new file mode 100644 index 0000000..b532831 Binary files /dev/null and b/public/images/icons/512x512.png differ diff --git a/public/images/icons/academy.svg b/public/images/icons/academy.svg new file mode 100644 index 0000000..993f6de --- /dev/null +++ b/public/images/icons/academy.svg @@ -0,0 +1,30 @@ + + + + + \ No newline at end of file diff --git a/public/images/icons/add.svg b/public/images/icons/add.svg new file mode 100644 index 0000000..b3dac11 --- /dev/null +++ b/public/images/icons/add.svg @@ -0,0 +1,48 @@ + + + + + + + \ No newline at end of file diff --git a/public/images/icons/arrow-down.svg b/public/images/icons/arrow-down.svg new file mode 100644 index 0000000..2a5bb94 --- /dev/null +++ b/public/images/icons/arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/icons/block-green.svg b/public/images/icons/block-green.svg new file mode 100644 index 0000000..5b845e6 --- /dev/null +++ b/public/images/icons/block-green.svg @@ -0,0 +1,23 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/block-red.svg b/public/images/icons/block-red.svg new file mode 100644 index 0000000..3da92c2 --- /dev/null +++ b/public/images/icons/block-red.svg @@ -0,0 +1,23 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/box.svg b/public/images/icons/box.svg new file mode 100644 index 0000000..f2b4c3c --- /dev/null +++ b/public/images/icons/box.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/images/icons/calendar.svg b/public/images/icons/calendar.svg new file mode 100644 index 0000000..9f6dc43 --- /dev/null +++ b/public/images/icons/calendar.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/images/icons/candle.svg b/public/images/icons/candle.svg new file mode 100644 index 0000000..7fe4acf --- /dev/null +++ b/public/images/icons/candle.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/images/icons/celo-(celo).svg b/public/images/icons/celo-(celo).svg new file mode 100644 index 0000000..b00233f --- /dev/null +++ b/public/images/icons/celo-(celo).svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/clock.svg b/public/images/icons/clock.svg new file mode 100644 index 0000000..463b209 --- /dev/null +++ b/public/images/icons/clock.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/close-circle.svg b/public/images/icons/close-circle.svg new file mode 100644 index 0000000..d845fd6 --- /dev/null +++ b/public/images/icons/close-circle.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/icons/contact.svg b/public/images/icons/contact.svg new file mode 100644 index 0000000..deba275 --- /dev/null +++ b/public/images/icons/contact.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/images/icons/copy.svg b/public/images/icons/copy.svg new file mode 100644 index 0000000..718281b --- /dev/null +++ b/public/images/icons/copy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/courthouse.svg b/public/images/icons/courthouse.svg new file mode 100644 index 0000000..4d8ccd9 --- /dev/null +++ b/public/images/icons/courthouse.svg @@ -0,0 +1,69 @@ + + + + + + + + + + diff --git a/public/images/icons/danger.svg b/public/images/icons/danger.svg new file mode 100644 index 0000000..f8dc961 --- /dev/null +++ b/public/images/icons/danger.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/images/icons/edit.svg b/public/images/icons/edit.svg new file mode 100644 index 0000000..3c30de2 --- /dev/null +++ b/public/images/icons/edit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/icons/eye.svg b/public/images/icons/eye.svg new file mode 100644 index 0000000..bb79a41 --- /dev/null +++ b/public/images/icons/eye.svg @@ -0,0 +1,24 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/failed.svg b/public/images/icons/failed.svg new file mode 100644 index 0000000..34cd90a --- /dev/null +++ b/public/images/icons/failed.svg @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/flash-circle.svg b/public/images/icons/flash-circle.svg new file mode 100644 index 0000000..9b9dc6c --- /dev/null +++ b/public/images/icons/flash-circle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/gallery-add.svg b/public/images/icons/gallery-add.svg new file mode 100644 index 0000000..dbd2d55 --- /dev/null +++ b/public/images/icons/gallery-add.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/icons/gallery-edit.svg b/public/images/icons/gallery-edit.svg new file mode 100644 index 0000000..603dd57 --- /dev/null +++ b/public/images/icons/gallery-edit.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/images/icons/heart.svg b/public/images/icons/heart.svg new file mode 100644 index 0000000..e1899c7 --- /dev/null +++ b/public/images/icons/heart.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/icons/instagram.svg b/public/images/icons/instagram.svg new file mode 100644 index 0000000..e6aa5f0 --- /dev/null +++ b/public/images/icons/instagram.svg @@ -0,0 +1,29 @@ + + + + + \ No newline at end of file diff --git a/public/images/icons/judge.svg b/public/images/icons/judge.svg new file mode 100644 index 0000000..188486f --- /dev/null +++ b/public/images/icons/judge.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/public/images/icons/key.svg b/public/images/icons/key.svg new file mode 100644 index 0000000..0733bc1 --- /dev/null +++ b/public/images/icons/key.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/images/icons/lifebuoy.svg b/public/images/icons/lifebuoy.svg new file mode 100644 index 0000000..2025877 --- /dev/null +++ b/public/images/icons/lifebuoy.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/images/icons/location.svg b/public/images/icons/location.svg new file mode 100644 index 0000000..618e447 --- /dev/null +++ b/public/images/icons/location.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/logo.svg b/public/images/icons/logo.svg new file mode 100644 index 0000000..fe1c8e2 --- /dev/null +++ b/public/images/icons/logo.svg @@ -0,0 +1,66 @@ + + + + + + diff --git a/public/images/icons/logout.svg b/public/images/icons/logout.svg new file mode 100644 index 0000000..5581f37 --- /dev/null +++ b/public/images/icons/logout.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/icons/man.svg b/public/images/icons/man.svg new file mode 100644 index 0000000..fe81c86 --- /dev/null +++ b/public/images/icons/man.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/images/icons/medal-star.svg b/public/images/icons/medal-star.svg new file mode 100644 index 0000000..8c5d932 --- /dev/null +++ b/public/images/icons/medal-star.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/images/icons/message-text.svg b/public/images/icons/message-text.svg new file mode 100644 index 0000000..60365de --- /dev/null +++ b/public/images/icons/message-text.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/icons/mobile.svg b/public/images/icons/mobile.svg new file mode 100644 index 0000000..f21ce09 --- /dev/null +++ b/public/images/icons/mobile.svg @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/public/images/icons/moon.svg b/public/images/icons/moon.svg new file mode 100644 index 0000000..38486d3 --- /dev/null +++ b/public/images/icons/moon.svg @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/public/images/icons/not-verify.svg b/public/images/icons/not-verify.svg new file mode 100644 index 0000000..c0448da --- /dev/null +++ b/public/images/icons/not-verify.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/notification.svg b/public/images/icons/notification.svg new file mode 100644 index 0000000..93942a3 --- /dev/null +++ b/public/images/icons/notification.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/images/icons/offer.svg b/public/images/icons/offer.svg new file mode 100644 index 0000000..815bbd1 --- /dev/null +++ b/public/images/icons/offer.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/public/images/icons/people.svg b/public/images/icons/people.svg new file mode 100644 index 0000000..256f584 --- /dev/null +++ b/public/images/icons/people.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/images/icons/phone.svg b/public/images/icons/phone.svg new file mode 100644 index 0000000..eae4e7a --- /dev/null +++ b/public/images/icons/phone.svg @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/public/images/icons/red-heart.svg b/public/images/icons/red-heart.svg new file mode 100644 index 0000000..2a012d2 --- /dev/null +++ b/public/images/icons/red-heart.svg @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/public/images/icons/ruler&pen.svg b/public/images/icons/ruler&pen.svg new file mode 100644 index 0000000..3c2cbc6 --- /dev/null +++ b/public/images/icons/ruler&pen.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/images/icons/search-normal.svg b/public/images/icons/search-normal.svg new file mode 100644 index 0000000..de1068d --- /dev/null +++ b/public/images/icons/search-normal.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/select-img.svg b/public/images/icons/select-img.svg new file mode 100644 index 0000000..c3b7ac2 --- /dev/null +++ b/public/images/icons/select-img.svg @@ -0,0 +1,29 @@ + + + + + \ No newline at end of file diff --git a/public/images/icons/send-msg.svg b/public/images/icons/send-msg.svg new file mode 100644 index 0000000..5adfd67 --- /dev/null +++ b/public/images/icons/send-msg.svg @@ -0,0 +1,22 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/services.svg b/public/images/icons/services.svg new file mode 100644 index 0000000..6f17a69 --- /dev/null +++ b/public/images/icons/services.svg @@ -0,0 +1,40 @@ + + + + + + \ No newline at end of file diff --git a/public/images/icons/share.svg b/public/images/icons/share.svg new file mode 100644 index 0000000..09c696c --- /dev/null +++ b/public/images/icons/share.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/images/icons/shop-add.svg b/public/images/icons/shop-add.svg new file mode 100644 index 0000000..9c13db7 --- /dev/null +++ b/public/images/icons/shop-add.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/images/icons/sms.svg b/public/images/icons/sms.svg new file mode 100644 index 0000000..b3e62b9 --- /dev/null +++ b/public/images/icons/sms.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/star1.svg b/public/images/icons/star1.svg new file mode 100644 index 0000000..a46bcbf --- /dev/null +++ b/public/images/icons/star1.svg @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/public/images/icons/submit.svg b/public/images/icons/submit.svg new file mode 100644 index 0000000..a878824 --- /dev/null +++ b/public/images/icons/submit.svg @@ -0,0 +1,22 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/success.svg b/public/images/icons/success.svg new file mode 100644 index 0000000..f22bdc7 --- /dev/null +++ b/public/images/icons/success.svg @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/sun.svg b/public/images/icons/sun.svg new file mode 100644 index 0000000..7f46a67 --- /dev/null +++ b/public/images/icons/sun.svg @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/teacher.svg b/public/images/icons/teacher.svg new file mode 100644 index 0000000..12a25a6 --- /dev/null +++ b/public/images/icons/teacher.svg @@ -0,0 +1,27 @@ + + + + + diff --git a/public/images/icons/telegram.svg b/public/images/icons/telegram.svg new file mode 100644 index 0000000..2cd8a2d --- /dev/null +++ b/public/images/icons/telegram.svg @@ -0,0 +1,22 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/timer.svg b/public/images/icons/timer.svg new file mode 100644 index 0000000..e480f39 --- /dev/null +++ b/public/images/icons/timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/icons/user-tick.svg b/public/images/icons/user-tick.svg new file mode 100644 index 0000000..7aa3ef9 --- /dev/null +++ b/public/images/icons/user-tick.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/icons/verify.svg b/public/images/icons/verify.svg new file mode 100644 index 0000000..325af55 --- /dev/null +++ b/public/images/icons/verify.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/verify2.svg b/public/images/icons/verify2.svg new file mode 100644 index 0000000..ae04a6d --- /dev/null +++ b/public/images/icons/verify2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/verify3.svg b/public/images/icons/verify3.svg new file mode 100644 index 0000000..16228b0 --- /dev/null +++ b/public/images/icons/verify3.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/wallet.svg b/public/images/icons/wallet.svg new file mode 100644 index 0000000..31b9a01 --- /dev/null +++ b/public/images/icons/wallet.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/public/images/icons/weight.svg b/public/images/icons/weight.svg new file mode 100644 index 0000000..8f45d2e --- /dev/null +++ b/public/images/icons/weight.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/icons/whatsapp.svg b/public/images/icons/whatsapp.svg new file mode 100644 index 0000000..9aa3845 --- /dev/null +++ b/public/images/icons/whatsapp.svg @@ -0,0 +1,22 @@ + + + + \ No newline at end of file diff --git a/public/images/icons/woman.svg b/public/images/icons/woman.svg new file mode 100644 index 0000000..f5ffd94 --- /dev/null +++ b/public/images/icons/woman.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/images/loading.gif b/public/images/loading.gif new file mode 100644 index 0000000..60c6bdf Binary files /dev/null and b/public/images/loading.gif differ diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..0f6b4bb Binary files /dev/null and b/public/logo.png differ diff --git a/public/manifest.json b/public/manifest.json new file mode 100644 index 0000000..6757fa0 --- /dev/null +++ b/public/manifest.json @@ -0,0 +1,21 @@ +{ + "name": "Modstagram", + "short_name": "Modstagram", + "description": "Modstagram App", + "icons": [ + { + "src": "/images/icons/256x256.png", + "sizes": "256x256", + "type": "image/png" + }, + { + "src": "/images/icons/512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone", + "start_url": "/" +} diff --git a/public/modstagram-back/.eslintrc.json b/public/modstagram-back/.eslintrc.json new file mode 100644 index 0000000..20328b0 --- /dev/null +++ b/public/modstagram-back/.eslintrc.json @@ -0,0 +1,14 @@ +{ + "env": { + "commonjs": true, + "es2021": true, + "node": true + }, + "extends": "standard", + "parserOptions": { + "ecmaVersion": "latest" + }, + "rules": { + "indent": ["error", 2] + } +} diff --git a/public/modstagram-back/.gitignore b/public/modstagram-back/.gitignore new file mode 100644 index 0000000..65d3ddc --- /dev/null +++ b/public/modstagram-back/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +.env +.vscode/ \ No newline at end of file diff --git a/public/modstagram-back/boot/index.js b/public/modstagram-back/boot/index.js new file mode 100644 index 0000000..1a0d11f --- /dev/null +++ b/public/modstagram-back/boot/index.js @@ -0,0 +1,2 @@ +const startMongoDB = require('./mongo') +startMongoDB() diff --git a/public/modstagram-back/boot/mongo.js b/public/modstagram-back/boot/mongo.js new file mode 100644 index 0000000..2d4259a --- /dev/null +++ b/public/modstagram-back/boot/mongo.js @@ -0,0 +1,24 @@ +// const mongoose = require('mongoose') +// const { MONGO_DBNAME, MONGO_HOST, MONGO_PORT } = process.env +// mongoose.connection.on('error', (error) => { +// console.log('mongodb connection failed! ', error.message) +// }) +// const startMongoDB = () => { +// mongoose.connect(`mongodb://${MONGO_HOST}:${MONGO_PORT}/${MONGO_DBNAME}`, { +// }) +// } +// module.exports = startMongoDB + +const mongoose = require('mongoose') +mongoose.connection.on('error', (error) => { + console.log('mongodb connection failed! ', error.message) +}) +mongoose.connection.on('open', function () { + console.log('Database Connected! ') +}) +const startMongoDB = () => { + mongoose.connect(process.env.DATABASE_URL, { + authSource: 'admin' + }) +} +module.exports = startMongoDB diff --git a/public/modstagram-back/controllers/application/academy/academyCategoryController.js b/public/modstagram-back/controllers/application/academy/academyCategoryController.js new file mode 100644 index 0000000..07bfec8 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/academyCategoryController.js @@ -0,0 +1,74 @@ +const AcademyCategoryModel = require('../../../models/AcademyCategoryModel'); +// GET all categories +exports.getAll = async (req, res) => { + try { + const categories = await AcademyCategoryModel.find({}).sort({ createdAt: -1 }); + res.status(200).json({ success: true, categories }); + } catch (error) { + res.status(500).json({ success: false, message: error.message }); + } +}; + +// CREATE category +exports.create = async (req, res) => { + try { + const { title, status } = req.body; + + if (!title) { + return res.status(400).json({ success: false, message: "title is required" }); + } + + const newCategory = new AcademyCategoryModel({ + title, + status: status ?? true, + }); + + await newCategory.save(); + + res.status(201).json({ success: true, category: newCategory }); + } catch (error) { + res.status(500).json({ success: false, message: error.message }); + } +}; + +// UPDATE category +exports.update = async (req, res) => { + try { + const { id } = req.params; + const { title, status } = req.body; + + const updated = await AcademyCategoryModel.findByIdAndUpdate( + id, + { title, status }, + { new: true, runValidators: true } + ); + + if (!updated) { + return res.status(404).json({ success: false, message: "category not found" }); + } + + res.status(200).json({ success: true, category: updated }); + } catch (error) { + res.status(500).json({ success: false, message: error.message }); + } +}; + +// DELETE +exports.remove = async (req, res) => { + try { + const { id } = req.params; + + const deleted = await AcademyCategoryModel.findByIdAndDelete(id); + + if (!deleted) { + return res.status(404).json({ success: false, message: "category not found" }); + } + + res.status(200).json({ + success: true, + message: 'category deleted successfully' + }); + } catch (error) { + res.status(500).json({ success: false, message: error.message }); + } +}; diff --git a/public/modstagram-back/controllers/application/academy/academyControllers.js b/public/modstagram-back/controllers/application/academy/academyControllers.js new file mode 100644 index 0000000..d11b344 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/academyControllers.js @@ -0,0 +1,4430 @@ +const jwt = require("jsonwebtoken"); +const fs = require("fs-extra"); +const path = require("path"); +const jMoment = require("moment-jalaali"); +const AcademyContentModel = require("../../../models/AcademyContentModel"); +const AcademyModel = require("../../../models/AcademyModel"); +const AcademyPaymentModel = require("../../../models/AcademyPaymentModel"); +const CourseModel = require("../../../models/CourseModel"); +const CoursePaymentModel = require("../../../models/CoursePaymentModel"); +const UserModel = require("../../../models/UserModel"); +const PaymentModel = require("../../../models/PaymentModel"); +const { default: axios } = require("axios"); +const AcademyLikeModel = require("../../../models/AcademyLikeModel"); +const CourseComment = require("../../../models/CourseComentModel"); +const IsPaymentCourse = require("../../../models/IsPaymentCourseModel"); +const Tax = require("../../../models/TaxModel"); +const AcademyCategoryModel = require('../../../models/AcademyCategoryModel'); + +const onServerRestart = async () => { + const CoursePayment = await CoursePaymentModel.findOne({ + cuorse_type: "pro", + }); + if (!CoursePayment) { + const newCoursePayment = new CoursePaymentModel({ + price: "60000", + cuorse_type: "pro", + }); + await newCoursePayment.save(); + + return console.log("اشتراک پرو ساخته شد"); + } + + console.log("اشتراک پرو موجود هست"); + const tax = await Tax.findOne({ + type: "course", + }); + if (!tax) { + const newTax = new Tax({ + tax: 8, + type: "course", + }); + await newTax.save(); + + return console.log("تکس ساخته شد"); + } + + console.log(" تکس موجود هست"); +}; +onServerRestart(); + +const findAcademy = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const user = await UserModel.findById(userId); + if (!user) { + return res.status(422).json({ + error: true, + message: "کاربر یافت نشد", + }); + } + const academy = await AcademyModel.findOne({ userId: userId }); + if (!academy) { + const newAcademy = new AcademyModel({ + userId: userId, + }); + await newAcademy.save(); + + return res.status(200).json({ + academy: newAcademy, + }); + } + + res.status(200).json({ + academy: academy, + }); + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error("Error:", error); + res.status(500).json({ message: "err in creat" }); + } +}; +const findAcademyById = async (req, res, next) => { + try { + const { _id } = req.body; + + const academy = await AcademyModel.findById(_id); + if (!academy) { + res.status(500).json({ + academy: "اکادمی موحود نیست", + }); + } + + res.status(200).json({ + academy: academy, + }); + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error("Error:", error); + res.status(500).json({ message: "err in creat" }); + } +}; +const academyProfile = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const user = await UserModel.findById(userId); + if (!user) { + return res.status(422).json({ + error: true, + message: "کاربر یافت نشد", + }); + } + const academy = await AcademyModel.findOne({ userId: userId }); + if (!academy) { + return res.status(200).json({ + message: "اکادمی پیدا نشد", + }); + } + + const { profile_image } = req.files; + const { name, sheba, bio, tag } = req.body; + + if (!profile_image) { + return res.status(422).json({ + error: true, + message: "اطلاعات ارسالی اشتباه است", + }); + } + + const uploadDir = path.join(__dirname, "../../../../storage/profiles"); + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }); + } + + const uniqueFileName = `${name}-${Date.now()}${path.extname( + profile_image.name + )}`; + const filePath = path.join(uploadDir, uniqueFileName); + + await fs.move(profile_image.path, filePath); + + academy.academy_image = `/profiles/${uniqueFileName}`; + academy.academy_name = name; + academy.sheba = sheba; + academy.bio = bio; + academy.tag = tag; + await academy.save(); + + res.status(200).json({ + message: "ثبت شد", + }); + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error("Error:", error); + res.status(500).json({ message: "err in update" }); + } +}; + +const creatCourse = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const user = await UserModel.findById(userId); + if (!user) { + return res.status(422).json({ + error: true, + message: "کاربر یافت نشد", + }); + } + + const academy = await AcademyModel.findOne({ userId: userId }); + if (!academy) { + return res.status(200).json({ + message: "اکادمی پیدا نشد", + }); + } + const { + price, + cuorse_name, + category, + offer, + caption, + course_time, + number_of_course_content, + teacher_number, + teacher_name, + } = req.body; + + const { course_image } = req.files; + + if (!course_image) { + return res.status(422).json({ + error: true, + message: "اطلاعات ارسالی اشتباه است", + }); + } + + const uploadDir = path.join(__dirname, "../../../../storage/profiles"); + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }); + } + + const uniqueFileName = `${cuorse_name}-${Date.now()}${path.extname( + course_image.name + )}`; + const filePath = path.join(uploadDir, uniqueFileName); + + await fs.move(course_image.path, filePath); + + // ✅ ایجاد رکورد جدید + const newAcademy = new CourseModel({ + course_image: `/profiles/${uniqueFileName}`, + price, + cuorse_name, + category, + offer, + teacher_name, + academyId: academy._id, + caption, + course_time, + number_of_course_content, + teacher_number, + }); + + await newAcademy.save(); + + res.status(200).json({ + message: "ثبت شد", + }); + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error("Error:", error); + res.status(500).json({ message: "err in update" }); + } +}; + +const updateCourse = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { + price, + cuorse_name, + category, + offer, + courseId, + teacher_name, + caption, + course_time, + number_of_course_content, + teacher_number, + } = req.body; + + // اعتبارسنجی courseId + if (!courseId) { + return res.status(422).json({ + error: true, + message: "آیدی دوره الزامی است", + }); + } + + const user = await UserModel.findById(userId); + if (!user) { + return res.status(422).json({ + error: true, + message: "کاربر یافت نشد", + }); + } + + const course = await CourseModel.findById(courseId); + if (!course) { + return res.status(422).json({ + error: true, + message: "پکیجی یافت نشد", + }); + } + + // ========== آپلود عکس جدید (اختیاری) ========== + const { course_image } = req.files || {}; + + if (course_image) { + // فقط اگه عکس جدید آپلود شده بود، آپلود کن + const uploadDir = path.join(__dirname, "../../../../storage/profiles"); + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }); + } + + // استفاده از id به جای نام دوره برای نام فایل + const safeFileName = `course-${courseId}-${Date.now()}${path.extname( + course_image.name + )}`; + const filePath = path.join(uploadDir, safeFileName); + + await fs.move(course_image.path, filePath); + course.course_image = `/profiles/${safeFileName}`; + } + + // ========== به روز رسانی فیلدها (فقط فیلدهایی که ارسال شده) ========== + if (price !== undefined) course.price = price; + if (cuorse_name !== undefined) course.cuorse_name = cuorse_name; + if (category !== undefined) course.category = category; + if (offer !== undefined) course.offer = offer; + if (caption !== undefined) course.caption = caption; + if (course_time !== undefined) course.course_time = course_time; + if (number_of_course_content !== undefined) + course.number_of_course_content = number_of_course_content; + if (teacher_number !== undefined) course.teacher_number = teacher_number; + if (teacher_name !== undefined) course.teacher_name = teacher_name; + + await course.save(); + + res.status(200).json({ + success: true, + message: "دوره با موفقیت به روز رسانی شد", + data: { + course: course, + }, + }); + } catch (error) { + console.error("Error in updateCourse:", error); + res.status(500).json({ + success: false, + message: "خطا در به روز رسانی دوره", + error: error.message, + }); + } +}; +const deleteCourse = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + const { courseId } = req.body; + + const user = await UserModel.findById(userId); + if (!user) { + return res.status(422).json({ + error: true, + message: "کاربر یافت نشد", + }); + } + const course = await CourseModel.findById(courseId); + if (!course) { + return res.status(422).json({ + error: true, + message: "پکیجی یافت نشد", + }); + } + + course.status = "reject"; + await course.save(); + + res.status(200).json({ + message: "ثبت شد", + }); + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error("Error:", error); + res.status(500).json({ message: "err in update" }); + } +}; +const getCourse = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + // گرفتن پارامترهای صفحه‌بندی + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 10; + const skip = (page - 1) * limit; + + const user = await UserModel.findById(userId); + if (!user) { + return res.status(422).json({ + error: true, + message: "کاربر یافت نشد", + }); + } + + const academy = await AcademyModel.findOne({ userId: userId }); + if (!academy) { + return res.status(404).json({ + success: false, + message: "آکادمی پیدا نشد", + }); + } + + // ✅ شرط جستجو - فقط دوره‌های تایید شده + const query = { + academyId: academy._id, + status: "accept", + }; + + // دریافت تعداد کل دوره‌های تایید شده + const totalCourses = await CourseModel.countDocuments(query); + + // دریافت دوره‌های تایید شده با صفحه‌بندی + const courses = await CourseModel.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit); + + // ✅ اگر دوره‌ای وجود نداشت، خطا نده، بلکه آرایه خالی برگردون + if (!courses || courses.length === 0) { + return res.status(200).json({ + success: true, + message: "هیچ دوره تایید شده‌ای یافت نشد", + data: { + courses: [], + pagination: { + currentPage: page, + totalPages: 0, + totalItems: 0, + itemsPerPage: limit, + hasNextPage: false, + hasPrevPage: false, + nextPage: null, + prevPage: null, + }, + }, + }); + } + + // محاسبات صفحه‌بندی + const totalPages = Math.ceil(totalCourses / limit); + const hasNextPage = page < totalPages; + const hasPrevPage = page > 1; + + res.status(200).json({ + success: true, + message: "لیست پکیج‌ها با موفقیت دریافت شد", + data: { + courses: courses, + pagination: { + currentPage: page, + totalPages: totalPages, + totalItems: totalCourses, + itemsPerPage: limit, + hasNextPage: hasNextPage, + hasPrevPage: hasPrevPage, + nextPage: hasNextPage ? page + 1 : null, + prevPage: hasPrevPage ? page - 1 : null, + }, + }, + }); + } catch (error) { + console.error("Error:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت پکیج‌ها", + error: error.message, + }); + } +}; + +const getCourses = async (req, res, next) => { + try { + // ========== 3. دریافت پارامترهای صفحه‌بندی ========== + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 10; + const skip = (page - 1) * limit; + + // ========== 4. دریافت پارامترهای جستجو ========== + const search = req.query.search || ""; + const category = req.query.category || ""; + const minPrice = req.query.minPrice ? parseInt(req.query.minPrice) : 0; + const maxPrice = req.query.maxPrice + ? parseInt(req.query.maxPrice) + : 100000000; + const hasOffer = req.query.hasOffer === "true"; // تخفیف دار + const teacherName = req.query.teacherName || ""; + const type = req.query.type || ""; // normal, pro, legend + const status = req.query.status || "all"; // pending, accept, reject + const sortBy = req.query.sortBy || "createdAt"; + const sortOrder = req.query.sortOrder === "asc" ? 1 : -1; + const _id = req.query._id || ""; + // ========== 5. ساخت شرط جستجو (Query) ========== + let query = {}; + + // جستجو در نام دوره و کپشن + if (search) { + query.$or = [ + { cuorse_name: { $regex: search, $options: "i" } }, + { caption: { $regex: search, $options: "i" } }, + { teacher_name: { $regex: search, $options: "i" } }, + ]; + } + + // فیلتر بر اساس دسته بندی + if (category) { + query.category = category; + } + if (_id) { + query._id = _id; + } + // فیلتر بر اساس محدوده قیمت (تبدیل به عدد برای مقایسه) + if (minPrice > 0 || maxPrice < 100000000) { + query.price = { + $gte: minPrice.toString(), + $lte: maxPrice.toString(), + }; + } + + // فیلتر بر اساس تخفیف دار (offer وجود داشته باشد و از 0 بیشتر باشد) + if (hasOffer) { + query.offer = { $exists: true, $ne: "0", $ne: "" }; + } + + // فیلتر بر اساس نام مدرس + if (teacherName) { + query.teacher_name = { $regex: teacherName, $options: "i" }; + } + + // فیلتر بر اساس نوع دوره + if (type) { + query.type = type; + } + + // فیلتر بر اساس وضعیت + if (status !== "all") { + query.status = status; + } + + // ========== 6. دریافت آمار و اطلاعات ========== + // تعداد کل پکیج‌ها (بدون صفحه‌بندی) + const totalCourses = await CourseModel.countDocuments(query); + + // مجموع قیمت‌ها (تبدیل به عدد برای محاسبه) + const priceStats = await CourseModel.aggregate([ + { $match: query }, + { + $group: { + _id: null, + total: { $sum: { $toDouble: "$price" } }, + avg: { $avg: { $toDouble: "$price" } }, + min: { $min: { $toDouble: "$price" } }, + max: { $max: { $toDouble: "$price" } }, + }, + }, + ]); + + // تعداد دوره‌های با تخفیف + const offeredCourses = await CourseModel.countDocuments({ + ...query, + offer: { $exists: true, $ne: "0", $ne: "" }, + }); + + // تعداد دوره‌ها بر اساس نوع + const typeStats = await CourseModel.aggregate([ + { $match: query }, + { + $group: { + _id: "$type", + count: { $sum: 1 }, + }, + }, + ]); + + // ========== 7. دریافت پکیج‌ها با صفحه‌بندی ========== + const courses = await CourseModel.find(query) + .populate("user_id", "name email") // اطلاعات کاربر سازنده + .populate("likes", "name") // اطلاعات لایک‌ها + .sort({ [sortBy]: sortOrder }) + .skip(skip) + .limit(limit) + .lean(); + + // پردازش داده‌ها برای خروجی + const processedCourses = courses.map((course) => ({ + ...course, + priceNumber: parseInt(course.price) || 0, + offerNumber: parseInt(course.offer) || 0, + finalPrice: course.offer + ? (parseInt(course.price) * (100 - parseInt(course.offer))) / 100 + : parseInt(course.price), + likesCount: course.likes?.length || 0, + })); + + // ========== 8. محاسبات صفحه‌بندی ========== + const totalPages = Math.ceil(totalCourses / limit); + const hasNextPage = page < totalPages; + const hasPrevPage = page > 1; + + // محاسبه محدوده نمایش + const startItem = totalCourses === 0 ? 0 : (page - 1) * limit + 1; + const endItem = Math.min(page * limit, totalCourses); + + // ========== 9. ارسال پاسخ ========== + res.status(200).json({ + success: true, + message: "لیست پکیج‌ها با موفقیت دریافت شد", + data: { + courses: processedCourses, + stats: { + totalCourses, + offeredCourses, + averagePrice: Math.round(priceStats[0]?.avg || 0), + minPrice: priceStats[0]?.min || 0, + maxPrice: priceStats[0]?.max || 0, + totalPrice: priceStats[0]?.total || 0, + typeStats: typeStats, + }, + pagination: { + currentPage: page, + totalPages: totalPages, + totalItems: totalCourses, + itemsPerPage: limit, + hasNextPage: hasNextPage, + hasPrevPage: hasPrevPage, + nextPage: hasNextPage ? page + 1 : null, + prevPage: hasPrevPage ? page - 1 : null, + startItem: startItem, + endItem: endItem, + }, + filters: { + search: search, + category: category, + minPrice: minPrice, + maxPrice: maxPrice, + hasOffer: hasOffer, + teacherName: teacherName, + type: type, + sortBy: sortBy, + sortOrder: sortOrder === 1 ? "asc" : "desc", + status: status, + }, + }, + }); + } catch (error) { + console.error("Error in getCourses:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت پکیج‌ها", + error: error.message, + }); + } +}; + +const proPayment = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + const { courseId } = req.body; + + // ========== 1. بررسی وجود CoursePayment ========== + const coursePayment = await CoursePaymentModel.findOne({ + cuorse_type: "pro", + }); + + if (!coursePayment) { + return res.status(404).json({ + error: true, + message: "قیمت‌گذاری برای نوع پرو یافت نشد", + }); + } + + const price = coursePayment.price; + + // ========== 2. اعتبارسنجی قیمت ========== + if (!price || isNaN(Number(price)) || Number(price) <= 0) { + return res.status(422).json({ + error: true, + message: "مبلغ نامعتبر است", + }); + } + + // ========== 3. بررسی وجود دوره ========== + const course = await CourseModel.findById(courseId); + if (!course) { + return res.status(404).json({ + error: true, + message: "پکیجی یافت نشد", + }); + } + + // ========== 4. محاسبه مبلغ ========== + const amount = Number(price) * 10; + + // مبلغ باید حداقل 1000 تومان باشد (طبق قوانین زرین‌پال) + if (amount < 1000) { + return res.status(422).json({ + error: true, + message: "مبلغ باید حداقل 1000 تومان باشد", + }); + } + + const callbackUrl = `https://api.modstagram.com/api/v1/academy/academy/course/pro?courseId=${courseId}&userId=${userId}`; + + // ========== 5. درخواست به زرین‌پال ========== + const zarinpalRes = await axios.post( + "https://api.zarinpal.com/pg/v4/payment/request.json", + { + merchant_id: + process.env.ZARINPAL_MERCHANT_ID || + "c7c41e8a-918f-4741-bcd5-58f3bc51db73", + amount: Math.round(amount), // حتماً عدد صحیح باشد + description: `خرید اشتراک پرو برای ${course.cuorse_name}`, + callback_url: callbackUrl, + metadata: { + user_id: userId, + course_id: courseId, + }, + }, + { + headers: { "Content-Type": "application/json" }, + timeout: 10000, // 10 ثانیه تایم‌اوت + } + ); + + const result = zarinpalRes.data; + + // ========== 6. بررسی پاسخ زرین‌پال ========== + if (result.data && result.data.code === 100) { + // ذخیره اطلاعات پرداخت در دیتابیس (اختیاری) + await PaymentModel.create({ + authority: result.data.authority, + amount: amount, + user_id: userId, + course_id: courseId, + status: "pending", + type: "pro", + createdAt: new Date(), + }); + + return res.status(200).json({ + success: true, + authority: result.data.authority, + paymentUrl: `https://www.zarinpal.com/pg/StartPay/${result.data.authority}`, + }); + } + + // خطای زرین‌پال + console.error("ZarinPal error:", result); + return res.status(422).json({ + error: true, + message: result.errors?.message || "خطا در ارتباط با درگاه پرداخت", + details: result.errors, + }); + } catch (error) { + console.error( + "Error in proPayment:", + error.response?.data || error.message + ); + res.status(500).json({ + error: true, + message: "خطا در پردازش پرداخت", + details: error.response?.data || error.message, + }); + } +}; + +const handleCoursePaymentCallback = async (req, res) => { + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS"); + res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization"); + + try { + const { Authority, Status, userId, courseId } = req.query; + + if (Status !== "OK") { + return res.redirect(`${process.env.APP_SITE}/offer/payment/failed`); + } + + // ========== 1. پیدا کردن قیمت ========== + const coursePayment = await CoursePaymentModel.findOne({ + cuorse_type: "pro", + }); + + if (!coursePayment) { + return res.redirect( + `${process.env.APP_SITE}/offer/payment/failed?message=price_not_found` + ); + } + + const price = coursePayment.price; + const amount = Number(price) * 10; + + // ========== 2. تایید پرداخت با زرین‌پال ========== + const verify = await axios.post( + "https://api.zarinpal.com/pg/v4/payment/verify.json", + { + merchant_id: + process.env.ZARINPAL_MERCHANT_ID || + "c7c41e8a-918f-4741-bcd5-58f3bc51db73", + authority: Authority, + amount: Math.round(amount), + }, + { + headers: { "Content-Type": "application/json" }, + timeout: 10000, + } + ); + + const data = verify.data.data; + + // ========== 3. بررسی نتیجه تایید ========== + if (data.code === 100) { + // ثبت پرداخت موفق + await PaymentModel.create({ + amount: amount / 10, + status: "successful", + authority: Authority, + ref_id: data.ref_id, + user_id: userId, + course_id: courseId, + type: "course", + verifiedAt: new Date(), + }); + + // به روز رسانی نوع دوره به pro + const course = await CourseModel.findById(courseId); + if (course) { + course.type = "pro"; + await course.save(); + } + + // به روز رسانی وضعیت کاربر (اشتراک پرو) + await UserModel.findByIdAndUpdate(userId, { + $set: { + "proSubscription.active": true, + "proSubscription.courseId": courseId, + "proSubscription.startDate": new Date(), + "proSubscription.purchaseDate": new Date(), + }, + }); + + return res.redirect( + `${process.env.APP_SITE}/settings/academy/course?payment=success` + ); + } + + // پرداخت ناموفق + return res.redirect( + `${process.env.APP_SITE}/offer/payment/failed?code=${data.code}` + ); + } catch (err) { + console.error("Error in handleCoursePaymentCallback:", err); + return res.redirect( + `${process.env.APP_SITE}/offer/payment/failed?message=verification_error` + ); + } +}; + +const creatCourseVideo = async (req, res, next) => { + console.log("=== New request received ==="); + console.log("Headers:", req.headers); + console.log("Body:", req.body); + console.log("File:", req.file); + + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { courseId, is_free, file_name } = req.body; + const videoFile = req.file; + + if (!videoFile) { + return res.status(422).json({ + error: true, + message: "فایل ویدیو ارسال نشده است", + }); + } + + if (!courseId) { + return res.status(422).json({ + error: true, + message: "شناسه دوره الزامی است", + }); + } + + // مسیر ذخیره‌سازی نهایی (مشابه سیستم پست‌ها) + const finalVideoDir = path.join( + __dirname, + "../../../storage/courses/videos" + ); + const safeFileName = `course-${courseId}-${Date.now()}${path.extname( + videoFile.originalname + )}`; + const filePath = path.join(finalVideoDir, safeFileName); + + // انتقال فایل از محل موقت به محل نهایی + await fs.rename(videoFile.path, filePath); + + // ایجاد رکورد جدید در دیتابیس + const newAcademyContent = new AcademyContentModel({ + course_video: `/storage/posts/videos/${safeFileName}`, + type: "video", + is_free: is_free === "true" || is_free === true, + courseId, + file_name: file_name || videoFile.originalname, + }); + + await newAcademyContent.save(); + + const course = await CourseModel.findById(courseId); + if (!course) { + return res.status(404).json({ + success: false, + message: "پکیج پیدا نشد", + }); + } + + course.number_of_course_content = `${ + Number(course.number_of_course_content) + 1 + }`; + await course.save(); + + res.status(200).json({ + success: true, + message: "ویدیو با موفقیت ثبت شد", + data: newAcademyContent, + }); + } catch (error) { + console.error("Error in creatCourseVideo:", error); + res.status(500).json({ + success: false, + message: "خطا در ثبت ویدیو", + error: error.message, + }); + } +}; + +const creatCourseVideoBase64 = async (req, res, next) => { + console.log("=== Base64 Video Upload ==="); + console.log("Body:", Object.keys(req.body)); + + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { courseId, is_free, file_name, video_base64, mime_type } = req.body; + + // اعتبارسنجی + if (!video_base64) { + return res.status(422).json({ + error: true, + message: "فایل ویدیو ارسال نشده است", + }); + } + + if (!courseId) { + return res.status(422).json({ + error: true, + message: "شناسه دوره الزامی است", + }); + } + + // تبدیل Base64 به بافر + const base64Data = video_base64.split(",")[1] || video_base64; + const buffer = Buffer.from(base64Data, "base64"); + + console.log("Buffer size:", buffer.length, "bytes"); + + // ایجاد دایرکتوری اگر وجود ندارد + const finalVideoDir = path.join( + process.cwd(), + "storage", + "courses", + "videos" + ); + if (!fs.existsSync(finalVideoDir)) { + fs.mkdirSync(finalVideoDir, { recursive: true }); + } + + // تعیین پسوند فایل از mime_type + let extension = ".mp4"; + if (mime_type === "video/mp4") extension = ".mp4"; + else if (mime_type === "video/quicktime") extension = ".mov"; + else if (mime_type === "video/x-msvideo") extension = ".avi"; + else if (mime_type === "video/webm") extension = ".webm"; + + const safeFileName = `course-${courseId}-${Date.now()}${extension}`; + const filePath = path.join(finalVideoDir, safeFileName); + + // ذخیره فایل + await fs.writeFileSync(filePath, buffer); + + console.log("File saved:", filePath); + + // ایجاد رکورد در دیتابیس + const newAcademyContent = new AcademyContentModel({ + course_video: `/storage/courses/videos/${safeFileName}`, + type: "video", + is_free: is_free === "true" || is_free === true, + courseId, + file_name: file_name, + }); + + await newAcademyContent.save(); + + // به روز رسانی تعداد محتواهای دوره + const course = await CourseModel.findById(courseId); + if (course) { + course.number_of_course_content = `${ + Number(course.number_of_course_content) + 1 + }`; + await course.save(); + } + + res.status(200).json({ + success: true, + message: "ویدیو با موفقیت ثبت شد", + data: newAcademyContent, + }); + } catch (error) { + console.error("Error in creatCourseVideoBase64:", error); + res.status(500).json({ + success: false, + message: "خطا در ثبت ویدیو", + error: error.message, + }); + } +}; + +const getCourseContent = async (req, res, next) => { + try { + // ✅ اصلاح: دریافت courseId از query یا params + const courseId = req.query.courseId || req.params.courseId; + + // اعتبارسنجی courseId + if (!courseId) { + return res.status(422).json({ + error: true, + message: "شناسه دوره الزامی است", + }); + } + + // گرفتن پارامترهای صفحه‌بندی + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 10; + const skip = (page - 1) * limit; + + const academy = await CourseModel.findById(courseId); + if (!academy) { + return res.status(404).json({ + success: false, + message: "پکیج پیدا نشد", + }); + } + + // ✅ شرط جستجو - فقط دوره‌های تایید شده + const query = { + courseId: academy._id, + status: "accept", + }; + + // دریافت تعداد کل دوره‌های تایید شده + const totalCourses = await AcademyContentModel.countDocuments(query); + + // دریافت دوره‌های تایید شده با صفحه‌بندی + const courses = await AcademyContentModel.find(query) + .skip(skip) + .limit(limit); + + // ✅ اگر دوره‌ای وجود نداشت، خطا نده، بلکه آرایه خالی برگردون + if (!courses || courses.length === 0) { + return res.status(200).json({ + success: true, + message: "هیچ محتوایی یافت نشد", + data: { + courses: [], + pagination: { + currentPage: page, + totalPages: 0, + totalItems: 0, + itemsPerPage: limit, + hasNextPage: false, + hasPrevPage: false, + }, + }, + }); + } + + // محاسبات صفحه‌بندی + const totalPages = Math.ceil(totalCourses / limit); + const hasNextPage = page < totalPages; + const hasPrevPage = page > 1; + + res.status(200).json({ + success: true, + message: "لیست محتواها با موفقیت دریافت شد", + data: { + courses: courses, + pagination: { + currentPage: page, + totalPages: totalPages, + totalItems: totalCourses, + itemsPerPage: limit, + hasNextPage: hasNextPage, + hasPrevPage: hasPrevPage, + nextPage: hasNextPage ? page + 1 : null, + prevPage: hasPrevPage ? page - 1 : null, + }, + }, + }); + } catch (error) { + console.error("Error in getCourseContent:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت محتواها", + error: error.message, + }); + } +}; +// لایک کردن محتوا +const likeCourseContent = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + if (!userId) { + return res.status(422).json({ + error: true, + message: "برای لایک کردن وارد حساب کاربری خود شوید", + }); + } + + const { courseId } = req.body; + + // بررسی وجود دوره + const course = await CourseModel.findById(courseId); + if (!course) { + return res.status(404).json({ + success: false, + message: "پکیج پیدا نشد", + }); + } + + // بررسی اینکه آیا قبلاً لایک کرده است + const existingLike = await AcademyLikeModel.findOne({ + user_id: userId, + course_id: courseId, + }); + + if (existingLike) { + return res.status(400).json({ + success: false, + message: "شما قبلاً این دوره را لایک کرده‌اید", + }); + } + + // افزایش تعداد لایک‌های دوره + course.likes = (course.likes || 0) + 1; + await course.save(); + + // ایجاد رکورد لایک + await AcademyLikeModel.create({ + user_id: userId, + course_id: courseId, + createdAt: new Date(), + }); + + res.status(200).json({ + success: true, + message: "دوره با موفقیت لایک شد", + isLiked: true, + likesCount: course.likes, + }); + } catch (error) { + console.error("Error in likeCourseContent:", error); + res.status(500).json({ + success: false, + message: "خطا در لایک کردن محتوا", + error: error.message, + }); + } +}; + +// دیسلایک کردن محتوا (حذف لایک) +const dontLikeCourseContent = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { courseId } = req.body; + + // بررسی وجود دوره + const course = await CourseModel.findById(courseId); + if (!course) { + return res.status(404).json({ + success: false, + message: "پکیج پیدا نشد", + }); + } + + // پیدا کردن و حذف لایک + const deletedLike = await AcademyLikeModel.findOneAndDelete({ + user_id: userId, + course_id: courseId, + }); + + if (!deletedLike) { + return res.status(404).json({ + success: false, + message: "شما این دوره را لایک نکرده‌اید", + }); + } + + // کاهش تعداد لایک‌های دوره + course.likes = Math.max((course.likes || 0) - 1, 0); // جلوگیری از منفی شدن + await course.save(); + + res.status(200).json({ + success: true, + message: "لایک دوره با موفقیت حذف شد", + isLiked: false, + likesCount: course.likes, + }); + } catch (error) { + console.error("Error in dontLikeCourseContent:", error); + res.status(500).json({ + success: false, + message: "خطا در حذف لایک محتوا", + error: error.message, + }); + } +}; + +// بررسی وضعیت لایک (آیا کاربر لایک کرده است یا نه) +const isLikeCourseContent = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { courseId } = req.body; + + // پیدا کردن لایک + const academyLike = await AcademyLikeModel.findOne({ + user_id: userId, + course_id: courseId, + }); + + res.status(200).json({ + success: true, + isLiked: !!academyLike, // تبدیل به boolean + }); + } catch (error) { + console.error("Error in isLikeCourseContent:", error); + res.status(500).json({ + success: false, + message: "خطا در بررسی وضعیت لایک", + error: error.message, + }); + } +}; + +// دریافت تعداد لایک‌های یک دوره +const getCourseLikesCount = async (req, res, next) => { + try { + const { courseId } = req.params; + + const course = await CourseModel.findById(courseId); + if (!course) { + return res.status(404).json({ + success: false, + message: "دوره پیدا نشد", + }); + } + + const likesCount = await AcademyLikeModel.countDocuments({ + course_id: courseId, + }); + + res.status(200).json({ + success: true, + likesCount: likesCount, + courseLikes: course.likes || 0, + }); + } catch (error) { + console.error("Error in getCourseLikesCount:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت تعداد لایک‌ها", + error: error.message, + }); + } +}; + +// دریافت همه دوره‌هایی که کاربر لایک کرده است +const getUserLikedCourses = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 10; + const skip = (page - 1) * limit; + + const likes = await AcademyLikeModel.find({ user_id: userId }) + .populate("course_id") + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit); + + const total = await AcademyLikeModel.countDocuments({ user_id: userId }); + + res.status(200).json({ + success: true, + data: likes, + pagination: { + currentPage: page, + totalPages: Math.ceil(total / limit), + totalItems: total, + itemsPerPage: limit, + }, + }); + } catch (error) { + console.error("Error in getUserLikedCourses:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت دوره‌های لایک شده", + error: error.message, + }); + } +}; + +// ==================== ساخت کامنت جدید ==================== +const createComment = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) + return res.status(401).json({ error: true, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { course_id, comment, rate } = req.body; + + // اعتبارسنجی + if (!course_id || !comment) { + return res.status(422).json({ + error: true, + message: "شناسه دوره و متن کامنت الزامی است", + }); + } + + // بررسی وجود دوره + const course = await CourseModel.findById(course_id); + if (!course) { + return res.status(404).json({ + error: true, + message: "دوره پیدا نشد", + }); + } + + // ایجاد کامنت جدید + const newComment = await CourseComment.create({ + user_id: userId, + course_id: course_id, + comment: comment, + rate: rate || 0, + status: "accepted", // با توجه به مدل شما که default: 'accepted' است + }); + + // populate کردن اطلاعات کاربر + const populatedComment = await CourseComment.findById( + newComment._id + ).populate("user_id", "name username"); + + res.status(201).json({ + success: true, + message: "کامنت با موفقیت ثبت شد", + data: populatedComment, + }); + } catch (error) { + console.error("Error in createComment:", error); + res.status(500).json({ + success: false, + message: "خطا در ثبت کامنت", + error: error.message, + }); + } +}; + +// ==================== دریافت تعداد کل کامنت‌های یک دوره ==================== +const getTotalCommentsCount = async (req, res) => { + try { + const { courseId } = req.params; + const { status } = req.query; // اختیاری: فقط کامنت‌های با وضعیت خاص + + const query = { course_id: courseId }; + if (status) { + query.status = status; + } + + const totalComments = await CourseComment.countDocuments(query); + + // محاسبه میانگین امتیازات + const averageRate = await CourseComment.aggregate([ + { $match: { course_id: courseId, status: "accepted" } }, + { $group: { _id: null, avgRate: { $avg: "$rate" } } }, + ]); + + res.status(200).json({ + success: true, + data: { + totalComments: totalComments, + averageRate: averageRate[0]?.avgRate || 0, + courseId: courseId, + }, + }); + } catch (error) { + console.error("Error in getTotalCommentsCount:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت تعداد کامنت‌ها", + error: error.message, + }); + } +}; + +// ==================== دریافت کامنت‌ها با فیلترهای مختلف ==================== +const getCourseComments = async (req, res) => { + try { + const { courseId } = req.params; + const { + page = 1, + limit = 10, + status = "accepted", // 'accepted', 'pending', 'rejected', 'all' + minRate, + maxRate, + sortBy = "createdAt", + sortOrder = "desc", + userId, // اختیاری: کامنت‌های یک کاربر خاص + } = req.query; + + // ساخت شرط جستجو + const query = { course_id: courseId }; + + // فیلتر بر اساس وضعیت + if (status !== "all") { + query.status = status; + } + + // فیلتر بر اساس امتیاز + if (minRate || maxRate) { + query.rate = {}; + if (minRate) query.rate.$gte = parseInt(minRate); + if (maxRate) query.rate.$lte = parseInt(maxRate); + } + + // فیلتر بر اساس کاربر خاص + if (userId) { + query.user_id = userId; + } + + // تنظیمات مرتب‌سازی + const sortOptions = {}; + sortOptions[sortBy] = sortOrder === "desc" ? -1 : 1; + + // دریافت کامنت‌ها با pagination + const skip = (parseInt(page) - 1) * parseInt(limit); + + const [comments, totalComments] = await Promise.all([ + CourseComment.find(query) + .sort(sortOptions) + .skip(skip) + .limit(parseInt(limit)) + .populate("user_id", "name username profileImage"), + CourseComment.countDocuments(query), + ]); + + // محاسبه آمار کامنت‌ها + const stats = await CourseComment.aggregate([ + { $match: { course_id: courseId, status: "accepted" } }, + { + $group: { + _id: null, + totalAccepted: { $sum: 1 }, + averageRate: { $avg: "$rate" }, + rateDistribution: { + $push: "$rate", + }, + }, + }, + ]); + + const totalPages = Math.ceil(totalComments / parseInt(limit)); + + res.status(200).json({ + success: true, + message: "لیست کامنت‌ها با موفقیت دریافت شد", + data: { + comments: comments, + pagination: { + currentPage: parseInt(page), + totalPages: totalPages, + totalItems: totalComments, + itemsPerPage: parseInt(limit), + hasNextPage: parseInt(page) < totalPages, + hasPrevPage: parseInt(page) > 1, + }, + stats: { + totalComments: totalComments, + acceptedComments: stats[0]?.totalAccepted || 0, + averageRate: Math.round((stats[0]?.averageRate || 0) * 10) / 10, + rateDistribution: stats[0]?.rateDistribution || [], + }, + }, + }); + } catch (error) { + console.error("Error in getCourseComments:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت کامنت‌ها", + error: error.message, + }); + } +}; +// ==================== ویرایش وضعیت کامنت (برای همه قابل استفاده است) ==================== +const updateCommentStatus = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) + return res.status(401).json({ error: true, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { commentId } = req.params; + const { status } = req.body; // 'pending', 'accepted', 'rejected' + + // اعتبارسنجی وضعیت + if (!["pending", "accepted", "rejected"].includes(status)) { + return res.status(422).json({ + error: true, + message: + "وضعیت نامعتبر است. وضعیت باید یکی از این موارد باشد: pending, accepted, rejected", + }); + } + + // پیدا کردن کامنت + const comment = await CourseComment.findById(commentId); + if (!comment) { + return res.status(404).json({ + error: true, + message: "کامنت پیدا نشد", + }); + } + + // بررسی دسترسی: یا خود صاحب کامنت است یا هر کاربر دیگری (طبق درخواست شما که همه بتوانند) + // اگر می‌خواهید فقط ادمین بتواند وضعیت را تغییر دهد، این بخش را تغییر دهید + const user = await UserModel.findById(userId); + const isOwner = comment.user_id.toString() === userId; + const isAdmin = user?.role === "admin"; + + if (!isOwner && !isAdmin) { + return res.status(403).json({ + error: true, + message: "شما اجازه تغییر وضعیت این کامنت را ندارید", + }); + } + + // به روز رسانی وضعیت + comment.status = status; + await comment.save(); + + // اگر کامنت تایید شد و امتیاز داشت، میانگین امتیاز دوره را به روز کن + if (status === "accepted" && comment.rate > 0) { + const averageRate = await CourseComment.aggregate([ + { $match: { course_id: comment.course_id, status: "accepted" } }, + { $group: { _id: null, avgRate: { $avg: "$rate" } } }, + ]); + + await CourseModel.findByIdAndUpdate(comment.course_id, { + averageRate: averageRate[0]?.avgRate || 0, + }); + } + + res.status(200).json({ + success: true, + message: `وضعیت کامنت با موفقیت به ${ + status === "accepted" + ? "تایید شده" + : status === "rejected" + ? "رد شده" + : "در انتظار" + } تغییر یافت`, + data: comment, + }); + } catch (error) { + console.error("Error in updateCommentStatus:", error); + res.status(500).json({ + success: false, + message: "خطا در تغییر وضعیت کامنت", + error: error.message, + }); + } +}; + +// ==================== دریافت کامنت‌های یک کاربر خاص ==================== +const getUserComments = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) + return res.status(401).json({ error: true, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { page = 1, limit = 10, status = "all", courseId } = req.query; + + const query = { user_id: userId }; + + if (status !== "all") { + query.status = status; + } + + if (courseId) { + query.course_id = courseId; + } + + const skip = (parseInt(page) - 1) * parseInt(limit); + + const [comments, totalComments] = await Promise.all([ + CourseComment.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(parseInt(limit)) + .populate("course_id", "cuorse_name packageImage"), + CourseComment.countDocuments(query), + ]); + + const totalPages = Math.ceil(totalComments / parseInt(limit)); + + res.status(200).json({ + success: true, + data: { + comments: comments, + pagination: { + currentPage: parseInt(page), + totalPages: totalPages, + totalItems: totalComments, + itemsPerPage: parseInt(limit), + }, + }, + }); + } catch (error) { + console.error("Error in getUserComments:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت کامنت‌های کاربر", + error: error.message, + }); + } +}; + +// ==================== حذف کامنت (اختیاری) ==================== +const deleteComment = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) + return res.status(401).json({ error: true, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { commentId } = req.params; + + const comment = await CourseComment.findById(commentId); + if (!comment) { + return res.status(404).json({ + error: true, + message: "کامنت پیدا نشد", + }); + } + + // بررسی دسترسی: یا خود صاحب کامنت است یا ادمین + const user = await UserModel.findById(userId); + const isOwner = comment.user_id.toString() === userId; + const isAdmin = user?.role === "admin"; + + if (!isOwner && !isAdmin) { + return res.status(403).json({ + error: true, + message: "شما اجازه حذف این کامنت را ندارید", + }); + } + + await comment.deleteOne(); + + res.status(200).json({ + success: true, + message: "کامنت با موفقیت حذف شد", + }); + } catch (error) { + console.error("Error in deleteComment:", error); + res.status(500).json({ + success: false, + message: "خطا در حذف کامنت", + error: error.message, + }); + } +}; +// academyController.js + +const coursePayment = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) { + return res.status(401).json({ + error: true, + message: "لطفا وارد حساب کاربری خود شوید", + }); + } + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + const { courseId } = req.body; + + // ========== 1. بررسی وجود دوره ========== + const course = await CourseModel.findById(courseId); + if (!course) { + return res.status(404).json({ + error: true, + message: "دوره مورد نظر یافت نشد", + }); + } + + // ========== 2. بررسی خرید قبلی ========== + const existingPurchase = await IsPaymentCourse.findOne({ + user_id: userId, + course_id: course._id, + }); + + if (existingPurchase) { + return res.status(400).json({ + error: true, + message: "شما قبلاً این دوره را خریداری کرده‌اید", + }); + } + + // ========== 3. دریافت نرخ مالیات ========== + let taxRate = 9; // پیش‌فرض 9 درصد + const tax = await Tax.findOne({ type: "course" }); + if (tax && tax.tax) { + taxRate = Number(tax.tax); + } + + // ========== 4. محاسبه قیمت ========== + const offerNum = Number(course.offer) || 0; + const priceNum = Number(course.price); + + // قیمت پس از تخفیف + const discountedPrice = (priceNum / 100) * (100 - offerNum); + + // محاسبه مالیات + const taxAmount = discountedPrice * (taxRate / 100); + + // قیمت نهایی با مالیات (تومان) + const finalPrice = discountedPrice; + const finalTaxPrice = (discountedPrice / 100) * (100 - taxRate); + + // ========== 5. اعتبارسنجی قیمت ========== + if (!finalPrice || isNaN(finalPrice) || finalPrice <= 0) { + return res.status(422).json({ + error: true, + message: "مبلغ نامعتبر است", + }); + } + + // تبدیل به ریال (ضرب در 10 چون هر تومان = 10 ریال) + const amountInRials = Math.round(finalPrice * 10); + + // مبلغ باید حداقل 1000 تومان باشد (10000 ریال) + if (amountInRials < 10000) { + return res.status(422).json({ + error: true, + message: "مبلغ باید حداقل 1000 تومان باشد", + }); + } + + // ========== 6. ساخت کال‌بک URL ========== + const callbackUrl = `https://api.modstagram.com/api/v1/academy/academy/course/payment/verify?courseId=${courseId}&userId=${userId}`; + + // ========== 7. درخواست به زرین‌پال ========== + const zarinpalRes = await axios.post( + "https://api.zarinpal.com/pg/v4/payment/request.json", + { + merchant_id: process.env.ZARINPAL_MERCHANT_ID, + amount: amountInRials, + description: `خرید دوره ${course.cuorse_name}`, + callback_url: callbackUrl, + metadata: { + user_id: userId, + course_id: courseId, + price: finalPrice, + tax_rate: taxRate, + }, + }, + { + headers: { "Content-Type": "application/json" }, + timeout: 90000, + } + ); + + const result = zarinpalRes.data; + + // ========== 8. بررسی پاسخ زرین‌پال ========== + if (result.data && result.data.code === 100) { + // ذخیره اطلاعات پرداخت در حالت pending + await AcademyPaymentModel.create({ + price: finalPrice, + discountAmount: priceNum - discountedPrice, + taxAmount: finalTaxPrice, + taxRate: taxRate, + course_name: course.cuorse_name, + course_id: course._id, + academy_id: course.academyId, + user_id: userId, + payment_authority: result.data.authority, + status: "pending", + }); + + return res.status(200).json({ + success: true, + authority: result.data.authority, + paymentUrl: `https://www.zarinpal.com/pg/StartPay/${result.data.authority}`, + }); + } + + // خطای زرین‌پال + console.error("ZarinPal error:", result); + return res.status(422).json({ + error: true, + message: result.errors?.message || "خطا در ارتباط با درگاه پرداخت", + details: result.errors, + }); + } catch (error) { + console.error( + "Error in coursePayment:", + error.response?.data || error.message + ); + res.status(500).json({ + error: true, + message: "خطا در پردازش پرداخت", + details: error.response?.data || error.message, + }); + } +}; + +const CoursePaymentCallback = async (req, res) => { + try { + const { Authority, Status, courseId, userId } = req.query; + + // ========== 1. بررسی وضعیت پرداخت ========== + if (Status !== "OK") { + return res.redirect( + `${process.env.APP_SITE}/offer/payment/failed?message=payment_canceled` + ); + } + + // ========== 2. پیدا کردن دوره ========== + const course = await CourseModel.findById(courseId); + if (!course) { + return res.redirect( + `${process.env.APP_SITE}/offer/payment/failed?message=course_not_found` + ); + } + + // ========== 3. پیدا کردن رکورد پرداخت ========== + const paymentRecord = await AcademyPaymentModel.findOne({ + payment_authority: Authority, + course_id: courseId, + user_id: userId, + }); + + if (!paymentRecord) { + return res.redirect( + `${process.env.APP_SITE}/offer/payment/failed?message=payment_not_found` + ); + } + + // ========== 4. محاسبه مبلغ ========== + const amountInRials = Math.round(paymentRecord.price * 10); + + // ========== 5. تایید پرداخت با زرین‌پال ========== + const verify = await axios.post( + "https://api.zarinpal.com/pg/v4/payment/verify.json", + { + merchant_id: process.env.ZARINPAL_MERCHANT_ID, + authority: Authority, + amount: amountInRials, + }, + { + headers: { "Content-Type": "application/json" }, + timeout: 10000, + } + ); + + const data = verify.data.data; + + // ========== 6. بررسی نتیجه تایید ========== + if (data.code === 100) { + // به‌روزرسانی رکورد پرداخت + await AcademyPaymentModel.findByIdAndUpdate(paymentRecord._id, { + status: "success", + payment_ref_id: data.ref_id, + }); + + // ثبت خرید کاربر + await IsPaymentCourse.create({ + user_id: userId, + course_id: course._id, + price_paid: paymentRecord.price, + purchased_at: new Date(), + }); + + // هدایت به صفحه موفقیت + return res.redirect( + `${process.env.APP_SITE}/academy/${course._id}/success?payment=success` + ); + } + + // پرداخت ناموفق + await AcademyPaymentModel.findByIdAndUpdate(paymentRecord._id, { + status: "failed", + }); + + return res.redirect( + `${process.env.APP_SITE}/offer/payment/failed?code=${data.code}` + ); + } catch (err) { + console.error("Error in CoursePaymentCallback:", err); + return res.redirect( + `${process.env.APP_SITE}/offer/payment/failed?message=verification_error` + ); + } +}; +const getUserPurchasedCourses = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) + return res.status(401).json({ error: true, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const user_id = decodedToken.id; + + const { page = 1, limit = 10 } = req.query; + + // پیدا کردن تمام رکوردهای پرداخت برای این کاربر + const payments = await IsPaymentCourse.find({ user_id: user_id }) + .sort({ createdAt: -1 }) // جدیدترین اول + .skip((page - 1) * limit) + .limit(parseInt(limit)); + + // گرفتن اطلاعات کامل دوره‌ها + const courseIds = payments.map((payment) => payment.course_id); + + const courses = await CourseModel.find({ + _id: { $in: courseIds }, + status: "accept", // فقط دوره‌های تایید شده + }); + + // محاسبه تعداد کل + const total = await IsPaymentCourse.countDocuments({ user_id: user_id }); + + res.status(200).json({ + success: true, + data: { + courses: courses, + pagination: { + total, + page: parseInt(page), + pages: Math.ceil(total / limit), + limit: parseInt(limit), + }, + }, + }); + } catch (error) { + console.error("Error in getUserPurchasedCourses:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت دوره‌های خریداری شده", + error: error.message, + }); + } +}; + +// API با populate (روش بهتر) +const getUserPurchasedCoursesWithPopulate = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) + return res.status(401).json({ error: true, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const user_id = decodedToken.id; + + const { page = 1, limit = 10 } = req.query; + + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { createdAt: -1 }, + populate: { + path: "course_id", + model: "Course", + match: { status: "accept" }, // فقط دوره‌های تایید شده + }, + }; + + const result = await IsPaymentCourse.paginate( + { user_id: user_id }, + options + ); + + // فیلتر کردن دوره‌هایی که populate شده‌اند و وجود دارند + const validCourses = result.docs + .filter((doc) => doc.course_id !== null) + .map((doc) => doc.course_id); + + res.status(200).json({ + success: true, + data: { + courses: validCourses, + pagination: { + total: result.totalDocs, + page: result.page, + totalPages: result.totalPages, + limit: result.limit, + hasNextPage: result.hasNextPage, + hasPrevPage: result.hasPrevPage, + }, + }, + }); + } catch (error) { + console.error("Error:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت دوره‌های خریداری شده", + }); + } +}; + +const getAllAcademyPayments = async (req, res) => { + try { + // 1. بررسی توکن + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) { + return res.status(401).json({ + success: false, + message: "دسترسی غیرمجاز", + }); + } + + // 2. verify توکن + let decodedToken; + try { + decodedToken = jwt.verify(token, process.env.APP_SECRET); + } catch (jwtError) { + return res.status(401).json({ + success: false, + message: "توکن نامعتبر است", + }); + } + + const userId = decodedToken.id; + + // 3. پیدا کردن آکادمی + const academy = await AcademyModel.findOne({ userId: userId }); + + if (!academy) { + return res.status(404).json({ + success: false, + message: "آکادمی برای این کاربر یافت نشد", + }); + } + + const academy_id = academy._id; + const { page = 1, limit = 10, status } = req.query; + + // 4. ساخت فیلتر + let filter = { academy_id: academy_id }; + + if ( + status && + ["pending", "success", "failed", "settled"].includes(status) + ) { + filter.status = status; + } + + // 5. تنظیمات صفحه‌بندی + const pageNum = parseInt(page); + const limitNum = parseInt(limit); + const skip = (pageNum - 1) * limitNum; + + const options = { + page: pageNum, + limit: limitNum, + sort: { createdAt: -1 }, + populate: [ + { + path: "course_id", + model: "Course", + select: "cuorse_name price course_image category teacher_name", + }, + { + path: "user_id", + model: "User", + select: "user_name profile_image email phone", + }, + ], + }; + + // 6. دریافت پرداخت‌ها + const result = await AcademyPaymentModel.paginate(filter, options); + + // 7. محاسبه آمار دقیق‌تر + let totalAmount = 0; + let pendingCount = 0; + let acceptedCount = 0; + + if (result.docs && Array.isArray(result.docs)) { + totalAmount = result.docs.reduce((sum, p) => { + const price = parseInt(p.taxAmount) || 0; + return sum + price; + }, 0); + + pendingCount = result.docs.filter((p) => p.status === "pending").length; + acceptedCount = result.docs.filter((p) => p.status === "accept").length; + } + + // 8. پاسخ نهایی + res.status(200).json({ + success: true, + data: { + academy: { + _id: academy._id, + academy_name: academy.academy_name, + academy_image: academy.academy_image, + bio: academy.bio, + }, + payments: result.docs || [], + pagination: { + total: result.totalDocs || 0, + page: result.page || pageNum, + totalPages: result.totalPages || 1, + limit: result.limit || limitNum, + hasNextPage: result.hasNextPage || false, + hasPrevPage: result.hasPrevPage || false, + }, + stats: { + totalAmount: totalAmount, + pendingCount: pendingCount, + acceptedCount: acceptedCount, + }, + }, + }); + } catch (error) { + console.error("Error in getAllAcademyPayments:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت لیست پرداخت‌ها", + error: process.env.NODE_ENV === "development" ? error.message : undefined, + }); + } +}; +const checkCoursePurchase = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) + return res.status(401).json({ error: true, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + const { courseId } = req.params; + + // بررسی وجود کاربر و دوره + if (!userId || !courseId) { + return res.status(400).json({ + success: false, + message: "userId و courseId الزامی هستند", + }); + } + + // جستجو در دیتابیس + const purchase = await IsPaymentCourse.findOne({ + user_id: userId, + course_id: courseId, + }); + + // نتیجه + if (purchase) { + return res.status(200).json({ + success: true, + isPurchased: true, + message: "این دوره قبلاً خریداری شده است", + purchaseData: purchase, + }); + } else { + return res.status(200).json({ + success: true, + isPurchased: false, + message: "این دوره خریداری نشده است", + }); + } + } catch (error) { + console.error("Error in checkCoursePurchase:", error); + res.status(500).json({ + success: false, + message: "خطا در بررسی خرید دوره", + error: error.message, + }); + } +}; + +const getAcademyCourse = async (req, res, next) => { + try { + const { Id } = req.params; + + // گرفتن پارامترهای صفحه‌بندی + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 10; + const skip = (page - 1) * limit; + + const academy = await AcademyModel.findById(Id); + if (!academy) { + return res.status(404).json({ + success: false, + message: "آکادمی پیدا نشد", + }); + } + + // ✅ شرط جستجو - فقط دوره‌های تایید شده + const query = { + academyId: academy._id, + status: "accept", + }; + + // دریافت تعداد کل دوره‌های تایید شده + const totalCourses = await CourseModel.countDocuments(query); + + // دریافت دوره‌های تایید شده با صفحه‌بندی + const courses = await CourseModel.find(query) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limit); + + // ✅ اگر دوره‌ای وجود نداشت، خطا نده، بلکه آرایه خالی برگردون + if (!courses || courses.length === 0) { + return res.status(200).json({ + success: true, + message: "هیچ دوره تایید شده‌ای یافت نشد", + data: { + courses: [], + pagination: { + currentPage: page, + totalPages: 0, + totalItems: 0, + itemsPerPage: limit, + hasNextPage: false, + hasPrevPage: false, + nextPage: null, + prevPage: null, + }, + }, + }); + } + + // محاسبات صفحه‌بندی + const totalPages = Math.ceil(totalCourses / limit); + const hasNextPage = page < totalPages; + const hasPrevPage = page > 1; + + res.status(200).json({ + success: true, + message: "لیست پکیج‌ها با موفقیت دریافت شد", + data: { + courses: courses, + pagination: { + currentPage: page, + totalPages: totalPages, + totalItems: totalCourses, + itemsPerPage: limit, + hasNextPage: hasNextPage, + hasPrevPage: hasPrevPage, + nextPage: hasNextPage ? page + 1 : null, + prevPage: hasPrevPage ? page - 1 : null, + }, + }, + }); + } catch (error) { + console.error("Error:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت پکیج‌ها", + error: error.message, + }); + } +}; + +// ==================== مدیریت پرداخت‌ها ==================== +const getAllPayments = async (req, res) => { + try { + const { page = 1, limit = 20, status, startDate, endDate } = req.query; + const skip = (parseInt(page) - 1) * parseInt(limit); + + let query = {}; + if (status) query.status = status; + if (startDate && endDate) { + query.createdAt = { + $gte: new Date(startDate), + $lte: new Date(endDate), + }; + } + + const payments = await AcademyPaymentModel.find(query) + .populate("user_id", "user_name profile_image email") + .populate("course_id", "cuorse_name price course_image") + .populate("academy_id", "academy_name academy_image sheba") + .sort({ createdAt: -1 }) + .skip(skip) + .limit(parseInt(limit)); + + const total = await AcademyPaymentModel.countDocuments(query); + + // آمار کلی پرداخت‌ها + const stats = await AcademyPaymentModel.aggregate([ + { $match: query }, + { + $group: { + _id: null, + totalAmount: { $sum: { $toDouble: "$price" } }, + totalCount: { $sum: 1 }, + pendingCount: { + $sum: { $cond: [{ $eq: ["$status", "pending"] }, 1, 0] }, + }, + settledCount: { + $sum: { $cond: [{ $eq: ["$status", "settled"] }, 1, 0] }, + }, + successCount: { + $sum: { $cond: [{ $eq: ["$status", "success"] }, 1, 0] }, + }, + }, + }, + ]); + + res.status(200).json({ + success: true, + data: { + payments, + stats: stats[0] || { + totalAmount: 0, + totalCount: 0, + pendingCount: 0, + settledCount: 0, + successCount: 0, + }, + pagination: { + currentPage: parseInt(page), + totalPages: Math.ceil(total / parseInt(limit)), + totalItems: total, + itemsPerPage: parseInt(limit), + }, + }, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در دریافت پرداخت‌ها" }); + } +}; + +const updatePaymentStatus = async (req, res) => { + try { + const { paymentId, status } = req.body; + + const payment = await AcademyPaymentModel.findByIdAndUpdate( + paymentId, + { status, updatedAt: new Date() }, + { new: true } + ); + + if (!payment) { + return res + .status(404) + .json({ success: false, message: "پرداخت یافت نشد" }); + } + + res.status(200).json({ + success: true, + message: "وضعیت پرداخت با موفقیت تغییر کرد", + data: payment, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در تغییر وضعیت پرداخت" }); + } +}; + +// ==================== مدیریت دوره‌ها ==================== +const getAllCourses = async (req, res) => { + try { + const { page = 1, limit = 20, status, type, category, search } = req.query; + const skip = (parseInt(page) - 1) * parseInt(limit); + + let query = {}; + if (status) query.status = status; + if (type) query.type = type; + if (category) query.category = category; + if (search) { + query.$or = [ + { cuorse_name: { $regex: search, $options: "i" } }, + { caption: { $regex: search, $options: "i" } }, + { teacher_name: { $regex: search, $options: "i" } }, + ]; + } + + const courses = await CourseModel.find(query) + .populate("academyId", "academy_name academy_image") + .populate("user_id", "user_name profile_image") + .sort({ createdAt: -1 }) + .skip(skip) + .limit(parseInt(limit)); + + const total = await CourseModel.countDocuments(query); + + // آمار دوره‌ها + const stats = await CourseModel.aggregate([ + { $match: query }, + { + $group: { + _id: null, + totalCourses: { $sum: 1 }, + totalPrice: { $sum: { $toDouble: "$price" } }, + normalCount: { + $sum: { $cond: [{ $eq: ["$type", "normal"] }, 1, 0] }, + }, + proCount: { $sum: { $cond: [{ $eq: ["$type", "pro"] }, 1, 0] } }, + legendCount: { + $sum: { $cond: [{ $eq: ["$type", "legend"] }, 1, 0] }, + }, + pendingCount: { + $sum: { $cond: [{ $eq: ["$status", "pending"] }, 1, 0] }, + }, + acceptCount: { + $sum: { $cond: [{ $eq: ["$status", "accept"] }, 1, 0] }, + }, + }, + }, + ]); + + res.status(200).json({ + success: true, + data: { + courses, + stats: stats[0] || {}, + pagination: { + currentPage: parseInt(page), + totalPages: Math.ceil(total / parseInt(limit)), + totalItems: total, + itemsPerPage: parseInt(limit), + }, + }, + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در دریافت دوره‌ها" }); + } +}; + +const updateCourseStatus = async (req, res) => { + try { + const { courseId, status, type } = req.body; + + console.log(courseId, status, type); + + const course = await CourseModel.findById(courseId); + + if (!course) { + return res.status(404).json({ success: false, message: "دوره یافت نشد" }); + } + + if (status) course.status = status; + if (type) course.type = type; + await course.save(); + + res.status(200).json({ + success: true, + message: "دوره با موفقیت به‌روزرسانی شد", + data: course, + courseId: courseId, + status: status, + type: type, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در به‌روزرسانی دوره" }); + } +}; + +const admindeleteCourse = async (req, res) => { + try { + const { courseId } = req.params; + + const course = await CourseModel.findByIdAndDelete(courseId); + + if (!course) { + return res.status(404).json({ success: false, message: "دوره یافت نشد" }); + } + + // حذف تمام پرداخت‌های مرتبط با این دوره + await AcademyPaymentModel.deleteMany({ course_id: courseId }); + + res.status(200).json({ + success: true, + message: "دوره با موفقیت حذف شد", + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در حذف دوره" }); + } +}; + +// ==================== مدیریت دوره‌های خریداری شده ==================== +const getAllPurchasedCourses = async (req, res) => { + try { + const { page = 1, limit = 20, userId, courseId, status } = req.query; + const skip = (parseInt(page) - 1) * parseInt(limit); + + let query = {}; + if (userId) query.user_id = userId; + if (courseId) query.course_id = courseId; + if (status) query.status = status; + + const purchases = await IsPaymentCourse.find(query) + .populate("user_id", "user_name profile_image email phone") + .populate("course_id", "cuorse_name price course_image teacher_name") + .sort({ createdAt: -1 }) + .skip(skip) + .limit(parseInt(limit)); + + const total = await IsPaymentCourse.countDocuments(query); + + // آمار خریدها + const stats = await IsPaymentCourse.aggregate([ + { $match: query }, + { + $group: { + _id: null, + totalPurchases: { $sum: 1 }, + uniqueUsers: { $addToSet: "$user_id" }, + }, + }, + ]); + + res.status(200).json({ + success: true, + data: { + purchases, + stats: { + totalPurchases: stats[0]?.totalPurchases || 0, + uniqueUsers: stats[0]?.uniqueUsers?.length || 0, + }, + pagination: { + currentPage: parseInt(page), + totalPages: Math.ceil(total / parseInt(limit)), + totalItems: total, + itemsPerPage: parseInt(limit), + }, + }, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در دریافت دوره‌های خریداری شده" }); + } +}; + +// ==================== مدیریت آکادمی‌ها ==================== +const getAllAcademies = async (req, res) => { + try { + const { page = 1, limit = 20, search } = req.query; + const skip = (parseInt(page) - 1) * parseInt(limit); + + let query = {}; + if (search) { + query.academy_name = { $regex: search, $options: "i" }; + } + + const academies = await AcademyModel.find(query) + .populate("userId", "user_name profile_image email") + .sort({ createdAt: -1 }) + .skip(skip) + .limit(parseInt(limit)); + + const total = await AcademyModel.countDocuments(query); + + // آمار آکادمی‌ها + const stats = await AcademyModel.aggregate([ + { + $group: { + _id: null, + totalAcademies: { $sum: 1 }, + totalRate: { $sum: "$rate" }, + avgRate: { $avg: "$rate" }, + }, + }, + ]); + + res.status(200).json({ + success: true, + data: { + academies, + stats: stats[0] || {}, + pagination: { + currentPage: parseInt(page), + totalPages: Math.ceil(total / parseInt(limit)), + totalItems: total, + itemsPerPage: parseInt(limit), + }, + }, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در دریافت آکادمی‌ها" }); + } +}; + +const updateAcademyStatus = async (req, res) => { + try { + const { academyId, status, rate, sheba } = req.body; + + const updateData = {}; + if (status) updateData.status = status; + if (rate) updateData.rate = rate; + if (sheba) updateData.sheba = sheba; + + const academy = await AcademyModel.findByIdAndUpdate( + academyId, + updateData, + { new: true } + ); + + if (!academy) { + return res + .status(404) + .json({ success: false, message: "آکادمی یافت نشد" }); + } + + res.status(200).json({ + success: true, + message: "آکادمی با موفقیت به‌روزرسانی شد", + data: academy, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در به‌روزرسانی آکادمی" }); + } +}; + +// ==================== مدیریت تنظیمات (تکس و قیمت پرو) ==================== +const getSettings = async (req, res) => { + try { + let settings = await SettingModel.findOne(); + + if (!settings) { + settings = await SettingModel.create({ + taxRate: 9, + proPrice: 99000, + legendPrice: 199000, + minWithdrawAmount: 50000, + maxWithdrawAmount: 10000000, + }); + } + + res.status(200).json({ + success: true, + data: settings, + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در دریافت تنظیمات" }); + } +}; + +const updateSettings = async (req, res) => { + try { + const { + taxRate, + proPrice, + legendPrice, + minWithdrawAmount, + maxWithdrawAmount, + } = req.body; + + const settings = await SettingModel.findOneAndUpdate( + {}, + { + taxRate, + proPrice, + legendPrice, + minWithdrawAmount, + maxWithdrawAmount, + updatedAt: new Date(), + }, + { new: true, upsert: true } + ); + + res.status(200).json({ + success: true, + message: "تنظیمات با موفقیت به‌روزرسانی شد", + data: settings, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در به‌روزرسانی تنظیمات" }); + } +}; + +const getCoursePrices = async (req, res) => { + try { + const proPrice = await CoursePaymentModel.findOne({ cuorse_type: "pro" }); + + const legendPrice = await CoursePaymentModel.findOne({ + cuorse_type: "legend", + }); + + const normalPrice = await CoursePaymentModel.findOne({ + cuorse_type: "normal", + }); + + res.status(200).json({ + success: true, + data: { + pro: proPrice + ? { price: proPrice.price, _id: proPrice._id } + : { price: "60000" }, + legend: legendPrice + ? { price: legendPrice.price, _id: legendPrice._id } + : { price: "199000" }, + normal: normalPrice + ? { price: normalPrice.price, _id: normalPrice._id } + : { price: "0" }, + }, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در دریافت قیمت دوره‌ها" }); + } +}; + +const updateCoursePrice = async (req, res) => { + try { + const { courseType, price } = req.body; + + if (!courseType || !price) { + return res + .status(400) + .json({ success: false, message: "نوع دوره و قیمت الزامی است" }); + } + + let coursePayment = await CoursePaymentModel.findOne({ + cuorse_type: courseType, + }); + + if (coursePayment) { + coursePayment.price = price.toString(); + await coursePayment.save(); + } else { + coursePayment = new CoursePaymentModel({ + price: price.toString(), + cuorse_type: courseType, + }); + await coursePayment.save(); + } + + res.status(200).json({ + success: true, + message: `قیمت دوره ${ + courseType === "pro" + ? "پرو" + : courseType === "legend" + ? "لجند" + : "معمولی" + } با موفقیت به‌روزرسانی شد`, + data: coursePayment, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در به‌روزرسانی قیمت دوره" }); + } +}; + +const getTax = async (req, res) => { + try { + let tax = await Tax.findOne({ type: "course" }); + + if (!tax) { + tax = new Tax({ tax: 8, type: "course" }); + await tax.save(); + } + + res.status(200).json({ + success: true, + data: { + tax: tax.tax, + _id: tax._id, + type: tax.type, + }, + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در دریافت مالیات" }); + } +}; + +const updateTax = async (req, res) => { + try { + const { tax } = req.body; + + if (tax === undefined || tax === null) { + return res + .status(400) + .json({ success: false, message: "مقدار مالیات الزامی است" }); + } + + let taxRecord = await Tax.findOne({ type: "course" }); + + if (taxRecord) { + taxRecord.tax = tax; + await taxRecord.save(); + } else { + taxRecord = new Tax({ tax: tax, type: "course" }); + await taxRecord.save(); + } + + res.status(200).json({ + success: true, + message: "مالیات با موفقیت به‌روزرسانی شد", + data: taxRecord, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در به‌روزرسانی مالیات" }); + } +}; + +const getAllSettings = async (req, res) => { + try { + const proPrice = await CoursePaymentModel.findOne({ cuorse_type: "pro" }); + const legendPrice = await CoursePaymentModel.findOne({ + cuorse_type: "legend", + }); + + let tax = await Tax.findOne({ type: "course" }); + if (!tax) { + tax = new Tax({ tax: 8, type: "course" }); + await tax.save(); + } + + res.status(200).json({ + success: true, + data: { + tax: tax.tax, + prices: { + pro: proPrice ? proPrice.price : "60000", + legend: legendPrice ? legendPrice.price : "199000", + }, + }, + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در دریافت تنظیمات" }); + } +}; + +const updateAllSettings = async (req, res) => { + try { + const { tax, proPrice, legendPrice } = req.body; + + if (tax !== undefined) { + let taxRecord = await Tax.findOne({ type: "course" }); + if (taxRecord) { + taxRecord.tax = tax; + await taxRecord.save(); + } else { + taxRecord = new Tax({ tax: tax, type: "course" }); + await taxRecord.save(); + } + } + + if (proPrice !== undefined) { + let proRecord = await CoursePaymentModel.findOne({ cuorse_type: "pro" }); + if (proRecord) { + proRecord.price = proPrice.toString(); + await proRecord.save(); + } else { + proRecord = new CoursePaymentModel({ + price: proPrice.toString(), + cuorse_type: "pro", + }); + await proRecord.save(); + } + } + + if (legendPrice !== undefined) { + let legendRecord = await CoursePaymentModel.findOne({ + cuorse_type: "legend", + }); + if (legendRecord) { + legendRecord.price = legendPrice.toString(); + await legendRecord.save(); + } else { + legendRecord = new CoursePaymentModel({ + price: legendPrice.toString(), + cuorse_type: "legend", + }); + await legendRecord.save(); + } + } + + res.status(200).json({ + success: true, + message: "تنظیمات با موفقیت به‌روزرسانی شد", + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در به‌روزرسانی تنظیمات" }); + } +}; + +const getPaymentStats = async (req, res) => { + try { + const stats = await AcademyPaymentModel.aggregate([ + { + $group: { + _id: null, + totalAmount: { $sum: { $toDouble: "$price" } }, + totalCount: { $sum: 1 }, + pendingCount: { + $sum: { $cond: [{ $eq: ["$status", "pending"] }, 1, 0] }, + }, + settledCount: { + $sum: { $cond: [{ $eq: ["$status", "settled"] }, 1, 0] }, + }, + successCount: { + $sum: { $cond: [{ $eq: ["$status", "success"] }, 1, 0] }, + }, + }, + }, + ]); + + const result = stats[0] || { + totalAmount: 0, + totalCount: 0, + pendingCount: 0, + settledCount: 0, + successCount: 0, + }; + + result.averageAmount = + result.totalCount > 0 + ? Math.round(result.totalAmount / result.totalCount) + : 0; + + res.status(200).json({ + success: true, + data: result, + }); + } catch (error) { + console.error("Error in getPaymentStats:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت آمار پرداخت‌ها", + error: process.env.NODE_ENV === "development" ? error.message : undefined, + }); + } +}; + +const getCourseById = async (req, res) => { + try { + const { id } = req.params; + const course = await CourseModel.findById(id) + .populate("academyId", "academy_name academy_image") + .populate("user_id", "user_name profile_image"); + + if (!course) { + return res.status(404).json({ success: false, message: "دوره یافت نشد" }); + } + + res.status(200).json({ + success: true, + data: course, + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در دریافت دوره" }); + } +}; + +const createCourse = async (req, res) => { + try { + const courseData = req.body; + const newCourse = new CourseModel(courseData); + await newCourse.save(); + + res.status(201).json({ + success: true, + message: "دوره با موفقیت ایجاد شد", + data: newCourse, + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در ایجاد دوره" }); + } +}; + +const getCourseStats = async (req, res) => { + try { + const stats = await CourseModel.aggregate([ + { + $group: { + _id: null, + totalCourses: { $sum: 1 }, + normalCount: { + $sum: { $cond: [{ $eq: ["$type", "normal"] }, 1, 0] }, + }, + proCount: { $sum: { $cond: [{ $eq: ["$type", "pro"] }, 1, 0] } }, + legendCount: { + $sum: { $cond: [{ $eq: ["$type", "legend"] }, 1, 0] }, + }, + pendingCount: { + $sum: { $cond: [{ $eq: ["$status", "pending"] }, 1, 0] }, + }, + acceptCount: { + $sum: { $cond: [{ $eq: ["$status", "accept"] }, 1, 0] }, + }, + rejectCount: { + $sum: { $cond: [{ $eq: ["$status", "reject"] }, 1, 0] }, + }, + }, + }, + ]); + + res.status(200).json({ + success: true, + data: stats[0] || {}, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در دریافت آمار دوره‌ها" }); + } +}; + +const getPurchasedStats = async (req, res) => { + try { + const stats = await IsPaymentCourse.aggregate([ + { + $group: { + _id: null, + totalPurchases: { $sum: 1 }, + uniqueUsers: { $addToSet: "$user_id" }, + }, + }, + ]); + + res.status(200).json({ + success: true, + data: { + totalPurchases: stats[0]?.totalPurchases || 0, + uniqueUsers: stats[0]?.uniqueUsers?.length || 0, + }, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در دریافت آمار خریدها" }); + } +}; + +const getAcademyById = async (req, res) => { + try { + const { id } = req.params; + const academy = await AcademyModel.findById(id).populate( + "userId", + "user_name profile_image email" + ); + + if (!academy) { + return res + .status(404) + .json({ success: false, message: "آکادمی یافت نشد" }); + } + + res.status(200).json({ + success: true, + data: academy, + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در دریافت آکادمی" }); + } +}; + +const createAcademy = async (req, res) => { + try { + const academyData = req.body; + const newAcademy = new AcademyModel(academyData); + await newAcademy.save(); + + res.status(201).json({ + success: true, + message: "آکادمی با موفقیت ایجاد شد", + data: newAcademy, + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در ایجاد آکادمی" }); + } +}; + +const updateAcademy = async (req, res) => { + try { + const { id } = req.params; + const updateData = req.body; + + const academy = await AcademyModel.findByIdAndUpdate(id, updateData, { + new: true, + }); + + if (!academy) { + return res + .status(404) + .json({ success: false, message: "آکادمی یافت نشد" }); + } + + res.status(200).json({ + success: true, + message: "آکادمی با موفقیت به‌روزرسانی شد", + data: academy, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در به‌روزرسانی آکادمی" }); + } +}; + +const deleteAcademy = async (req, res) => { + try { + const { id } = req.params; + const academy = await AcademyModel.findByIdAndDelete(id); + + if (!academy) { + return res + .status(404) + .json({ success: false, message: "آکادمی یافت نشد" }); + } + + await CourseModel.deleteMany({ academyId: id }); + + res.status(200).json({ + success: true, + message: "آکادمی با موفقیت حذف شد", + }); + } catch (error) { + console.error(error); + res.status(500).json({ success: false, message: "خطا در حذف آکادمی" }); + } +}; + +const getAcademyStats = async (req, res) => { + try { + const stats = await AcademyModel.aggregate([ + { + $group: { + _id: null, + totalAcademies: { $sum: 1 }, + totalRate: { $sum: "$rate" }, + avgRate: { $avg: "$rate" }, + }, + }, + ]); + + res.status(200).json({ + success: true, + data: stats[0] || { + totalAcademies: 0, + totalRate: 0, + avgRate: 0, + }, + }); + } catch (error) { + console.error(error); + res + .status(500) + .json({ success: false, message: "خطا در دریافت آمار آکادمی‌ها" }); + } +}; +const deleteCourseVideo = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { courseContentId, courseId } = req.body; + const courseContent = await AcademyContentModel.findById(courseContentId); + + if (!courseContent) { + return res.status(404).json({ + error: true, + message: "ویدعو یافت نشد", + }); + } + + courseContent.status = "reject"; + + await courseContent.save(); + + const course = await CourseModel.findById(courseId); + if (course) { + course.number_of_course_content = `${ + Number(course.number_of_course_content) - 1 + }`; + await course.save(); + } + + res.status(200).json({ + success: true, + message: "ویدیو با موفقیت پاک شد", + }); + } catch (error) { + console.error("Error:", error); + res.status(500).json({ + success: false, + message: "خطا در حذف ویدیو", + error: error.message, + }); + } +}; + +const getChunkDir = (uploadKey) => { + return path.join(process.cwd(), "storage", "temp-chunks", uploadKey); +}; + +setInterval(async () => { + const tempDir = path.join(process.cwd(), "storage", "temp-chunks"); + if (await fs.pathExists(tempDir)) { + const dirs = await fs.readdir(tempDir); + const now = Date.now(); + for (const dir of dirs) { + const dirPath = path.join(tempDir, dir); + const stat = await fs.stat(dirPath); + if (now - stat.mtimeMs > 30 * 60 * 1000) { + // 30 دقیقه + await fs.remove(dirPath); + console.log(`Cleaned up old upload: ${dir}`); + } + } + } +}, 60 * 60 * 1000); + +const creatCourseVideoChunk = async (req, res, next) => { + console.log("=== Chunk Video Upload ==="); + console.log("Chunk index:", req.body.chunkIndex); + + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { + courseId, + is_free, + file_name, + chunk, + chunkIndex, + totalChunks, + originalFileName, + fileSize, + mime_type, + } = req.body; + + if (!chunk) { + return res.status(422).json({ + error: true, + message: "تکه فایل ارسال نشده است", + }); + } + + if (!courseId) { + return res.status(422).json({ + error: true, + message: "شناسه دوره الزامی است", + }); + } + + const base64Data = chunk.split(",")[1] || chunk; + const buffer = Buffer.from(base64Data, "base64"); + + const uploadKey = `${courseId}_${originalFileName}`; + const chunkDir = getChunkDir(uploadKey); + + await fs.ensureDir(chunkDir); + + const metaPath = path.join(chunkDir, "meta.json"); + if (chunkIndex === "0" || chunkIndex === 0) { + const metaData = { + totalChunks: parseInt(totalChunks), + file_name: file_name, + originalFileName: originalFileName, + fileSize: fileSize, + mime_type: mime_type, + courseId: courseId, + is_free: is_free, + createdAt: Date.now(), + }; + await fs.writeJson(metaPath, metaData); + } + + if (!(await fs.pathExists(metaPath))) { + return res.status(404).json({ + error: true, + message: "جلسه آپلود یافت نشد", + }); + } + + const chunkPath = path.join(chunkDir, `chunk_${chunkIndex}`); + await fs.writeFile(chunkPath, buffer); + + console.log( + `✅ Chunk ${parseInt(chunkIndex) + 1}/${totalChunks} saved to disk (${ + buffer.length + } bytes)` + ); + + res.status(200).json({ + success: true, + message: `تکه ${ + parseInt(chunkIndex) + 1 + } از ${totalChunks} با موفقیت دریافت شد`, + chunkIndex: chunkIndex, + totalChunks: totalChunks, + }); + } catch (error) { + console.error("Error in creatCourseVideoChunk:", error); + res.status(500).json({ + success: false, + message: "خطا در دریافت تکه ویدیو", + error: error.message, + }); + } +}; + +const mergeVideoChunks = async (req, res, next) => { + console.log("=== Merge Video Chunks ==="); + + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { courseId, originalFileName, totalChunks } = req.body; + + const uploadKey = `${courseId}_${originalFileName}`; + const chunkDir = getChunkDir(uploadKey); + const metaPath = path.join(chunkDir, "meta.json"); + + if (!(await fs.pathExists(chunkDir)) || !(await fs.pathExists(metaPath))) { + return res.status(404).json({ + error: true, + message: "داده‌های آپلود یافت نشد", + }); + } + + const metaData = await fs.readJson(metaPath); + + const existingChunks = await fs.readdir(chunkDir); + const chunkFiles = existingChunks.filter((f) => f.startsWith("chunk_")); + + if (chunkFiles.length !== parseInt(totalChunks)) { + return res.status(422).json({ + error: true, + message: `تعداد تکه‌ها کامل نیست. دریافت شده: ${chunkFiles.length}، مورد نیاز: ${totalChunks}`, + }); + } + + const chunks = []; + for (let i = 0; i < parseInt(totalChunks); i++) { + const chunkPath = path.join(chunkDir, `chunk_${i}`); + if (!(await fs.pathExists(chunkPath))) { + return res.status(422).json({ + error: true, + message: `تکه ${i + 1} پیدا نشد`, + }); + } + const chunkBuffer = await fs.readFile(chunkPath); + chunks.push(chunkBuffer); + } + + const completeBuffer = Buffer.concat(chunks); + console.log("Original file size:", completeBuffer.length, "bytes"); + + const finalVideoDir = path.join( + process.cwd(), + "storage", + "courses", + "videos" + ); + await fs.ensureDir(finalVideoDir); + + let extension = ".mp4"; + if (metaData.mime_type === "video/mp4") extension = ".mp4"; + else if (metaData.mime_type === "video/quicktime") extension = ".mov"; + else if (metaData.mime_type === "video/x-msvideo") extension = ".avi"; + else if (metaData.mime_type === "video/webm") extension = ".webm"; + + const safeFileName = `course-${courseId}-${Date.now()}${extension}`; + const filePath = path.join(finalVideoDir, safeFileName); + + await fs.writeFile(filePath, completeBuffer); + console.log("Original file saved:", filePath); + + const newAcademyContent = new AcademyContentModel({ + course_video: `/storage/courses/videos/${safeFileName}`, + type: "video", + is_free: metaData.is_free === "true" || metaData.is_free === true, + courseId: courseId, + file_name: metaData.file_name || metaData.originalFileName, + }); + + await newAcademyContent.save(); + + const course = await CourseModel.findById(courseId); + if (course) { + course.number_of_course_content = `${ + Number(course.number_of_course_content) + 1 + }`; + await course.save(); + } + + await fs.remove(chunkDir); + + res.status(200).json({ + success: true, + message: "ویدیو با موفقیت ثبت شد (در حال پردازش...)", + data: newAcademyContent, + }); + + if (completeBuffer.length > 20 * 1024 * 1024) { + // اجرای غیرهمزمان بدون await + compressVideoInBackground(filePath, safeFileName, newAcademyContent._id); + } + } catch (error) { + console.error("Error in mergeVideoChunks:", error); + res.status(500).json({ + success: false, + message: "خطا در ترکیب ویدیو", + error: error.message, + }); + } +}; + +const compressVideoInBackground = async (filePath, fileName, contentId) => { + console.log(`Starting background compression for ${fileName}`); + + const dir = path.dirname(filePath); + const tempPath = path.join(dir, `temp-${fileName}`); + const { exec } = require("child_process"); + const util = require("util"); + const execPromise = util.promisify(exec); + + try { + await execPromise( + `ffmpeg -i "${filePath}" -c:v libx264 -crf 28 -preset veryfast -c:a aac -b:a 128k -movflags +faststart "${tempPath}" -y` + ); + + const compressedStat = await fs.stat(tempPath); + const originalStat = await fs.stat(filePath); + + if (compressedStat.size < originalStat.size) { + await fs.rename(tempPath, filePath); + console.log( + `✅ Background compression done: ${( + originalStat.size / + 1024 / + 1024 + ).toFixed(2)}MB → ${(compressedStat.size / 1024 / 1024).toFixed(2)}MB` + ); + } else { + await fs.remove(tempPath); + console.log("Compression didn't reduce size, keeping original"); + } + } catch (error) { + console.error("Background compression failed:", error.message); + if (await fs.pathExists(tempPath)) { + await fs.remove(tempPath); + } + } +}; + +const getUploadStatus = async (req, res) => { + try { + const { courseId, originalFileName } = req.query; + const uploadKey = `${courseId}_${originalFileName}`; + const chunkDir = getChunkDir(uploadKey); + + if (!(await fs.pathExists(chunkDir))) { + return res.status(200).json({ + success: true, + uploadedChunks: [], + totalChunks: 0, + }); + } + + const files = await fs.readdir(chunkDir); + const chunkFiles = files + .filter((f) => f.startsWith("chunk_")) + .map((f) => parseInt(f.replace("chunk_", ""))) + .sort((a, b) => a - b); + + const metaPath = path.join(chunkDir, "meta.json"); + let totalChunks = 0; + if (await fs.pathExists(metaPath)) { + const metaData = await fs.readJson(metaPath); + totalChunks = metaData.totalChunks; + } + + res.status(200).json({ + success: true, + uploadedChunks: chunkFiles, + totalChunks: totalChunks, + }); + } catch (error) { + res.status(500).json({ success: false, error: error.message }); + } +}; + + + +// ایجاد slug یکتا +const generateUniqueSlug = async (title, excludeId = null) => { + let slug = title + .replace(/[^\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C\uFB8E\u0698a-zA-Z0-9\s]/g, '') + .trim() + .replace(/\s+/g, '-') + .toLowerCase(); + + let uniqueSlug = slug; + let counter = 1; + + while (true) { + const query = { slug: uniqueSlug }; + if (excludeId) query._id = { $ne: excludeId }; + const exists = await AcademyCategoryModel.findOne(query); + if (!exists) break; + uniqueSlug = `${slug}-${counter}`; + counter++; + } + + return uniqueSlug; +}; + +// ==================== GET - دریافت لیست دسته‌بندی‌ها ==================== +const getAll = async (req, res) => { + try { + const { + page = 1, + limit = 20, + sortBy = 'order', + sortOrder = 'asc', + status, + parent, + search, + is_featured, + withChildren = 'false' + } = req.query; + + let query = {}; + + if (status) query.status = status; + if (parent !== undefined) query.parent = parent === 'null' ? null : parent; + if (is_featured === 'true') query.is_featured = true; + + if (search) { + query.$or = [ + { title: { $regex: search, $options: 'i' } }, + { description: { $regex: search, $options: 'i' } } + ]; + } + + const sortOptions = {}; + sortOptions[sortBy] = sortOrder === 'asc' ? 1 : -1; + + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: sortOptions, + populate: [ + { path: 'parent', select: 'title slug' }, + { path: 'created_by', select: 'user_name name' }, + { path: 'updated_by', select: 'user_name name' } + ] + }; + + let categories = await AcademyCategoryModel.paginate(query, options); + + // دریافت درخت دسته‌بندی (اختیاری) + if (withChildren === 'true' && !parent) { + const tree = await AcademyCategoryModel.getTree(); + categories = { ...categories, tree }; + } + + res.status(200).json({ + success: true, + message: 'لیست دسته‌بندی‌ها با موفقیت دریافت شد', + data: categories + }); + } catch (error) { + console.error('Error in getAll:', error); + res.status(500).json({ + success: false, + message: 'خطا در دریافت دسته‌بندی‌ها', + error: error.message + }); + } +}; + +// ==================== GET - دریافت یک دسته‌بندی ==================== +const getOne = async (req, res) => { + try { + const { id } = req.params; + const { includeCourses = 'false' } = req.query; + + let query = AcademyCategoryModel.findById(id); + + query = query.populate('parent', 'title slug icon color'); + query = query.populate('children', 'title slug icon color course_count order'); + query = query.populate('created_by', 'user_name name'); + + if (includeCourses === 'true') { + query = query.populate({ + path: 'courses', + select: 'cuorse_name course_image price offer', + options: { limit: 10 } + }); + } + + const category = await query; + + if (!category) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی یافت نشد' + }); + } + + res.status(200).json({ + success: true, + message: 'دسته‌بندی با موفقیت دریافت شد', + data: category + }); + } catch (error) { + console.error('Error in getOne:', error); + res.status(500).json({ + success: false, + message: 'خطا در دریافت دسته‌بندی', + error: error.message + }); + } +}; + +// ==================== GET - دریافت درخت دسته‌بندی ==================== +const getTree = async (req, res) => { + try { + const tree = await AcademyCategoryModel.getTree(); + + res.status(200).json({ + success: true, + message: 'درخت دسته‌بندی با موفقیت دریافت شد', + data: tree + }); + } catch (error) { + console.error('Error in getTree:', error); + res.status(500).json({ + success: false, + message: 'خطا در دریافت درخت دسته‌بندی', + error: error.message + }); + } +}; + +// ==================== GET - دریافت توسط اسلاگ ==================== +const getBySlug = async (req, res) => { + try { + const { slug } = req.params; + const { page = 1, limit = 20 } = req.query; + + const category = await AcademyCategoryModel.getBySlug(slug); + + if (!category) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی یافت نشد' + }); + } + + // دریافت دوره‌های این دسته + const courses = await CourseModel.find({ + category_id: category._id, + status: 'accept' + }) + .sort({ createdAt: -1 }) + .skip((page - 1) * limit) + .limit(parseInt(limit)); + + const totalCourses = await CourseModel.countDocuments({ + category_id: category._id, + status: 'accept' + }); + + res.status(200).json({ + success: true, + message: 'دسته‌بندی با موفقیت دریافت شد', + data: { + category, + courses: { + data: courses, + pagination: { + page: parseInt(page), + limit: parseInt(limit), + total: totalCourses, + pages: Math.ceil(totalCourses / limit) + } + } + } + }); + } catch (error) { + console.error('Error in getBySlug:', error); + res.status(500).json({ + success: false, + message: 'خطا در دریافت دسته‌بندی', + error: error.message + }); + } +}; + +// ==================== POST - ایجاد دسته‌بندی جدید ==================== +const create = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).json({ success: false, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { + title, + description, + icon, + color, + parent, + order, + image, + is_featured, + seo_title, + seo_description + } = req.body; + + // اعتبارسنجی + if (!title || title.trim().length < 2) { + return res.status(422).json({ + success: false, + message: 'عنوان دسته‌بندی باید حداقل ۲ کاراکتر باشد' + }); + } + + // بررسی تکراری نبودن عنوان + const existingTitle = await AcademyCategoryModel.findOne({ title }); + if (existingTitle) { + return res.status(409).json({ + success: false, + message: 'این عنوان قبلاً ثبت شده است' + }); + } + + // تولید slug یکتا + const slug = await generateUniqueSlug(title); + + // بررسی وجود parent + let level = 0; + if (parent) { + const parentCategory = await AcademyCategoryModel.findById(parent); + if (!parentCategory) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی والد یافت نشد' + }); + } + level = parentCategory.level + 1; + + if (level > 3) { + return res.status(422).json({ + success: false, + message: 'عمق دسته‌بندی نمی‌تواند بیشتر از ۳ سطح باشد' + }); + } + } + + const newCategory = new AcademyCategoryModel({ + title, + slug, + description: description || null, + icon: icon || null, + color: color || '#3B82F6', + parent: parent || null, + level, + order: order || 0, + image: image || null, + is_featured: is_featured || false, + seo_title: seo_title || title, + seo_description: seo_description || description, + created_by: userId, + status: 'active' + }); + + await newCategory.save(); + + res.status(201).json({ + success: true, + message: 'دسته‌بندی با موفقیت ایجاد شد', + data: newCategory + }); + } catch (error) { + console.error('Error in create:', error); + res.status(500).json({ + success: false, + message: 'خطا در ایجاد دسته‌بندی', + error: error.message + }); + } +}; + +// ==================== PUT/PATCH - ویرایش دسته‌بندی ==================== +const update = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).json({ success: false, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { id } = req.params; + const updateData = req.body; + + const category = await AcademyCategoryModel.findById(id); + if (!category) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی یافت نشد' + }); + } + + // بررسی تکراری نبودن عنوان + if (updateData.title && updateData.title !== category.title) { + const existingTitle = await AcademyCategoryModel.findOne({ + title: updateData.title, + _id: { $ne: id } + }); + if (existingTitle) { + return res.status(409).json({ + success: false, + message: 'این عنوان قبلاً ثبت شده است' + }); + } + + // آپدیت slug + updateData.slug = await generateUniqueSlug(updateData.title, id); + } + + // بررسی parent + if (updateData.parent) { + if (updateData.parent === id) { + return res.status(422).json({ + success: false, + message: 'یک دسته‌بندی نمی‌تواند والد خودش باشد' + }); + } + + const parentCategory = await AcademyCategoryModel.findById(updateData.parent); + if (!parentCategory) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی والد یافت نشد' + }); + } + + updateData.level = parentCategory.level + 1; + + if (updateData.level > 3) { + return res.status(422).json({ + success: false, + message: 'عمق دسته‌بندی نمی‌تواند بیشتر از ۳ سطح باشد' + }); + } + } + + updateData.updated_by = userId; + updateData.updatedAt = new Date(); + + const updatedCategory = await AcademyCategoryModel.findByIdAndUpdate( + id, + updateData, + { new: true, runValidators: true } + ); + + res.status(200).json({ + success: true, + message: 'دسته‌بندی با موفقیت به‌روزرسانی شد', + data: updatedCategory + }); + } catch (error) { + console.error('Error in update:', error); + res.status(500).json({ + success: false, + message: 'خطا در به‌روزرسانی دسته‌بندی', + error: error.message + }); + } +}; + +// ==================== DELETE - حذف (سافت دیلیت) ==================== +const remove = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).json({ success: false, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { id } = req.params; + const { permanent = 'false' } = req.query; + + const category = await AcademyCategoryModel.findById(id); + if (!category) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی یافت نشد' + }); + } + + // بررسی وجود زیردسته‌ها + const hasChildren = await AcademyCategoryModel.exists({ parent: id }); + if (hasChildren) { + return res.status(422).json({ + success: false, + message: 'این دسته‌بندی دارای زیردسته است. ابتدا زیردسته‌ها را حذف کنید' + }); + } + + // بررسی وجود دوره در این دسته + const hasCourses = await CourseModel.exists({ category_id: id }); + if (hasCourses && permanent === 'true') { + return res.status(422).json({ + success: false, + message: 'این دسته‌بندی دارای دوره است. ابتدا دوره‌ها را جابه‌جا کنید' + }); + } + + if (permanent === 'true') { + // حذف فیزیکی + await category.deleteOne(); + res.status(200).json({ + success: true, + message: 'دسته‌بندی با موفقیت حذف شد' + }); + } else { + // سافت دیلیت + category.status = 'deleted'; + category.updated_by = userId; + await category.save(); + + res.status(200).json({ + success: true, + message: 'دسته‌بندی با موفقیت غیرفعال شد' + }); + } + } catch (error) { + console.error('Error in remove:', error); + res.status(500).json({ + success: false, + message: 'خطا در حذف دسته‌بندی', + error: error.message + }); + } +}; + +// ==================== POST - تغییر وضعیت (اکتیو/غیراکتیو) ==================== +const toggleStatus = async (req, res) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).json({ success: false, message: "Access Denied" }); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userId = decodedToken.id; + + const { id } = req.params; + const { status } = req.body; // 'active' or 'inactive' + + if (!['active', 'inactive'].includes(status)) { + return res.status(422).json({ + success: false, + message: 'وضعیت نامعتبر است' + }); + } + + const category = await AcademyCategoryModel.findByIdAndUpdate( + id, + { + status, + updated_by: userId, + updatedAt: new Date() + }, + { new: true } + ); + + if (!category) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی یافت نشد' + }); + } + + res.status(200).json({ + success: true, + message: `وضعیت دسته‌بندی با موفقیت به ${status === 'active' ? 'فعال' : 'غیرفعال'} تغییر کرد`, + data: category + }); + } catch (error) { + console.error('Error in toggleStatus:', error); + res.status(500).json({ + success: false, + message: 'خطا در تغییر وضعیت دسته‌بندی', + error: error.message + }); + } +}; + +// ==================== POST - افزایش تعداد دوره‌ها ==================== +const incrementCourseCount = async (req, res) => { + try { + const { id } = req.params; + const { increment = 1 } = req.body; + + const category = await AcademyCategoryModel.incrementCourseCount(id, increment); + + if (!category) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی یافت نشد' + }); + } + + res.status(200).json({ + success: true, + message: 'تعداد دوره‌ها به‌روزرسانی شد', + data: { course_count: category.course_count } + }); + } catch (error) { + console.error('Error in incrementCourseCount:', error); + res.status(500).json({ + success: false, + message: 'خطا در به‌روزرسانی تعداد دوره‌ها', + error: error.message + }); + } +}; + +// ==================== GET - دریافت دسته‌بندی‌های ویژه (featured) ==================== +const getFeatured = async (req, res) => { + try { + const { limit = 10 } = req.query; + + const categories = await AcademyCategoryModel.find({ + is_featured: true, + status: 'active' + }) + .sort({ order: 1 }) + .limit(parseInt(limit)) + .populate('parent', 'title slug'); + + res.status(200).json({ + success: true, + message: 'دسته‌بندی‌های ویژه با موفقیت دریافت شد', + data: categories + }); + } catch (error) { + console.error('Error in getFeatured:', error); + res.status(500).json({ + success: false, + message: 'خطا در دریافت دسته‌بندی‌های ویژه', + error: error.message + }); + } +}; + + +module.exports = { + // ========================================== + // 🏢 ماژول آکادمی (Academy) + // ========================================== + + // پیدا کردن آکادمی کاربر جاری + findAcademy, + + // پیدا کردن آکادمی با شناسه + findAcademyById, + + // تکمیل و ویرایش پروفایل آکادمی + academyProfile, + + // تغییر وضعیت آکادمی (فعال/غیرفعال - فقط ادمین) + updateAcademyStatus, + + // دریافت اطلاعات یک آکادمی با شناسه + getAcademyById, + + // ایجاد آکادمی جدید (دستی - معمولاً خودکار ایجاد می‌شود) + createAcademy, + + // ویرایش اطلاعات آکادمی + updateAcademy, + + // حذف آکادمی (به همراه تمام دوره‌های آن) + deleteAcademy, + + // دریافت آمار کلی آکادمی‌ها (تعداد، میانگین امتیاز و...) + getAcademyStats, + + // ========================================== + // 📚 ماژول دوره‌ها (Course) + // ========================================== + + // ایجاد دوره جدید + creatCourse, + + // ویرایش اطلاعات دوره + updateCourse, + + // حذف دوره (تغییر وضعیت به reject) + deleteCourse, + + // دریافت لیست دوره‌های آکادمی جاری + getCourse, + + // دریافت لیست همه دوره‌ها با فیلتر و جستجو + getCourses, + + // دریافت دوره‌های یک آکادمی خاص + getAcademyCourse, + + // آپلود ویدیو با روش Multipart + creatCourseVideo, + + // آپلود ویدیو با روش Base64 (برای فایل‌های کوچک) + creatCourseVideoBase64, + + // ========================================== + // 💳 ماژول پرداخت (Payment) + // ========================================== + + // پرداخت برای اشتراک پرو + proPayment, + + // کال‌بک درگاه پرداخت زرین‌پال (اشتراک پرو) + handleCoursePaymentCallback, + + // پرداخت برای خرید دوره + coursePayment, + + // کال‌بک درگاه پرداخت زرین‌پال (خرید دوره) + CoursePaymentCallback, + + // ========================================== + // 🎬 ماژول محتوای دوره (Course Content) + // ========================================== + + // دریافت محتوای دوره (لیست ویدیوها و فایل‌ها) + getCourseContent, + + // حذف ویدیو از دوره + deleteCourseVideo, + + // لایک کردن محتوا + likeCourseContent, + + // حذف لایک (دیسلایک) + dontLikeCourseContent, + + // دریافت تعداد لایک‌های یک دوره + getCourseLikesCount, + + // دریافت لیست دوره‌های لایک شده توسط کاربر + getUserLikedCourses, + + // بررسی وضعیت لایک کاربر (آیا لایک کرده یا نه) + isLikeCourseContent, + + // ========================================== + // 💬 ماژول کامنت‌ها (Comments) + // ========================================== + + // ایجاد کامنت جدید + createComment, + + // دریافت تعداد کل کامنت‌های یک دوره + getTotalCommentsCount, + + // دریافت لیست کامنت‌های یک دوره (با فیلتر و صفحه‌بندی) + getCourseComments, + + // تغییر وضعیت کامنت (تایید/رد/در انتظار) + updateCommentStatus, + + // دریافت کامنت‌های یک کاربر خاص + getUserComments, + + // حذف کامنت + deleteComment, + + // ========================================== + // 🛒 ماژول دوره‌های خریداری شده (Purchased) + // ========================================== + + // دریافت دوره‌های خریداری شده توسط کاربر جاری + getUserPurchasedCourses, + + // دریافت دوره‌های خریداری شده (با populate - روش بهینه) + getUserPurchasedCoursesWithPopulate, + + // دریافت همه پرداخت‌های آکادمی + getAllAcademyPayments, + + // بررسی خرید یک دوره توسط کاربر (برای صفحه دوره) + checkCoursePurchase, + + // ========================================== + // 👑 ماژول مدیریتی (Admin Panel) + // ========================================== + + // ------ مدیریت پرداخت‌ها ------ + + // دریافت همه پرداخت‌های سیستم (ادمین) + getAllPayments, + + // تغییر وضعیت پرداخت (pending/success/settled/failed) + updatePaymentStatus, + + // ------ مدیریت دوره‌ها ------ + + // دریافت همه دوره‌های سیستم (ادمین) + getAllCourses, + + // تغییر وضعیت دوره (تایید/رد/در انتظار) + updateCourseStatus, + + // حذف کامل دوره از سیستم (ادمین) + admindeleteCourse, + + // ------ مدیریت دوره‌های خریداری شده ------ + + // دریافت همه خریدهای سیستم (ادمین) + getAllPurchasedCourses, + + // ------ مدیریت آکادمی‌ها ------ + + // دریافت همه آکادمی‌های سیستم (ادمین) + getAllAcademies, + + // ------ مدیریت تنظیمات ------ + + // دریافت تنظیمات (تکس، قیمت‌ها و...) + getSettings, + + // به‌روزرسانی تنظیمات + updateSettings, + + // دریافت قیمت دوره‌ها (پرو، لجند، معمولی) + getCoursePrices, + + // به‌روزرسانی قیمت یک نوع دوره + updateCoursePrice, + + // دریافت درصد مالیات + getTax, + + // به‌روزرسانی درصد مالیات + updateTax, + + // دریافت همه تنظیمات یکجا + getAllSettings, + + // به‌روزرسانی همه تنظیمات یکجا + updateAllSettings, + + // ========================================== + // 📊 ماژول آمار (Stats) + // ========================================== + + // دریافت آمار پرداخت‌ها + getPaymentStats, + + // دریافت اطلاعات یک دوره با شناسه + getCourseById, + + // ایجاد دوره جدید (ادمین) + createCourse, + + // ویرایش دوره (ادمین) + updateCourse, + + // دریافت آمار کلی دوره‌ها + getCourseStats, + + // دریافت آمار دوره‌های خریداری شده + getPurchasedStats, + + // ========================================== + // 📹 ماژول آپلود تکه‌تکه (Chunk Upload) + // ========================================== + + // دریافت تکه ویدیو (هر بار یک تکه) + creatCourseVideoChunk, + + // ادغام تکه‌ها بعد از اتمام آپلود + mergeVideoChunks, + + // بررسی وضعیت آپلود (برای ادامه از جای قطع شده) + getUploadStatus, + + // ========================================== + // 🏷️ ماژول دسته‌بندی آکادمی (Category) + // ========================================== + + // دریافت لیست دسته‌بندی‌ها (با فیلتر و صفحه‌بندی) + getAll, + + // دریافت یک دسته‌بندی با شناسه + getOne, + + // دریافت درخت دسته‌بندی (ساختار سلسله‌مراتبی والد-فرزند) + getTree, + + // دریافت دسته‌بندی با اسلاگ (برای سئو و لینک‌های زیبا) + getBySlug, + + // ایجاد دسته‌بندی جدید + create, + + // ویرایش دسته‌بندی + update, + + // حذف دسته‌بندی (سافت دیلیت - فقط غیرفعال می‌شود) + remove, + + // تغییر وضعیت دسته‌بندی (فعال/غیرفعال) + toggleStatus, + + // افزایش تعداد دوره‌های دسته‌بندی + incrementCourseCount, + + // دریافت دسته‌بندی‌های ویژه (برای نمایش در صفحه اصلی) + getFeatured +}; \ No newline at end of file diff --git a/public/modstagram-back/controllers/application/academy/helpers/chatHelpers.js b/public/modstagram-back/controllers/application/academy/helpers/chatHelpers.js new file mode 100644 index 0000000..a22af9f --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/helpers/chatHelpers.js @@ -0,0 +1,72 @@ +const moment = require('moment-jalaali') +const MessageModel = require('../models/MessageModel') +const UserModel = require('../models/UserModel') + +function formatTimeOnly(date) { + return moment(date).locale('fa').format('HH:mm:ss') +} + +async function enrichMessage(message) { + const doc = message._doc ? { ...message._doc } : { ...message } + let replyTo = null + + if (doc.replyToId) { + const parent = await MessageModel.findById(doc.replyToId).lean() + if (parent) { + const parentUser = + String(parent.senderId) === String(doc.senderId) + ? await UserModel.findById(doc.senderId).select('first_name last_name user_name').lean() + : await UserModel.findById(parent.senderId).select('first_name last_name user_name').lean() + replyTo = { + _id: parent._id, + content: (parent.content || 'پیام').slice(0, 200), + senderName: parentUser + ? `${parentUser.first_name || ''} ${parentUser.last_name || ''}`.trim() || parentUser.user_name + : 'کاربر' + } + } + } + + return { + ...doc, + createdAt: formatTimeOnly(doc.createdAt), + replyTo, + forwardedFrom: doc.forwardedFrom || undefined + } +} + +function emitChatEvents(io, message, senderId, receiverId) { + const payload = message + const roomA = `chat:${senderId}:${receiverId}` + const roomB = `chat:${receiverId}:${senderId}` + io.to(roomA).to(roomB).emit('newMessage', payload) + io.to(`user:${senderId}`).to(`user:${receiverId}`).emit('chatListUpdate', { + senderId, + receiverId, + message: payload + }) +} + +function parseForwardedContent(content) { + if (!content) return { body: '', forwardedFrom: null } + try { + const line = content.split('\n')[0] + const j = JSON.parse(line) + if (j.forwardedFrom) { + return { + forwardedFrom: j.forwardedFrom, + body: content.replace(/^\{.*\}\n?/, '').trim() + } + } + } catch (_) { + /* not json */ + } + return { body: content, forwardedFrom: null } +} + +module.exports = { + formatTimeOnly, + enrichMessage, + emitChatEvents, + parseForwardedContent +} diff --git a/public/modstagram-back/controllers/application/academy/index.js b/public/modstagram-back/controllers/application/academy/index.js new file mode 100644 index 0000000..67ae759 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/index.js @@ -0,0 +1,357 @@ +const express = require('express'); +const app = express(); +const path = require('path'); +const http = require('http').createServer(app); +const cors = require('cors'); +const moment = require('moment-jalaali'); +const MessageModel = require('./models/MessageModel'); +const fs = require('fs-extra'); +const cron = require('node-cron'); +const UserModel = require('./models/UserModel'); +const blockCheck = require('./middlewares/blockCheck'); +const rateLimit = require('express-rate-limit'); +const { default: axios } = require('axios'); + +const allowedOrigins = [ + 'http://localhost:3000', + 'http://localhost:3001', // اضافه شد — مهم برای توسعه فرانت + 'http://localhost:3002', + 'http://localhost:3003', + 'http://localhost', + 'https://modstagram.com', + 'https://www.modstagram.com', + 'https://api.modstagram.com', + 'https://panel.modstagram.com', + 'https://www.panel.modstagram.com', + 'https://panel.modstagram.ir', + 'https://www.panel.modstagram.ir', + 'ionic://localhost', + 'capacitor://localhost', + // IPهای محلی (برای تست در شبکه داخلی) + /^http:\/\/192\.168\.\d{1,3}\.\d{1,3}:\d+$/, + /^http:\/\/10\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/, +]; + +app.use(cors({ + origin: (origin, callback) => { + // در محیط توسعه، همه originها مجاز باشن + if (process.env.NODE_ENV !== 'production') { + return callback(null, true); + } + + // اگر origin وجود نداشته باشه (مثل درخواست از موبایل یا Postman) اجازه بده + if (!origin) { + return callback(null, true); + } + + // چک لیست یا RegExp + const isAllowed = allowedOrigins.some(item => { + if (typeof item === 'string') return item === origin; + if (item instanceof RegExp) return item.test(origin); + return false; + }); + + if (isAllowed) { + callback(null, true); + } else { + callback(new Error('Not allowed by CORS')); + } + }, + methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-no-toast'], + credentials: true, + optionsSuccessStatus: 200 // برای مرورگرهای قدیمی +})); + +// Socket.IO CORS +const io = require('socket.io')(http, { + cors: { + origin: (origin, callback) => { + if (process.env.NODE_ENV !== 'production') { + return callback(null, true); + } + + if (!origin) { + return callback(null, true); + } + + const isAllowed = allowedOrigins.some(item => { + if (typeof item === 'string') return item === origin; + if (item instanceof RegExp) return item.test(origin); + return false; + }); + + if (isAllowed) { + callback(null, true); + } else { + callback(new Error('Not allowed by CORS')); + } + }, + methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'], + credentials: true + } +}); + +// افزایش limit برای Base64 (1000mb کافیه) +app.use(express.json({ limit: '1000mb' })); +app.use(express.urlencoded({ limit: '1000mb', extended: true })); + +app.use('/storage', express.static(path.join(__dirname, 'storage'))); +app.use('/storage/profiles', express.static(path.join(__dirname, '../storage/profiles'))); +app.use('/storage/carts', express.static(path.join(__dirname, '../storage/carts'))); +app.use('/storage/posts', express.static(path.join(__dirname, '../storage/posts'))); +app.use('/storage/messages', express.static(path.join(__dirname, '../storage/messages'))); +app.use('/storage/tickets', express.static(path.join(__dirname, '../storage/tickets'))); +app.use('/storage/advertising', express.static(path.join(__dirname, '../storage/advertising'))); +app.use('/storage/services', express.static(path.join(__dirname, '../storage/services'))); + +require('./boot'); + +// غیرفعال کردن پارس‌کننده‌های بدنه برای روت‌های آپلود فایل +app.use((req, res, next) => { + if (req.path === '/api/v1/posts/create' && req.method === 'POST') { + console.log('DEBUG: Skipping body parsers for /api/v1/posts/create'); + return next(); + } + express.json()(req, res, next); +}); +app.use((req, res, next) => { + if (req.path === '/api/v1/posts/create' && req.method === 'POST') { + return next(); + } + express.urlencoded({ extended: true })(req, res, next); +}); + +require('./middlewares')(app); + +const limiter = rateLimit({ + windowMs: 3 * 60 * 1000, + max: 3000, + standardHeaders: true, + legacyHeaders: false, + message: 'تعداد درخواست‌های شما بیشتر از حد مجاز است، لطفاً بعداً دوباره تلاش کنید.', + handler: (req, res) => { + const retryAfter = Math.ceil((req.rateLimit.resetTime - Date.now()) / 1000); + res.set('Retry-After', retryAfter); + res.status(429).json({ + error: `شما بیش از حد مجاز درخواست ارسال کرده‌اید. لطفاً بعد از ${retryAfter} ثانیه دوباره تلاش کنید.` + }); + } +}); +app.use(limiter); +app.set('trust proxy', 'loopback'); + +require('./routes')(app); + +const { enrichMessage, emitChatEvents, parseForwardedContent } = require('./helpers/chatHelpers') + +app.get('/api/v1/chat', async (req, res) => { + try { + const { senderId, receiverId, limit, page } = req.query + const pageNumber = parseInt(page) || 1 + const limitPerPage = parseInt(limit) || 40 + + const filter = { + $or: [ + { senderId, receiverId }, + { senderId: receiverId, receiverId: senderId } + ] + } + + const totalMessagesCount = await MessageModel.countDocuments(filter) + const totalPages = Math.ceil(totalMessagesCount / limitPerPage) || 1 + const skip = (pageNumber - 1) * limitPerPage + + const messages = await MessageModel.find(filter) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limitPerPage) + + await MessageModel.updateMany( + { _id: { $in: messages.map((m) => m._id) }, receiverId: senderId }, + { $set: { readStatus: 1 } } + ) + + const enriched = await Promise.all(messages.map((m) => enrichMessage(m))) + res.json({ messages: enriched.reverse(), totalPages }) + } catch (error) { + console.error('Error fetching messages:', error) + res.status(500).json({ error: 'Server error' }) + } +}) + +app.post('/api/v1/chat', [blockCheck], async (req, res) => { + try { + const { senderId, receiverId, content, replyToId, forwardedFrom: fwdBody } = req.body + const { body, forwardedFrom: fwdParsed } = parseForwardedContent(content) + + const payload = { + senderId, + receiverId, + content: body || content, + replyToId: replyToId || undefined, + forwardedFrom: fwdBody || fwdParsed || undefined + } + + const newMessage = new MessageModel(payload) + await newMessage.save() + const formatted = await enrichMessage(newMessage) + + res.status(201).json({ data: formatted }) + emitChatEvents(io, formatted, senderId, receiverId) + } catch (error) { + console.error('Error sending message:', error) + res.status(500).json({ error: 'Server error' }) + } +}) +app.get('/api/v1/chat/read', async (req, res) => { + try { + const { senderId, receiverId } = req.query // شناسه فرستنده و گیرنده از درخواست دریافت شود + // پیدا کردن تمام پیام‌هایی که کاربر دوم مشاهده کرده است و کاربر اول آنها را ارسال کرده است + const messages = await MessageModel.find( + { senderId: receiverId, receiverId: senderId } // برای مواقعی که شناسه‌ها معکوس باشند + ) + // به روزرسانی وضعیت خوانده شده یا نشده بودن پیام‌ها به "خوانده شده" + await MessageModel.updateMany({ _id: { $in: messages.map(message => message._id) } }, { $set: { readStatus: 1 } }) + res.status(200).json({ message: 'Message read status updated successfully' }) + } catch (error) { + console.error('Error updating message read status:', error) + res.status(500).json({ error: 'Server error' }) + } +}) + +app.post("/api/v1/notification/send-sms", async (req, res) => { + const { receiverId, message } = req.body; + const user = await UserModel.findById(receiverId); + if (!user || !user.mobile) return res.status(404).json({ error: "User not found" }); + console.log("3"); + + const mobile = user.mobile + const user_name = user.user_name + const data = JSON.stringify({ + mobile, + templateId: '876533', + parameters: [ + { name: 'USER', value: user_name } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + + axios(config) + .then(function (response) { + console.log(response); + + }) + .catch(function (error) { + console.log(error) + }) + + res.status(200).json({ success: true }); +}); + +app.post('/api/v1/chat/file', [blockCheck], async (req, res) => { + try { + const { senderId, receiverId, content, replyToId, fileType } = req.body + const { file } = req.files + let fileUrl = null + if (file) { + const uploadDir = path.join(__dirname, '../storage/messages') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + const uniqueFileName = `${Date.now()}-${file.name}` + const filePath = path.join(uploadDir, uniqueFileName) + await fs.move(file.path, filePath) + fileUrl = `/messages/${uniqueFileName}` + } + + const newMessage = new MessageModel({ + senderId, + receiverId, + content: content || '', + file: fileUrl, + fileType: fileType || undefined, + replyToId: replyToId || undefined + }) + await newMessage.save() + const formatted = await enrichMessage(newMessage) + + res.status(201).json({ data: formatted }) + emitChatEvents(io, formatted, senderId, receiverId) + } catch (error) { + console.error('Error sending message:', error) + res.status(500).json({ error: 'Server error' }) + } +}) +// Errors +require('./middlewares/exception')(app) +require('./middlewares/404')(app) +io.on('connection', (socket) => { + socket.on('joinUser', ({ userId }) => { + if (userId) socket.join(`user:${userId}`) + }) + + socket.on('joinChat', ({ userId, receiverId }) => { + if (userId && receiverId) { + socket.join(`chat:${userId}:${receiverId}`) + socket.join(`chat:${receiverId}:${userId}`) + } + }) + + socket.on('typing', ({ senderId, receiverId }) => { + io.to(`chat:${receiverId}:${senderId}`).emit('userTyping', { userId: senderId }) + }) + + socket.on('stopTyping', ({ senderId, receiverId }) => { + io.to(`chat:${receiverId}:${senderId}`).emit('userStoppedTyping', { userId: senderId }) + }) + + socket.on('messageSeen', async ({ messageId, senderId, receiverId }) => { + try { + if (messageId) { + await MessageModel.findByIdAndUpdate(messageId, { readStatus: 1 }) + io.to(`chat:${receiverId}:${senderId}`).emit('messageStatusUpdate', { + messageId, + status: 'seen' + }) + } + } catch (e) { + console.error('messageSeen error', e) + } + }) +}) + +// Free Project +require('./services/AdvertisingCron') +require('./services/ProjectCron') +cron.schedule('0 0 1 * *', async () => { + try { + await UserModel.updateMany({}, { + daily_free_request: 1, + last_free_request_date: new Date(), + monthly_free_offer: 1, + last_free_offer_date: new Date() + }) + console.log('Monthly free requests reset for all users.') + } catch (error) { + console.error('Error resetting daily free requests:', error) + } +}, { + scheduled: true, + timezone: 'Asia/Tehran' +}) +module.exports = (port) => { + http.listen(port, () => { + console.log(`HTTP server is running on port ${port}`) + }) +} diff --git a/public/modstagram-back/controllers/application/academy/models/AcademyCategoryModel.js b/public/modstagram-back/controllers/application/academy/models/AcademyCategoryModel.js new file mode 100644 index 0000000..be50bf0 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AcademyCategoryModel.js @@ -0,0 +1,190 @@ +const mongoose = require('mongoose'); +const mongoosePaginate = require('mongoose-paginate-v2'); +const timestamp = require('mongoose-timestamp'); + +const AcademyCategorySchema = new mongoose.Schema({ + title: { + type: String, + required: [true, 'عنوان دسته‌بندی الزامی است'], + trim: true, + minLength: [2, 'عنوان باید حداقل ۲ کاراکتر باشد'], + maxLength: [100, 'عنوان باید حداکثر ۱۰۰ کاراکتر باشد'], + unique: true, + index: true, + }, + slug: { + type: String, + required: true, + unique: true, + lowercase: true, + trim: true, + index: true, + }, + description: { + type: String, + required: false, + trim: true, + maxLength: 500, + default: null, + }, + icon: { + type: String, + required: false, + default: null, + }, + color: { + type: String, + required: false, + default: '#3B82F6', + match: /^#[0-9A-F]{6}$/i, + }, + parent: { + type: mongoose.Schema.Types.ObjectId, + ref: 'AcademyCategory', + required: false, + default: null, + index: true, + }, + level: { + type: Number, + required: true, + default: 0, + min: 0, + max: 3, + }, + order: { + type: Number, + required: true, + default: 0, + index: true, + }, + image: { + type: String, + required: false, + default: null, + }, + course_count: { + type: Number, + required: true, + default: 0, + min: 0, + }, + status: { + type: String, + enum: ['active', 'inactive', 'deleted'], + required: true, + default: 'active', + index: true, + }, + is_featured: { + type: Boolean, + required: true, + default: false, + index: true, + }, + seo_title: { + type: String, + required: false, + trim: true, + maxLength: 70, + }, + seo_description: { + type: String, + required: false, + trim: true, + maxLength: 160, + }, + created_by: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true, + }, + updated_by: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: false, + }, +}, { + toJSON: { virtuals: true }, + toObject: { virtuals: true } +}); + +// Virtual برای زیردسته‌ها +AcademyCategorySchema.virtual('children', { + ref: 'AcademyCategory', + localField: '_id', + foreignField: 'parent', + justOne: false, + options: { sort: { order: 1, title: 1 } } +}); + +// Virtual برای دوره‌های این دسته +AcademyCategorySchema.virtual('courses', { + ref: 'Course', + localField: '_id', + foreignField: 'category_id', + justOne: false, + match: { status: 'accept' } +}); + +// Middleware: قبل از save +AcademyCategorySchema.pre('save', async function(next) { + if (this.isModified('title') || this.isNew) { + // تولید slug + this.slug = this.title + .replace(/[^\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C\uFB8E\u0698a-zA-Z0-9\s]/g, '') + .trim() + .replace(/\s+/g, '-') + .toLowerCase(); + + // اگه parent داره، سطح رو محاسبه کن + if (this.parent) { + const parent = await this.constructor.findById(this.parent); + if (parent) { + this.level = parent.level + 1; + } + } else { + this.level = 0; + } + } + next(); +}); + +// استاتیک متدها +AcademyCategorySchema.statics = { + // دریافت درخت دسته‌بندی‌ها + async getTree() { + const categories = await this.find({ status: 'active', parent: null }) + .sort({ order: 1, title: 1 }) + .populate({ + path: 'children', + match: { status: 'active' }, + options: { sort: { order: 1, title: 1 } }, + populate: { + path: 'children', + match: { status: 'active' }, + options: { sort: { order: 1, title: 1 } } + } + }); + return categories; + }, + + // افزایش تعداد دوره‌ها + async incrementCourseCount(categoryId, increment = 1) { + return this.findByIdAndUpdate(categoryId, { + $inc: { course_count: increment } + }); + }, + + // دریافت دسته‌بندی با اسلاگ + async getBySlug(slug) { + return this.findOne({ slug, status: 'active' }) + .populate('children') + .populate('parent'); + } +}; + +AcademyCategorySchema.plugin(timestamp); +AcademyCategorySchema.plugin(mongoosePaginate); + +module.exports = mongoose.model('AcademyCategory', AcademyCategorySchema); \ No newline at end of file diff --git a/public/modstagram-back/controllers/application/academy/models/AcademyContentModel.js b/public/modstagram-back/controllers/application/academy/models/AcademyContentModel.js new file mode 100644 index 0000000..092990f --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AcademyContentModel.js @@ -0,0 +1,71 @@ +const mongoose = require('mongoose'); +const timestamp = require('mongoose-timestamp'); +const mongoosePaginate = require('mongoose-paginate-v2'); + +const modelSchema = new mongoose.Schema({ + course_images: { + type: [String], // آرایه‌ای از مسیرهای تصاویر + required: false, + default: [], + }, + course_video: { + type: String, // مسیر ویدئو + required: false, + trim: true, + default: null, + }, + type: { + type: String, // نوع پست: 'image' یا 'video' + required: true, + enum: ['image', 'video'], + }, + files: [ + { + path: { type: String, required: false }, + type: { type: String, enum: ['image', 'video'], required: false }, + } + ], + caption: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1000, + default: null, + }, + status: { + type: String, + required: false, + trim: true, + enum: ['pending', 'accept', 'reject'], + default: 'accept', + }, + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }, + likes: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }], + comments: { + type: Object, + default: null, + }, + courseId: { + type: String, + }, + + is_free: { + type: Boolean, + }, + file_name: { + type: String, + }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model('AcademyContent', modelSchema); +module.exports = PostModel; \ No newline at end of file diff --git a/public/modstagram-back/controllers/application/academy/models/AcademyLikeModel.js b/public/modstagram-back/controllers/application/academy/models/AcademyLikeModel.js new file mode 100644 index 0000000..358f036 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AcademyLikeModel.js @@ -0,0 +1,25 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + + user_id: { + type: String, + required: true, + trim: true, + default: 0, + }, + course_id: { + type: String, + required: true, + trim: true, + default: 0, + }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("Likes", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/controllers/application/academy/models/AcademyModel.js b/public/modstagram-back/controllers/application/academy/models/AcademyModel.js new file mode 100644 index 0000000..9f8e758 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AcademyModel.js @@ -0,0 +1,55 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + academy_image: { + type: String, + required: false, + trim: true, + default: null, + }, + academy_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null, + }, + userId: { + type: String, + required: true, + }, + rate: { + type: Number, + trim: true, + default: 0 + }, + number_of_rate: { + type: Number, + trim: true, + default: 0 + }, + sheba: { + type: String, + required: false, + default: null + }, + bio: { + type: String, + required: false, + default: null + }, + tag: { + type: Object, + required: false, + default: null + }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("Academy", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/controllers/application/academy/models/AcademyPaymentModel.js b/public/modstagram-back/controllers/application/academy/models/AcademyPaymentModel.js new file mode 100644 index 0000000..b7c9fa7 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AcademyPaymentModel.js @@ -0,0 +1,24 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + price: { type: Number, required: true }, // قیمت نهایی شامل مالیات + discountAmount: { type: Number, default: 0 }, // مبلغ تخفیف + taxAmount: { type: Number, default: 0 }, // مبلغ مالیات + taxRate: { type: Number, default: 9 }, // درصد مالیات + course_name: { type: String, required: true }, + course_id: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true }, + academy_id: { type: mongoose.Schema.Types.ObjectId, ref: "Academy", required: true }, + user_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }, + payment_authority: { type: String }, + payment_ref_id: { type: String }, + status: { type: String, enum: ["pending", "success", "failed", "settled"], default: "success" }, + + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("AcademyPayment", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/controllers/application/academy/models/AdminModel.js b/public/modstagram-back/controllers/application/academy/models/AdminModel.js new file mode 100644 index 0000000..4bca3a2 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdminModel.js @@ -0,0 +1,80 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const adminSchema = new mongoose.Schema({ + mobile: { + type: String, + required: false, + trim: true, + unique: true + }, + otp: { + type: String, + required: false, + trim: true, + minLength: 6, + maxLength: 6 + }, + user_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + password: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + first_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + last_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + user_type: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + profile_image: { + type: String, + required: false, + trim: true + }, + gender: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + last_online: { + type: Date, // ذخیره تاریخ و زمان آخرین بازدید + default: Date.now // تنظیم تاریخ به تاریخ فعلی + } +}) + +adminSchema.plugin(timestamp) +adminSchema.plugin(mongoosePaginate) +const AdminModel = mongoose.model('Admin', adminSchema) +module.exports = AdminModel diff --git a/public/modstagram-back/controllers/application/academy/models/AdvertisingCategoryModel.js b/public/modstagram-back/controllers/application/academy/models/AdvertisingCategoryModel.js new file mode 100644 index 0000000..855035a --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdvertisingCategoryModel.js @@ -0,0 +1,23 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const advertisingCategorySchema = new mongoose.Schema({ + title: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + status: { + type: Boolean, + required: false, + default: true + } +}) + +advertisingCategorySchema.plugin(timestamp) +advertisingCategorySchema.plugin(mongoosePaginate) +const AdvertisingCategoryModel = mongoose.model('AdvertisingCategory', advertisingCategorySchema) +module.exports = AdvertisingCategoryModel diff --git a/public/modstagram-back/controllers/application/academy/models/AdvertisingCommentModel.js b/public/modstagram-back/controllers/application/academy/models/AdvertisingCommentModel.js new file mode 100644 index 0000000..f6ea2b4 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdvertisingCommentModel.js @@ -0,0 +1,32 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const advertisingCommentSchema = new mongoose.Schema({ + advertisingId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Advertising', + required: true + }, + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + text: { + type: String, + required: true, + trim: true + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], + default: 'pending' + } +}) + +advertisingCommentSchema.plugin(timestamp) +advertisingCommentSchema.plugin(mongoosePaginate) +const AdvertisingComment = mongoose.model('AdvertisingComment', advertisingCommentSchema) + +module.exports = AdvertisingComment diff --git a/public/modstagram-back/controllers/application/academy/models/AdvertisingFeaturesModel.js b/public/modstagram-back/controllers/application/academy/models/AdvertisingFeaturesModel.js new file mode 100644 index 0000000..4081d59 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdvertisingFeaturesModel.js @@ -0,0 +1,27 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const advertisingFeaturesSchema = new mongoose.Schema({ + title: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + status: { + type: Boolean, + required: false, + default: true + }, + type: { + type: String, + default: 'boolean' + } +}) + +advertisingFeaturesSchema.plugin(timestamp) +advertisingFeaturesSchema.plugin(mongoosePaginate) +const AdvertisingFeaturesModel = mongoose.model('AdvertisingFeatures', advertisingFeaturesSchema) +module.exports = AdvertisingFeaturesModel diff --git a/public/modstagram-back/controllers/application/academy/models/AdvertisingLikeModel.js b/public/modstagram-back/controllers/application/academy/models/AdvertisingLikeModel.js new file mode 100644 index 0000000..f8552dd --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdvertisingLikeModel.js @@ -0,0 +1,20 @@ +const mongoose = require('mongoose') + +const advertisingLikeSchema = new mongoose.Schema({ + advertisingId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Advertising', + required: true + }, + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + } + +}) + +// تعریف مدل AdvertisingLikeModel +const AdvertisingLikeModel = mongoose.model('AdvertisingLike', advertisingLikeSchema) + +module.exports = AdvertisingLikeModel diff --git a/public/modstagram-back/controllers/application/academy/models/AdvertisingModel.js b/public/modstagram-back/controllers/application/academy/models/AdvertisingModel.js new file mode 100644 index 0000000..3046a48 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdvertisingModel.js @@ -0,0 +1,230 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const advertisingSchema = new mongoose.Schema({ + title: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + category: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + description: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1024, + default: null + }, + province: { + type: Object, + default: null + }, + city: { + type: Object, + default: null + }, + neighbourhood: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + address: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + lat: { + type: String, + trim: true, + minLength: 1, + maxLength: 256, + default: null + }, + lng: { + type: String, + trim: true, + minLength: 1, + maxLength: 256, + default: null + }, + images: [{ + type: String, + required: false, + trim: true, + default: null + }], + services: [{ + title: { + type: String, + required: true, + trim: true + }, + originalPrice: { + type: String, + required: true + }, + discountPrice: { + type: String, + required: false + }, + discountPercentage: { + type: Number, + required: false + }, + status: { + type: String, + default: "UnderReview", + required: false + }, + image: { + type: String, + required: false, + trim: true + } + }], + features: [{ + title: { + type: String, + required: false, + trim: true + }, + value: { + type: Boolean, + required: true + } + }], + contactInfo: { + phone: { + type: String, + required: false, + trim: true, + default: null + }, + mobile: { + type: String, + required: false, + trim: true, + default: null + }, + telegramLink: { + type: String, + required: false, + trim: true, + default: null + }, + whatsappNumber: { + type: String, + required: false, + trim: true, + default: null + }, + instagramLink: { + type: String, + required: false, + trim: true, + default: null + }, + saveInfoForNextAds: { + type: Boolean, + required: true, + default: false + } + }, + type: { + type: String, + enum: ['free', 'normal', 'special', 'highlight'], + default: 'normal' + }, + status: { + type: String, + enum: ['pre_payment', 'paid', 'accepted', 'rejected', 'expired'], + default: 'pre_payment' + }, + payment_status: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + creator_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }, + reject_reason: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1024, + default: null + }, + mostDiscountPercentage: { + type: Number, + required: false + }, + showDiscount: { + type: Boolean, + required: false, + default: false + }, + likesCount: { + type: Number, + default: 0 + }, + commentsCount: { + type: Number, + default: 0 + }, + ratings: [{ + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + rating: { + type: Number, + required: true, + min: 1, + max: 5 + } + }], + averageRating: { + type: Number, + default: 0 + }, + ratingsCount: { + type: Number, + default: 0 + }, + viewCount: { + type: Number, + default: 0 + }, + acceptedAt: { + type: Date, + default: null + } +}) + +advertisingSchema.plugin(timestamp) +advertisingSchema.plugin(mongoosePaginate) +const AdvertisingModel = mongoose.model('Advertising', advertisingSchema) +module.exports = AdvertisingModel diff --git a/public/modstagram-back/controllers/application/academy/models/AdvertisingProfile.js b/public/modstagram-back/controllers/application/academy/models/AdvertisingProfile.js new file mode 100644 index 0000000..70dfc5a --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdvertisingProfile.js @@ -0,0 +1,113 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const advertisingProfileSchema = new mongoose.Schema({ + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + profile_image: { + type: String, + required: false, + trim: true, + default: null + }, + image_count: { + type: Number, + default: 0 + }, + like_count: { + type: Number, + default: 0 + }, + comment_count: { + type: Number, + default: 0 + }, + vitrine_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + category: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + about_us: { + type: String, + required: false, + minLength: 1, + maxLength: 1024, + default: null + }, + province: { + type: Object, + default: null + }, + city: { + type: Object, + default: null + }, + lat: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + lng: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + address: { + type: String, + required: false, + trim: true, + default: null + }, + neighbourhood: { + type: String, + required: false, + trim: true, + default: null + }, + adTotalRatings: { + type: Number, + default: 0 + }, + adRatingsCount: { + type: Number, + default: 0 + }, + adAverageRating: { + type: Number, + default: 0 + }, + contactInfo: { + phone: String, + mobile: String, + telegramLink: String, + whatsappNumber: String, + instagramLink: String, + saveInfoForNextAds: { type: Boolean, default: false } + } +}) + +advertisingProfileSchema.plugin(timestamp) +advertisingProfileSchema.plugin(mongoosePaginate) + +const AdvertisingProfileModel = mongoose.model('AdvertisingProfile', advertisingProfileSchema) + +module.exports = AdvertisingProfileModel diff --git a/public/modstagram-back/controllers/application/academy/models/AdvertisingRatingModel.js b/public/modstagram-back/controllers/application/academy/models/AdvertisingRatingModel.js new file mode 100644 index 0000000..ac8b79b --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdvertisingRatingModel.js @@ -0,0 +1,26 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const advertisingRatingSchema = new mongoose.Schema({ + advertisingId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Advertising', + required: true + }, + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + rating: { + type: Number, + required: true, + min: 1, + max: 5 + } +}) + +advertisingRatingSchema.plugin(timestamp) + +const AdvertisingRatingModel = mongoose.model('AdvertisingRating', advertisingRatingSchema) +module.exports = AdvertisingRatingModel diff --git a/public/modstagram-back/controllers/application/academy/models/AdvertisingTypeModel.js b/public/modstagram-back/controllers/application/academy/models/AdvertisingTypeModel.js new file mode 100644 index 0000000..5b49649 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/AdvertisingTypeModel.js @@ -0,0 +1,25 @@ +const mongoose = require('mongoose') + +const advertisingTypeSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + }, + price: { + type: Number, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + }, + status: { + type: String, + default: 'active' + } +}) + +const AdvertisingTypeModel = mongoose.model('AdvertisingType', advertisingTypeSchema) +module.exports = AdvertisingTypeModel diff --git a/public/modstagram-back/controllers/application/academy/models/CommentModel.js b/public/modstagram-back/controllers/application/academy/models/CommentModel.js new file mode 100644 index 0000000..5fbabc9 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/CommentModel.js @@ -0,0 +1,54 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const commentSchema = new mongoose.Schema({ + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + project: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Project', + required: false + }, + offer: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Offer', + required: false + }, + creator: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + rating: { + type: Number, + required: true + }, + comment: { + type: String, + trim: true + }, + post: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Post', + required: false + }, + comment_for: { + type: String, + enum: ['user', 'project', 'post'], + required: true + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], + default: 'pending' + } +}) + +commentSchema.plugin(timestamp) +commentSchema.plugin(mongoosePaginate) +const CommentModel = mongoose.model('Comment', commentSchema) +module.exports = CommentModel diff --git a/public/modstagram-back/controllers/application/academy/models/CourseComentModel.js b/public/modstagram-back/controllers/application/academy/models/CourseComentModel.js new file mode 100644 index 0000000..b5c7d5c --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/CourseComentModel.js @@ -0,0 +1,40 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + + user_id: { + type: String, + required: true, + trim: true, + }, + course_id: { + type: String, + required: true, + trim: true, + }, + comment: { + type: String, + required: true, + trim: true, + default: 0, + }, + rate: { + type: String, + required: true, + trim: true, + default: 0, + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], + default: 'accepted' + } + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("CourseComment", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/controllers/application/academy/models/CourseModel.js b/public/modstagram-back/controllers/application/academy/models/CourseModel.js new file mode 100644 index 0000000..f8a5e67 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/CourseModel.js @@ -0,0 +1,79 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + price: { + type: String, + required: true, + }, + cuorse_name: { + type: String, + required: true, + }, + category:{ + type: String + }, + offer: { + type: String + }, + academyId:{ + type: String + }, + caption: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1000, + default: null, + }, + status: { + type: String, + required: false, + trim: true, + enum: ['pending', 'accept', 'reject'], + default: 'accept', + }, + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }, + likes: { + type: Number, + required: false, + trim: true, + default: 0, + }, + comments: { + type: Object, + default: null, + }, + type: { + type: String, + required: false, + trim: true, + enum: ['normal', 'pro', 'legend'], + default: "normal", + }, + course_time: { + type: String + }, + number_of_course_content: { + type: String + }, + teacher_number: { + type: String + }, + course_image: { + type: String + }, + teacher_name: { + type: String + }, +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("Course", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/controllers/application/academy/models/CoursePaymentModel.js b/public/modstagram-back/controllers/application/academy/models/CoursePaymentModel.js new file mode 100644 index 0000000..cb6de53 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/CoursePaymentModel.js @@ -0,0 +1,22 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + price: { + type: String, + required: true, + }, + cuorse_type: { + type: String, + required: false, + trim: true, + enum: ['normal', 'pro', 'legend'], + }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("CoursePayment", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/controllers/application/academy/models/ExpertiseModel.js b/public/modstagram-back/controllers/application/academy/models/ExpertiseModel.js new file mode 100644 index 0000000..29b490a --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/ExpertiseModel.js @@ -0,0 +1,47 @@ +// const mongoose = require('mongoose') +// const timestamp = require('mongoose-timestamp') + +// const subExpertiseSchema = new mongoose.Schema({ +// id: { +// type: mongoose.Schema.Types.ObjectId, +// ref: 'ExpertiseModel' +// }, +// name: { +// type: String +// } +// }) + +// const expertiseSchema = new mongoose.Schema({ +// expertise: { +// type: String, +// unique: true +// }, +// sub_expertise: [subExpertiseSchema] +// }) + +// expertiseSchema.plugin(timestamp) + +// const ExpertiseModel = mongoose.model('Expertise', expertiseSchema) +// module.exports = ExpertiseModel + +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const subExpertiseSchema = new mongoose.Schema({ + name: { + type: String + } +}) + +const expertiseSchema = new mongoose.Schema({ + expertise: { + type: String, + unique: true + }, + sub_expertise: [subExpertiseSchema] +}) + +expertiseSchema.plugin(timestamp) + +const ExpertiseModel = mongoose.model('Expertise', expertiseSchema) +module.exports = ExpertiseModel diff --git a/public/modstagram-back/controllers/application/academy/models/IsPaymentCourseModel.js b/public/modstagram-back/controllers/application/academy/models/IsPaymentCourseModel.js new file mode 100644 index 0000000..0524f3c --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/IsPaymentCourseModel.js @@ -0,0 +1,15 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + user_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }, + course_id: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true }, + price_paid: { type: Number, required: true }, // قیمت پرداخت شده + purchased_at: { type: Date, default: Date.now }, +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("IsPaymentCourse", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/controllers/application/academy/models/LikeModel.js b/public/modstagram-back/controllers/application/academy/models/LikeModel.js new file mode 100644 index 0000000..1957530 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/LikeModel.js @@ -0,0 +1,25 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const likeSchema = new mongoose.Schema({ + postId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Post', + required: true + }, + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + likes: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }] +}) + +// تعریف مدل LikeModel +likeSchema.plugin(timestamp) +const LikeModel = mongoose.model('Like', likeSchema) + +module.exports = LikeModel diff --git a/public/modstagram-back/controllers/application/academy/models/MessageModel.js b/public/modstagram-back/controllers/application/academy/models/MessageModel.js new file mode 100644 index 0000000..594f7c4 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/MessageModel.js @@ -0,0 +1,51 @@ +const mongoose = require('mongoose') +const { Schema } = mongoose + +const messageSchema = new Schema({ + senderId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + receiverId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + content: { + type: String, + required: false, + trim: true + }, + file: { + type: String, + required: false + }, + fileType: { + type: String, + enum: ['image', 'video', 'file', 'voice', 'location'], + required: false + }, + replyToId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Message', + required: false + }, + forwardedFrom: { + userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, + userName: String, + displayName: String + }, + createdAt: { + type: Date, + default: Date.now + }, + readStatus: { + type: Number, + default: 0 + } +}) + +const MessageModel = mongoose.model('Message', messageSchema) + +module.exports = MessageModel diff --git a/public/modstagram-back/controllers/application/academy/models/NotificationModel.js b/public/modstagram-back/controllers/application/academy/models/NotificationModel.js new file mode 100644 index 0000000..ff79e19 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/NotificationModel.js @@ -0,0 +1,37 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const notificationSchema = new mongoose.Schema({ + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', // مرجع به مدل کاربر + required: true + }, + project_post_id: { + type: mongoose.Schema.Types.ObjectId, + required: false + }, + type: { + type: String, + required: true + }, + title: { + type: String, + required: true + }, + description: { + type: String, + required: true + }, + read: { + type: Boolean, + default: false // وضعیت خوانده شده یا نشده + } +}) + +notificationSchema.plugin(timestamp) +notificationSchema.plugin(mongoosePaginate) + +const NotificationModel = mongoose.model('Notification', notificationSchema) +module.exports = NotificationModel diff --git a/public/modstagram-back/controllers/application/academy/models/OfferModel.js b/public/modstagram-back/controllers/application/academy/models/OfferModel.js new file mode 100644 index 0000000..ec36550 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/OfferModel.js @@ -0,0 +1,32 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') + +const offerSchema = new mongoose.Schema({ + sender: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + receiver: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], // وضعیت درخواست + default: 'pending' + }, + transaction_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Payment', + default: null + } +}) + +offerSchema.plugin(timestamp) +offerSchema.plugin(mongoosePaginate) + +const OfferModel = mongoose.model('Offer', offerSchema) +module.exports = OfferModel diff --git a/public/modstagram-back/controllers/application/academy/models/OfferTypeModel.js b/public/modstagram-back/controllers/application/academy/models/OfferTypeModel.js new file mode 100644 index 0000000..fa2b49c --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/OfferTypeModel.js @@ -0,0 +1,21 @@ +const mongoose = require('mongoose') + +const offerTypeModelSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + }, + price: { + type: Number, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + } +}) + +const OfferTypeModel = mongoose.model('OfferTypeModel', offerTypeModelSchema) +module.exports = OfferTypeModel diff --git a/public/modstagram-back/controllers/application/academy/models/PaymentModel.js b/public/modstagram-back/controllers/application/academy/models/PaymentModel.js new file mode 100644 index 0000000..c78a252 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/PaymentModel.js @@ -0,0 +1,46 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const paymentSchema = new mongoose.Schema({ + amount: { + type: Number, + required: true + }, + status: { + type: String, + enum: ['pending', 'successful', 'failed'], + default: 'pending' + }, + authority: { + type: String, + required: false + }, + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }, + project_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Project' + }, + advertising_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Advertising' + }, + type: { + type: String, + required: true + }, + installment_step: { + type: String, + required: false, + default: null + } +}) + +paymentSchema.plugin(timestamp) +paymentSchema.plugin(mongoosePaginate) + +const PaymentModel = mongoose.model('Payment', paymentSchema) +module.exports = PaymentModel diff --git a/public/modstagram-back/controllers/application/academy/models/PostModel.js b/public/modstagram-back/controllers/application/academy/models/PostModel.js new file mode 100644 index 0000000..ff6d8cc --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/PostModel.js @@ -0,0 +1,60 @@ +const mongoose = require('mongoose'); +const timestamp = require('mongoose-timestamp'); +const mongoosePaginate = require('mongoose-paginate-v2'); + +const modelSchema = new mongoose.Schema({ + post_images: { + type: [String], // آرایه‌ای از مسیرهای تصاویر + required: false, + default: [], + }, + post_video: { + type: String, // مسیر ویدئو + required: false, + trim: true, + default: null, + }, + type: { + type: String, // نوع پست: 'image' یا 'video' + required: true, + enum: ['image', 'video'], + }, + files: [ + { + path: { type: String, required: true }, + type: { type: String, enum: ['image', 'video'], required: true }, + } + ], + caption: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1000, + default: null, + }, + status: { + type: String, + required: false, + trim: true, + enum: ['pending', 'accept', 'reject'], + default: 'pending', + }, + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }, + likes: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }], + comments: { + type: Object, + default: null, + }, +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model('Post', modelSchema); +module.exports = PostModel; \ No newline at end of file diff --git a/public/modstagram-back/controllers/application/academy/models/ProjectModel.js b/public/modstagram-back/controllers/application/academy/models/ProjectModel.js new file mode 100644 index 0000000..4b4382e --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/ProjectModel.js @@ -0,0 +1,186 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') +const projectSchema = new mongoose.Schema({ + title: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + expertise: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + sub_expertise: { + type: [String], // تغییر نوع به آرایه از استرینگ + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + gender: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + age: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + conversation_projects: { + type: Boolean, + required: false, + default: null + }, + province: { + type: Object, + default: null + }, + city: { + type: Object, + default: null + }, + offer_time: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + offer_price: { + type: Number, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + description: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1024, + default: null + }, + project_type: { + type: String, + enum: ['free', 'normal', 'force', 'highlight'], + default: 'normal' + }, + payment_status: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + // فیلد برای وضعیت پروژه + status: { + type: String, + enum: ['pre_payment', 'paid', 'accepted', 'rejected', 'done', 'cancled', 'ongoing'], + default: 'pre_payment' + }, + public_status: { + type: String, + enum: ['public', 'private'], + default: 'public' + }, + created_for_user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + default: null + }, + creator_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }, + requested_users: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }], + selected_user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + default: null + }, + final_price: { + type: Number, + required: false, + default: null + }, + final_time: { + type: Number, + required: false, + default: null + }, + installments: [{ + installment_number: { + type: Number, + required: true + }, + amount: { + type: Number, + required: true + }, + due_date: { + type: Date, + required: true + } + }], + reject_reason: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1024, + default: null + }, + ratings: [{ + creator_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + rating: { + type: Number, + required: true + }, + comment: { + type: String, + trim: true + } + }], + acceptedAt: { + type: Date, + default: null + }, + isExpired: { + type: Boolean, + default: false + } + +}) + +projectSchema.plugin(timestamp) +// اضافه کردن پیجینیشن به مدل +projectSchema.plugin(mongoosePaginate) +const ProjectModel = mongoose.model('Project', projectSchema) +module.exports = ProjectModel diff --git a/public/modstagram-back/controllers/application/academy/models/RequestModel.js b/public/modstagram-back/controllers/application/academy/models/RequestModel.js new file mode 100644 index 0000000..3049ec1 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/RequestModel.js @@ -0,0 +1,33 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const requestSchema = new mongoose.Schema({ + project: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Project', + required: true + }, + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + time: { + type: Number, + required: true + }, + price: { + type: Number, + required: true + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], + default: 'pending' + } +}) + +requestSchema.plugin(timestamp) + +const RequestModel = mongoose.model('Request', requestSchema) +module.exports = RequestModel diff --git a/public/modstagram-back/controllers/application/academy/models/SettingsModel.js b/public/modstagram-back/controllers/application/academy/models/SettingsModel.js new file mode 100644 index 0000000..8d41208 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/SettingsModel.js @@ -0,0 +1,19 @@ +// models/Setting.js +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const settingSchema = new mongoose.Schema({ + key: { + type: String, + required: true, + unique: true + }, + value: { + type: String, + required: true + } +}) +settingSchema.plugin(timestamp) + +const SettingModel = mongoose.model('Setting', settingSchema) +module.exports = SettingModel diff --git a/public/modstagram-back/controllers/application/academy/models/StateCity.js b/public/modstagram-back/controllers/application/academy/models/StateCity.js new file mode 100644 index 0000000..5f24232 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/StateCity.js @@ -0,0 +1,19 @@ +const mongoose = require('mongoose') + +const provincesSchema = new mongoose.Schema({ + id: Number, + name: String, + slug: String +}) + +const citiesSchema = new mongoose.Schema({ + id: Number, + name: String, + slug: String, + province_id: Number +}) + +const ProvinceModel = mongoose.model('Province', provincesSchema) +const CityModel = mongoose.model('City', citiesSchema) + +module.exports = { ProvinceModel, CityModel } diff --git a/public/modstagram-back/controllers/application/academy/models/TaxModel.js b/public/modstagram-back/controllers/application/academy/models/TaxModel.js new file mode 100644 index 0000000..70b27e7 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/TaxModel.js @@ -0,0 +1,15 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + type: { type: String, enum: ["course", "product", "service"], required: true }, + tax: { type: Number, required: true, default: 9 }, // درصد مالیات + is_active: { type: Boolean, default: true }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("Tax", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/controllers/application/academy/models/TicketMessageModel.js b/public/modstagram-back/controllers/application/academy/models/TicketMessageModel.js new file mode 100644 index 0000000..b054d05 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/TicketMessageModel.js @@ -0,0 +1,20 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const ticketMessageSchema = new mongoose.Schema({ + text: { type: String, required: false }, + file: { + type: String, // مسیر فایل در ذخیره شود + required: false // فایل اختیاری است + }, + senderType: { type: String, enum: ['User', 'Admin'], required: true }, + senderId: { type: mongoose.Schema.Types.ObjectId, refPath: 'senderType', required: true }, + ticket: { type: mongoose.Schema.Types.ObjectId, ref: 'Ticket', required: true } +}) + +ticketMessageSchema.plugin(timestamp) +// اضافه کردن پیجینیشن به مدل +ticketMessageSchema.plugin(mongoosePaginate) +const TicketMessageModel = mongoose.model('TicketMessage', ticketMessageSchema) +module.exports = TicketMessageModel diff --git a/public/modstagram-back/controllers/application/academy/models/TicketModel.js b/public/modstagram-back/controllers/application/academy/models/TicketModel.js new file mode 100644 index 0000000..4157fb3 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/TicketModel.js @@ -0,0 +1,24 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const ticketSchema = new mongoose.Schema({ + title: { type: String, required: true }, + status: { type: String, enum: ['Pending', 'Answered', 'Customer Response', 'Closed'], default: 'Pending' }, + user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, + new_message: { + type: Boolean, + default: false // وضعیت خوانده شده یا نشده + } +}) + +ticketSchema.pre('save', function (next) { + this.updatedAt = Date.now() + next() +}) + +ticketSchema.plugin(timestamp) +// اضافه کردن پیجینیشن به مدل +ticketSchema.plugin(mongoosePaginate) +const TicketModel = mongoose.model('Ticket', ticketSchema) +module.exports = TicketModel diff --git a/public/modstagram-back/controllers/application/academy/models/TypeAndPriceModel.js b/public/modstagram-back/controllers/application/academy/models/TypeAndPriceModel.js new file mode 100644 index 0000000..2b059d1 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/TypeAndPriceModel.js @@ -0,0 +1,21 @@ +const mongoose = require('mongoose') + +const typeAndPriceSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + }, + price: { + type: Number, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + } +}) + +const TypeAndPriceModel = mongoose.model('TypeAndPrice', typeAndPriceSchema) +module.exports = TypeAndPriceModel diff --git a/public/modstagram-back/controllers/application/academy/models/UserModel.js b/public/modstagram-back/controllers/application/academy/models/UserModel.js new file mode 100644 index 0000000..66b025a --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/UserModel.js @@ -0,0 +1,381 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const userSchema = new mongoose.Schema({ + mobile: { + type: String, + required: false, + trim: true, + unique: true + }, + otp: { + type: String, + required: false, + trim: true, + minLength: 6, + maxLength: 6, + default: null + }, + user_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + password: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + first_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + last_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + user_type: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + is_verified: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: 'none' + }, + profile_image: { + type: String, + required: false, + trim: true, + default: null + }, + national_card_image: { + type: String, + required: false, + trim: true, + default: null + }, + expertise: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + sub_expertise: { + type: [String], // تغییر نوع به آرایه از استرینگ + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + gender: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + height: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + weight: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + size: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + eye_color: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + hair_color: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + cooperation_type: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + cooperation_abroad: { + type: Boolean, + required: false, + default: null + }, + conversation_projects: { + type: Boolean, + required: false, + default: null + }, + bio: { + type: String, + required: false, + minLength: 1, + maxLength: 1024, + default: null + }, + national_code: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + birthday: { + type: Date, + required: false, + default: null + }, + is_Register: { + type: String, + + default: false + }, + shaba: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + address: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + province: { + type: Object, + default: null + }, + city: { + type: Object, + default: null + }, + lat: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + lng: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + show_location: { + type: Boolean, + required: false, + default: null + }, + rate: { + type: String, + trim: true, + maxLength: 512, + default: null + }, + referral_code: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + shop_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Shop', + default: null + }, + last_online: { + type: Date, // ذخیره تاریخ و زمان آخرین بازدید + default: Date.now // تنظیم تاریخ به تاریخ فعلی + }, + business_license: { + type: String, + required: false, + trim: true, + default: null + }, + user_level: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + user_score: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + last_post: { + type: Object, + default: null + }, + // user_ratings: [{ + // project_id: { + // type: mongoose.Schema.Types.ObjectId, + // ref: 'Project', + // required: true + // }, + // creator_id: { + // type: mongoose.Schema.Types.ObjectId, + // ref: 'User', + // required: true + // }, + // rating: { + // type: Number, + // required: true + // }, + // comment: { + // type: String, + // trim: true + // } + // }], + daily_free_request: { + type: Number, + default: 1 + }, + last_free_request_date: { + type: Date, + default: null + }, + blocked_by: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }], + blocked_users: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }], + block_status: { + type: Boolean, + required: false, + default: null + }, + advertising_profiles: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'AdvertisingProfile' + }], + services: [{ + title: { + type: String, + required: true, + trim: true + }, + originalPrice: { + type: String, + required: true + }, + discountPrice: { + type: String, + required: false + }, + discountPercentage: { + type: Number, + required: false + }, + status: { + type: String, + default: "UnderReview", + required: false + }, + image: { + type: String, + required: false, + trim: true + } + }], + monthly_free_offer: { + type: Number, + default: 1 + }, + last_free_offer_date: { + type: Date, + default: null + } + // contactInfo: { + // phone: String, + // mobile: String, + // telegramLink: String, + // whatsappNumber: String, + // instagramLink: String, + // saveInfoForNextAds: { type: Boolean, default: false } + // }, + // adTotalRatings: { + // type: Number, + // default: 0 + // }, + // adRatingsCount: { + // type: Number, + // default: 0 + // }, + // adAverageRating: { + // type: Number, + // default: 0 + // } +}) + +userSchema.plugin(timestamp) +userSchema.plugin(mongoosePaginate) +const UserModel = mongoose.model('User', userSchema) +module.exports = UserModel diff --git a/public/modstagram-back/controllers/application/academy/models/VersionModel.js b/public/modstagram-back/controllers/application/academy/models/VersionModel.js new file mode 100644 index 0000000..51aaf0b --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/VersionModel.js @@ -0,0 +1,12 @@ +// models/VersionModel.js +const mongoose = require('mongoose') + +const versionSchema = new mongoose.Schema({ + version: { type: String, required: true }, + mandatory: { type: Boolean, required: true }, + releaseNotes: { type: String }, + updateUrls: { type: [String], required: true } // لینک‌های آپدیت +}) + +const VersionModel = mongoose.model('Version', versionSchema) +module.exports = VersionModel diff --git a/public/modstagram-back/controllers/application/academy/models/license.js b/public/modstagram-back/controllers/application/academy/models/license.js new file mode 100644 index 0000000..13c59a2 --- /dev/null +++ b/public/modstagram-back/controllers/application/academy/models/license.js @@ -0,0 +1,14 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const license = new mongoose.Schema({ + + userId : String, + Confirmation : { type : Boolean, default : false}, + licenseImg : { type : String }, +}) + +license.plugin(timestamp) +license.plugin(mongoosePaginate) +const LicenseMoldel = mongoose.model('license', license) +module.exports = LicenseMoldel diff --git a/public/modstagram-back/controllers/application/advertising/advertisingController.js b/public/modstagram-back/controllers/application/advertising/advertisingController.js new file mode 100644 index 0000000..59d3667 --- /dev/null +++ b/public/modstagram-back/controllers/application/advertising/advertisingController.js @@ -0,0 +1,1414 @@ +/* eslint-disable eqeqeq */ +/* eslint-disable camelcase */ +const jwt = require('jsonwebtoken') +const { check, validationResult } = require('express-validator') +const { ProvinceModel, CityModel } = require('../../../models/StateCity') +const UserModel = require('../../../models/UserModel') +const AdvertisingModel = require('../../../models/AdvertisingModel') +const fs = require('fs-extra') +const path = require('path') +const AdvertisingTypeModel = require('../../../models/AdvertisingTypeModel') +const AdvertisingCategoryModel = require('../../../models/AdvertisingCategoryModel') +const AdvertisingFeaturesModel = require('../../../models/AdvertisingFeaturesModel') +const AdvertisingLikeModel = require('../../../models/AdvertisingLikeModel') +const AdvertisingComment = require('../../../models/AdvertisingCommentModel') +const AdvertisingRatingModel = require('../../../models/AdvertisingRatingModel') +const AdvertisingProfileModel = require('../../../models/AdvertisingProfile') + +const createAdvertisingValidationRules = () => { + return [ + check('title').notEmpty().withMessage('عنوان نمی‌تواند خالی باشد'), + check('category').notEmpty().withMessage('دسته‌بندی نمی‌تواند خالی باشد'), + check('province').notEmpty().withMessage('استان نمی‌تواند خالی باشد'), + check('city').notEmpty().withMessage('شهر نمی‌تواند خالی باشد') + ] +} +// تابع کمکی برای ذخیره تصاویر +const saveFile = async (file, folder, userName) => { + const uploadDir = path.join(__dirname, '../../../../storage', folder) + if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true }) + + const uniqueFileName = `${userName}-${Date.now()}${Math.random().toString().slice(2, 11)}${path.extname(file.name)}` + const filePath = path.join(uploadDir, uniqueFileName) + await fs.move(file.path, filePath) + return `/${folder}/${uniqueFileName}` +} + +const createAdvertising = async (req, res, next) => { + try { + // ✅ بررسی Authorization header + const authHeader = req.header('Authorization') + if (!authHeader) return res.status(401).json({ error: true, message: 'Access Denied' }) + + const token = authHeader.split(' ')[1] + if (!token) return res.status(401).json({ error: true, message: 'Access Denied' }) + + let decodedToken + try { + decodedToken = jwt.verify(token, process.env.APP_SECRET) + } catch (err) { + return res.status(401).json({ error: true, message: 'توکن نامعتبر است' }) + } + + const user = await UserModel.findById(decodedToken.id) + if (!user) return res.status(422).json({ error: true, message: 'شما دسترسی به این بخش ندارید' }) + + // ✅ اعتبارسنجی فرم + const errors = validationResult(req) + if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() }) + + const { + category, + title, + description, + province, + city, + neighbourhood, + address, + lat, + lng, + services, + features, + contactInfo, + mostDiscountPercentage, + showDiscount, + type + } = req.body + + if (!title || !category || !province || !city) { + return res.status(422).json({ error: true, message: 'اطلاعات ارسالی اشتباه است' }) + } + + const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) + const cityFind = await CityModel.findOne({ id: city }) + + // ✅ مدیریت خدمات و تصاویرشان + let parsedServices = [] + try { + parsedServices = services ? JSON.parse(services) : [] + } catch (err) { + return res.status(422).json({ error: true, message: 'فرمت خدمات اشتباه است' }) + } + + const servicesWithImages = [] + for (const service of parsedServices) { + const serviceImages = [] + const serviceId = service.id + const serviceFiles = req.files?.serviceImages?.[serviceId] + const imageFiles = Array.isArray(serviceFiles) ? serviceFiles : serviceFiles ? [serviceFiles] : [] + + for (const file of imageFiles) { + const imageUrl = await saveFile(file, 'services', user.user_name) + serviceImages.push(imageUrl) + service.image = imageUrl + } + servicesWithImages.push({ ...service, images: serviceImages }) + } + + // ✅ مدیریت تصاویر تبلیغ + const imageFiles = Array.isArray(req.files?.images) ? req.files.images : req.files?.images ? [req.files.images] : [] + const images = [] + for (const file of imageFiles) { + const imageUrl = await saveFile(file, 'advertising', user.user_name) + images.push(imageUrl) + } + + // ✅ مدیریت ویژگی‌ها + let parsedFeatures = [] + try { + parsedFeatures = features ? JSON.parse(features) : [] + } catch (err) { + return res.status(422).json({ error: true, message: 'فرمت ویژگی‌ها اشتباه است' }) + } + + // ✅ ایجاد رکورد جدید + const newAd = new AdvertisingModel({ + title, + category, + description, + province: provinceFind, + city: cityFind, + neighbourhood, + address, + lat, + lng, + images, + services: servicesWithImages, + features: parsedFeatures, + contactInfo, + creator_id: user._id, + mostDiscountPercentage, + showDiscount, + type + }) + + await newAd.save() + + // ✅ ذخیره اطلاعات تماس برای استفاده بعدی + if (contactInfo?.saveInfoForNextAds) { + let advertisingProfile = await AdvertisingProfileModel.findOne({ user: user._id }) + if (advertisingProfile) { + advertisingProfile.contactInfo = contactInfo + await advertisingProfile.save() + } else { + advertisingProfile = new AdvertisingProfileModel({ user: user._id, contactInfo }) + await advertisingProfile.save() + } + } + + return res.status(201).json({ + success: true, + message: 'ویترین با موفقیت ایجاد شد', + data: { id: newAd._id } + }) + } catch (error) { + next(error) + } +} +// const getAdvertisings = async (req, res, next) => { +// let previousPage = 0 // تعریف متغیر سراسری برای نگهداری شماره صفحه قبلی + +// try { +// const token = req.header('Authorization').split(' ')[1] +// if (!token) return res.status(401).send('Access Denied') +// const decodedToken = jwt.verify(token, process.env.APP_SECRET) + +// const { page = 1, limit = 10, province, city, category, search } = req.query +// const currentPage = parseInt(page) // شماره صفحه جاری + +// const filter = { +// payment_status: 'done', +// status: 'accepted' +// } +// if (province) { +// const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) +// filter.province = provinceFind +// } +// if (city) { +// const cityFind = await CityModel.findOne({ id: city }) +// filter.city = cityFind +// } +// if (category) { +// filter.category = category +// } +// if (search) { +// filter.$or = [ +// { title: { $regex: search, $options: 'i' } }, +// { category: { $regex: search, $options: 'i' } } +// ] +// } +// const options = { +// page: parseInt(page), +// limit: parseInt(limit), +// sort: { acceptedAt: -1, createdAt: -1 } // مرتب‌سازی بر اساس acceptedAt و سپس createdAt +// } +// const advertisings = await AdvertisingModel.paginate(filter, options) + +// // اگر شماره صفحه تغییر کرده بود، تعداد بازدیدها را به روز رسانی کنید +// if (currentPage !== previousPage) { +// await AdvertisingModel.updateMany( +// { _id: { $in: advertisings.docs.map(ad => ad._id) } }, +// { $inc: { viewCount: 1 } } +// ) +// previousPage = currentPage // به‌روزرسانی شماره صفحه قبلی +// } +// // دریافت لیست لایک هر ویترین و اضافه کردن آن به اطلاعات تبلیغات +// const advertisingIds = advertisings.docs.map(ad => ad._id) +// const advertisingLikes = await AdvertisingLikeModel.find({ advertisingId: { $in: advertisingIds } }) + +// const creatorIds = advertisings.docs.map(ad => ad.creator_id) +// const creators = await AdvertisingProfileModel.find({ user: { $in: creatorIds } }) +// const newAds = advertisings.docs.map(ad => { +// const creator = creators.find(user => user.user.toString() === ad.creator_id.toString()) +// const likedByUser = advertisingLikes.some(like => like.advertisingId.toString() === ad._id.toString() && like.userId.toString() === decodedToken.id) +// return { +// // فیلدهای مشخص‌شده از ad._doc +// _id: ad._doc._id, +// category: ad._doc.category, +// title: ad._doc.title, +// province: ad._doc.province, +// city: ad._doc.city, +// neighbourhood: ad._doc.neighbourhood, +// type: ad._doc.type, +// mostDiscountPercentage: ad._doc.mostDiscountPercentage, +// images: ad._doc.images, +// likedByUser, +// likesCount: ad._doc.likesCount, +// commentsCount: ad._doc.commentsCount, +// showDiscount: ad._doc.showDiscount, +// viewCount: ad._doc.viewCount, +// rate: { +// adTotalRatings: creator?.adTotalRatings, +// adAverageRating: creator?.adAverageRating +// } +// } +// }) +// res.status(200).json({ +// advertisings: newAds, +// totalPages: advertisings.totalPages, +// totalItems: advertisings.totalDocs +// }) +// } catch (error) { +// next(error) +// } +// } +const getAdvertisings = async (req, res, next) => { + let previousPage = 0 // تعریف متغیر سراسری برای نگهداری شماره صفحه قبلی + + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + + const { page = 1, limit = 10, province, city, category, search, sort } = req.query + const currentPage = parseInt(page) // شماره صفحه جاری + + const filter = { + payment_status: 'done', + status: 'accepted' + } + if (province) { + const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) + filter.province = provinceFind + } + if (city) { + const cityFind = await CityModel.findOne({ id: city }) + filter.city = cityFind + } + if (category) { + filter.category = category + } + if (search) { + filter.$or = [ + { title: { $regex: search, $options: 'i' } }, + { category: { $regex: search, $options: 'i' } } + ] + } + + // مرتب‌سازی بر اساس پارامتر sort + let sortOptions = { acceptedAt: -1, createdAt: -1 } // مرتب‌سازی پیش‌فرض + if (sort) { + const sortFields = sort.split(',') + sortFields.forEach(field => { + if (field === 'mostDiscount') { + sortOptions = { mostDiscountPercentage: -1 } + } else if (field === 'highestRating') { + sortOptions = { 'rate.adAverageRating': -1 } + } + }) + } + + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: sortOptions // استفاده از مرتب‌سازی تنظیم‌شده + } + const advertisings = await AdvertisingModel.paginate(filter, options) + + // اگر شماره صفحه تغییر کرده بود، تعداد بازدیدها را به روز رسانی کنید + if (currentPage !== previousPage) { + await AdvertisingModel.updateMany( + { _id: { $in: advertisings.docs.map(ad => ad._id) } }, + { $inc: { viewCount: 1 } } + ) + previousPage = currentPage // به‌روزرسانی شماره صفحه قبلی + } + // دریافت لیست لایک هر ویترین و اضافه کردن آن به اطلاعات تبلیغات + const advertisingIds = advertisings.docs.map(ad => ad._id) + const advertisingLikes = await AdvertisingLikeModel.find({ advertisingId: { $in: advertisingIds } }) + + const creatorIds = advertisings.docs.map(ad => ad.creator_id) + const creators = await AdvertisingProfileModel.find({ user: { $in: creatorIds } }) + const newAds = advertisings.docs.map(ad => { + const creator = creators.find(user => user.user.toString() === ad.creator_id.toString()) + const likedByUser = advertisingLikes.some(like => like.advertisingId.toString() === ad._id.toString() && like.userId.toString() === decodedToken.id) + return { + // فیلدهای مشخص‌شده از ad._doc + _id: ad._doc._id, + category: ad._doc.category, + title: ad._doc.title, + province: ad._doc.province, + city: ad._doc.city, + neighbourhood: ad._doc.neighbourhood, + type: ad._doc.type, + mostDiscountPercentage: ad._doc.mostDiscountPercentage, + images: ad._doc.images, + likedByUser, + likesCount: ad._doc.likesCount, + commentsCount: ad._doc.commentsCount, + showDiscount: ad._doc.showDiscount, + viewCount: ad._doc.viewCount, + rate: { + adTotalRatings: creator?.adTotalRatings, + adAverageRating: creator?.adAverageRating + } + } + }) + res.status(200).json({ + advertisings: newAds, + totalPages: advertisings.totalPages, + totalItems: advertisings.totalDocs + }) + } catch (error) { + next(error) + } +} + +const getAdvertisingsWeb = async (req, res, next) => { + let previousPage = 0 + let userId = null + + try { + const token = req.header('Authorization') + if (token) { + try { + const decodedToken = jwt.verify(token.split(' ')[1], process.env.APP_SECRET) + userId = decodedToken.id + } catch (err) { + console.warn('Invalid token:', err.message) + } + } + + const { page = 1, limit = 10, province, city, category, search, sort } = req.query + const currentPage = parseInt(page) + + const filter = { + // payment_status: 'done', + status: 'accepted' + } + if (province) { + const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) + filter.province = provinceFind + } + if (city) { + const cityFind = await CityModel.findOne({ id: city }) + filter.city = cityFind + } + if (category) { + filter.category = category + } + if (search) { + filter.$or = [ + { title: { $regex: search, $options: 'i' } }, + { category: { $regex: search, $options: 'i' } } + ] + } + + let sortOptions = { acceptedAt: -1, createdAt: -1 } + if (sort) { + const sortFields = sort.split(',') + sortFields.forEach(field => { + if (field === 'mostDiscount') { + sortOptions = { mostDiscountPercentage: -1 } + } else if (field === 'highestRating') { + sortOptions = { 'rate.adAverageRating': -1 } + } + }) + } + + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: sortOptions + } + const advertisings = await AdvertisingModel.paginate(filter, options) + + if (currentPage !== previousPage) { + await AdvertisingModel.updateMany( + { _id: { $in: advertisings.docs.map(ad => ad._id) } }, + { $inc: { viewCount: 1 } } + ) + previousPage = currentPage + } + + const advertisingIds = advertisings.docs.map(ad => ad._id) + const creatorIds = advertisings.docs.map(ad => ad.creator_id) + const creators = await AdvertisingProfileModel.find({ user: { $in: creatorIds } }) + + let advertisingLikes = [] + if (userId) { + advertisingLikes = await AdvertisingLikeModel.find({ advertisingId: { $in: advertisingIds }, userId }) + } + + const newAds = advertisings.docs.map(ad => { + const creator = creators.find(user => user.user.toString() === ad.creator_id.toString()) + const likedByUser = userId ? advertisingLikes.some(like => like.advertisingId.toString() === ad._id.toString()) : false + + return { + _id: ad._doc._id, + category: ad._doc.category, + title: ad._doc.title, + province: ad._doc.province, + city: ad._doc.city, + neighbourhood: ad._doc.neighbourhood, + type: ad._doc.type, + mostDiscountPercentage: ad._doc.mostDiscountPercentage, + images: ad._doc.images, + likedByUser, + likesCount: ad._doc.likesCount, + commentsCount: ad._doc.commentsCount, + showDiscount: ad._doc.showDiscount, + viewCount: ad._doc.viewCount, + rate: { + adTotalRatings: creator?.adTotalRatings, + adAverageRating: creator?.adAverageRating + } + } + }) + + res.status(200).json({ + advertisings: newAds, + totalPages: advertisings.totalPages, + totalItems: advertisings.totalDocs + }) + } catch (error) { + next(error) + } +} + +const getSingleAdvertising = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const advertisingId = req.params.advertisingId + const advertising = await AdvertisingModel.findById(advertisingId) + .populate('creator_id', '_id user_name first_name last_name') + + if (!advertising) { + return res.status(404).json({ message: 'ویترین مورد نظر یافت نشد' }) + } + + // دریافت تعداد لایک‌ها و بررسی اینکه آیا کاربر ویترین را لایک کرده است یا خیر + const likesCount = await AdvertisingLikeModel.countDocuments({ advertisingId }) + const likedByUser = await AdvertisingLikeModel.findOne({ advertisingId, userId }) + + // دریافت تعداد کامنت‌ها + const commentsCount = await AdvertisingComment.countDocuments({ advertisingId, status: 'accepted' }) + const creator = await AdvertisingProfileModel.findOne({ user: advertising.creator_id._id }) + + // اضافه کردن تعداد لایک‌ها، تعداد کامنت‌ها و وضعیت لایک به تبلیغ + const advertisingData = { + ...advertising._doc, + likesCount, + likedByUser: !!likedByUser, + commentsCount, + creatorId: creator?._id + } + + res.status(200).json({ + advertising: advertisingData, + rate: { + adTotalRatings: creator?.adTotalRatings, + adAverageRating: creator?.adAverageRating + } + }) + } catch (error) { + next(error) + } +} +const getSingleAdvertisingWeb = async (req, res, next) => { + try { + let userId = null + let likedByUser = false + + // بررسی وجود توکن + const authHeader = req.header('Authorization') + if (authHeader) { + const tokenParts = authHeader.split(' ') + if (tokenParts.length === 2) { + try { + const decodedToken = jwt.verify(tokenParts[1], process.env.APP_SECRET) + userId = decodedToken.id + } catch (err) { + console.error('Invalid Token:', err.message) + } + } + } + + const advertisingId = req.params.advertisingId + const advertising = await AdvertisingModel.findById(advertisingId) + .populate('creator_id', '_id user_name first_name last_name') + + if (!advertising) { + return res.status(404).json({ message: 'ویترین مورد نظر یافت نشد' }) + } + + // دریافت تعداد لایک‌ها + const likesCount = await AdvertisingLikeModel.countDocuments({ advertisingId }) + + // دریافت تعداد کامنت‌ها + const commentsCount = await AdvertisingComment.countDocuments({ advertisingId, status: 'accepted' }) + + // دریافت اطلاعات سازنده تبلیغ + const creator = await AdvertisingProfileModel.findOne({ user: advertising.creator_id._id }) + + // اگر کاربر احراز هویت شده باشد، وضعیت لایک‌شدن توسط او بررسی می‌شود + if (userId) { + likedByUser = !!(await AdvertisingLikeModel.findOne({ advertisingId, userId })) + } + + // آماده‌سازی داده‌های تبلیغ + const advertisingData = { + ...advertising._doc, + likesCount, + likedByUser, + commentsCount, + creatorId: creator?._id + } + + res.status(200).json({ + advertising: advertisingData, + rate: { + adTotalRatings: creator?.adTotalRatings, + adAverageRating: creator?.adAverageRating + } + }) + } catch (error) { + next(error) + } +} + +const getAdvertisingTypes = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // const decodedToken = jwt.verify(token, process.env.APP_SECRET) + // const userId = decodedToken.id + + // const user = await UserModel.findById(userId) + // if (!user) { + // return res.status(422).json({ + // error: true, + // message: 'کاربر یافت نشد' + // }) + // } + // درخواست انواع تبلیغات از دیتابیس + // let projectTypes = await AdvertisingTypeModel.find({}, 'name price') + const advertisingTypes = await AdvertisingTypeModel.find({}, 'name price') + + // بررسی برای مواردی مانند پیدا نشدن انواع تبلیغات + if (!advertisingTypes) { + return res.status(404).json({ message: 'انواع تبلیغات یافت نشد.' }) + } + // اگر کاربر درخواست رایگان روزانه نداشته باشد، نوع تبلیغات رایگان را حذف کنید + // if (user.daily_free_request <= 0) { + // advertisingTypes = advertisingTypes.filter(projectType => projectType.name !== 'free') + // } + // ارسال انواع تبلیغات به کاربر + res.status(200).json({ advertisingTypes }) + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error('Error in getAdvertisingTypes:', error) + res.status(500).json({ message: 'خطا در دریافت انواع تبلیغات.' }) + } +} +const getAdvertisingCategory = async (req, res, next) => { + try { + // const token = req.header('Authorization').split(' ')[1] + // if (!token) return res.status(401).send('Access Denied') + // const decodedToken = jwt.verify(token, process.env.APP_SECRET) + // const userId = decodedToken.id + + // const user = await UserModel.findById(userId) + // if (!user) { + // return res.status(422).json({ + // error: true, + // message: 'کاربر یافت نشد' + // }) + // } + // let projectTypes = await AdvertisingTypeModel.find({}, 'name price') + const categories = await AdvertisingCategoryModel.find({}) + + // بررسی برای مواردی مانند پیدا نشدن انواع پروژه + if (!categories) { + return res.status(404).json({ message: 'دسته بندی یافت نشد.' }) + } + // if (user.daily_free_request <= 0) { + // categories = categories.filter(projectType => projectType.name !== 'free') + // } + // ارسال انواع پروژه به کاربر + res.status(200).json({ categories }) + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error('Error in getAdvertisingTypes:', error) + res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' }) + } +} + +const getAdvertisingFeatures = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // const decodedToken = jwt.verify(token, process.env.APP_SECRET) + // const userId = decodedToken.id + + // const user = await UserModel.findById(userId) + // if (!user) { + // return res.status(422).json({ + // error: true, + // message: 'کاربر یافت نشد' + // }) + // } + // let projectTypes = await AdvertisingTypeModel.find({}, 'name price') + const features = await AdvertisingFeaturesModel.find({}) + + // بررسی برای مواردی مانند پیدا نشدن امکانات + if (!features) { + return res.status(404).json({ message: 'امکانات یافت نشد.' }) + } + // if (user.daily_free_request <= 0) { + // features = features.filter(projectType => projectType.name !== 'free') + // } + // ارسال امکانات به کاربر + res.status(200).json({ features }) + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error('Error in getAdvertisingTypes:', error) + res.status(500).json({ message: 'خطا در دریافت امکانات.' }) + } +} +const toggleLike = async (req, res, next) => { + try { + const { advertisingId } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + // بررسی وجود تبلیغات با استفاده از advertisingId + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + return res.status(404).json({ message: 'ویترین مورد نظر یافت نشد' }) + } + // بررسی وضعیت لایک کردن توسط کاربر + const isLiked = await AdvertisingLikeModel.findOne({ advertisingId, userId }) + if (isLiked) { + // حذف لایک + await AdvertisingLikeModel.findOneAndDelete({ advertisingId, userId }) + // کاهش تعداد لایک‌ها در تبلیغات + advertising.likesCount -= 1 + await advertising.save() + return res.status(200).json({ message: 'لایک با موفقیت پاک شد' }) + } else { + // اضافه کردن لایک + await AdvertisingLikeModel.create({ advertisingId, userId }) + // افزایش تعداد لایک‌ها در تبلیغات + advertising.likesCount += 1 + await advertising.save() + return res.status(201).json({ message: 'ویترین با موفقیت لایک شد' }) + } + } catch (error) { + next(error) + } +} +const addComment = async (req, res, next) => { + try { + const { advertisingId, text } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + // eslint-disable-next-line no-unused-vars + const user = await UserModel.findById(decodedToken.id) + // if (user.is_verified !== 'verified') { + // return res.status(422).json({ + // error: true, + // message: 'مدارک شما تایید نشده است' + // }) + // } + const newComment = new AdvertisingComment({ + advertisingId, + userId, + text + }) + + await newComment.save() + // افزایش تعداد کامنت‌های تبلیغ + // await AdvertisingModel.findByIdAndUpdate(advertisingId, { $inc: { commentsCount: 1 } }) + + res.status(201).json({ message: 'کامنت با موفقیت اضافه شد', comment: newComment }) + } catch (error) { + next(error) + } +} +const getComments = async (req, res, next) => { + try { + const { advertisingId, page = 1, limit = 10 } = req.query + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { createdAt: -1 }, + populate: [{ path: 'userId', select: '_id profile_image user_type user_name first_name last_name is_verified' }] + } + + const comments = await AdvertisingComment.paginate({ advertisingId, status: 'accepted' }, options) + res.status(200).json({ + comments: comments.docs, + totalPages: comments.totalPages, + totalItems: comments.totalDocs + }) + } catch (error) { + next(error) + } +} +const rateAdvertising = async (req, res, next) => { + try { + const { advertisingId, rating } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + if (rating < 1 || rating > 5) { + return res.status(400).json({ message: 'امتیاز باید بین 1 تا 5 باشد' }) + } + + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + return res.status(404).json({ message: 'ویترین مورد نظر یافت نشد' }) + } + + const existingRating = await AdvertisingRatingModel.findOne({ advertisingId, userId }) + if (existingRating) { + return res.status(400).json({ message: 'شما قبلا برای این ویترین امتیاز ثبت کرده‌اید' }) + } else { + const newRating = new AdvertisingRatingModel({ + advertisingId, + userId, + rating + }) + await newRating.save() + } + + // به‌روزرسانی امتیازات کلی کاربر + const advertisingProfile = await AdvertisingProfileModel.findOne({ user: advertising.creator_id }) + if (advertisingProfile) { + const totalUserRatings = await AdvertisingRatingModel.aggregate([ + { + $lookup: { + from: 'advertisings', + localField: 'advertisingId', + foreignField: '_id', + as: 'advertising' + } + }, + { $unwind: '$advertising' }, + { $match: { 'advertising.creator_id': advertising.creator_id } }, + { $group: { _id: null, total: { $sum: '$rating' }, count: { $sum: 1 } } } + ]) + + if (totalUserRatings.length > 0) { + const { total, count } = totalUserRatings[0] + advertisingProfile.adTotalRatings = total + advertisingProfile.adRatingsCount = count + advertisingProfile.adAverageRating = (total / count).toFixed(1) + } else { + advertisingProfile.adTotalRatings = 0 + advertisingProfile.adRatingsCount = 0 + advertisingProfile.adAverageRating = 0 + } + + await advertisingProfile.save() + } else { + // ایجاد پروفایل تبلیغاتی جدید در صورت عدم وجود + const newAdvertisingProfile = new AdvertisingProfileModel({ + user: advertising.creator_id, + adTotalRatings: rating, + adRatingsCount: 1, + adAverageRating: rating.toFixed(1) + }) + await newAdvertisingProfile.save() + } + + res.status(200).json({ message: 'امتیاز با موفقیت ثبت شد' }) + } catch (error) { + next(error) + } +} +const getUserAdvertisings = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { page = 1, limit = 10, status, search } = req.query + + const filter = { + creator_id: userId + } + + if (status) { + filter.status = status + } + if (search) { + filter.$or = [ + { title: { $regex: search, $options: 'i' } }, + { category: { $regex: search, $options: 'i' } } + ] + } + + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { updatedAt: -1 } + } + + const advertisings = await AdvertisingModel.paginate(filter, options) + + // دریافت لیست لایک هر ویترین و اضافه کردن آن به اطلاعات تبلیغات + const advertisingIds = advertisings.docs.map(ad => ad._id) + const advertisingLikes = await AdvertisingLikeModel.find({ advertisingId: { $in: advertisingIds } }) + const creator = await AdvertisingProfileModel.findOne({ user: userId }) + + const newAds = advertisings.docs.map(ad => { + const likedByUser = advertisingLikes.some(like => like.advertisingId.toString() === ad._id.toString() && like.userId.toString() === decodedToken.id) + let remainingTime = null + if (ad.status === 'accepted' && ad.acceptedAt) { + const expirationDate = new Date(ad.acceptedAt) + expirationDate.setDate(expirationDate.getDate() + 15) + const currentDate = new Date() + const diffMilliseconds = expirationDate - currentDate + const diffDays = Math.floor(diffMilliseconds / (1000 * 60 * 60 * 24)) + const diffHours = Math.floor((diffMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) + remainingTime = `${diffDays} روز و ${diffHours} ساعت` + } + return { + _id: ad._doc._id, + category: ad._doc.category, + title: ad._doc.title, + province: ad._doc.province, + city: ad._doc.city, + neighbourhood: ad._doc.neighbourhood, + type: ad._doc.type, + mostDiscountPercentage: ad._doc.mostDiscountPercentage, + images: ad._doc.images, + likedByUser, + likesCount: ad._doc.likesCount, + commentsCount: ad._doc.commentsCount, + status: ad._doc.status, + viewCount: ad._doc.viewCount, + remainingTime, + rate: { + adTotalRatings: creator?.adTotalRatings, + adAverageRating: creator?.adAverageRating + } + } + }) + + res.status(200).json({ + advertisings: newAds, + totalPages: advertisings.totalPages, + totalItems: advertisings.totalDocs + }) + } catch (error) { + next(error) + } +} +const getUserSingleAdvertising = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const user = await UserModel.findById(userId) + if (!user) { + return res.status(422).json({ + error: true, + message: 'شما دسترسی به این بخش ندارید' + }) + } + const advertisingId = req.params.advertisingId + const advertising = await AdvertisingModel.findById(advertisingId) + .populate('creator_id', '_id user_name first_name last_name') + + if (!advertising) { + return res.status(404).json({ message: 'ویترین مورد نظر یافت نشد' }) + } + + // دریافت تعداد لایک‌ها و بررسی اینکه آیا کاربر ویترین را لایک کرده است یا خیر + const likesCount = await AdvertisingLikeModel.countDocuments({ advertisingId }) + const likedByUser = await AdvertisingLikeModel.findOne({ advertisingId, userId }) + + // دریافت تعداد کامنت‌ها + const commentsCount = await AdvertisingComment.countDocuments({ advertisingId, status: 'accepted' }) + const creator = await AdvertisingProfileModel.findOne({ user: advertising.creator_id._id }) + + // اضافه کردن تعداد لایک‌ها، تعداد کامنت‌ها و وضعیت لایک به تبلیغ + const advertisingData = { + ...advertising._doc, + likesCount, + likedByUser: !!likedByUser, + commentsCount, + creatorId: creator?._id + + } + + res.status(200).json({ + advertising: advertisingData, + rate: { + adTotalRatings: creator?.adTotalRatings, + adAverageRating: creator?.adAverageRating + } + }) + } catch (error) { + next(error) + } +} +const editAdvertising = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(422).json({ + error: true, + message: 'شما دسترسی به این بخش ندارید' + }) + } + // if (user.is_verified !== 'verified') { + // return res.status(422).json({ + // error: true, + // message: 'مدارک شما تایید نشده است' + // }) + // } + + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + + const { id } = req.params + const { + category, + title, + description, + province, + city, + neighbourhood, + address, + lat, + lng, + services, + features, + contactInfo, + mostDiscountPercentage, + showDiscount, + type + } = req.body + + if (!title || !category || !province || !city) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const advertising = await AdvertisingModel.findOne({ + _id: id, + creator_id: user._id, + status: { $in: ['pre_payment', 'paid', 'rejected', 'expired'] } + }) + + if (!advertising) { + return res.status(404).json({ + error: true, + message: 'تبلیغ مورد نظر یافت نشد یا شما اجازه ویرایش آن را ندارید' + }) + } + + const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) + const cityFind = await CityModel.findOne({ id: city }) + + // مدیریت تصاویر برای خدمات + const servicesWithImages = [] + const parsedServices = JSON.parse(services) + if (parsedServices && parsedServices.length > 0) { + for (const service of parsedServices) { + if (typeof service.image === 'string' && service.image.startsWith('/services/')) { + servicesWithImages.push(service) + } else { + const serviceImages = [] + const serviceId = service.id + if (req.files && req.files.serviceImages && req.files.serviceImages[serviceId]) { + const imageFiles = Array.isArray(req.files.serviceImages[serviceId]) ? req.files.serviceImages[serviceId] : [req.files.serviceImages[serviceId]] + const uploadDir = path.join(__dirname, '../../../../storage/services') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + for (const imageFile of imageFiles) { + const uniqueFileName = `${user.user_name}-${Date.now()}${Math.random().toString().slice(2, 11)}${path.extname(imageFile.name)}` + const filePath = path.join(uploadDir, uniqueFileName) + await fs.move(imageFile.path, filePath) + const imageUrl = `/services/${uniqueFileName}` + serviceImages.push(imageUrl) + service.image = imageUrl + } + } + servicesWithImages.push({ ...service, image: serviceImages[0] }) + } + } + } + // مدیریت تصاویر + const images = [] + + // اضافه کردن تصاویر موجود + if (Array.isArray(req.body.existingImages)) { + req.body.existingImages.forEach(image => { + if (typeof image === 'string' && image.startsWith('/advertising/')) { + images.push(image) + } + }) + } + + // اضافه کردن تصاویر جدید + if (req.files && req.files.images) { + const imageFiles = Array.isArray(req.files.images) ? req.files.images : [req.files.images] + const uploadDir = path.join(__dirname, '../../../../storage/advertising') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + for (const imageFile of imageFiles) { + // بررسی فرمت تصویر + if (imageFile && typeof imageFile === 'object' && imageFile.path) { + const uniqueFileName = `${user.user_name}-${Date.now()}${Math.random().toString().slice(2, 11)}${path.extname(imageFile.name)}` + const filePath = path.join(uploadDir, uniqueFileName) + await fs.move(imageFile.path, filePath) + const imageUrl = `/advertising/${uniqueFileName}` + images.push(imageUrl) + } + } + } + const parsedFeatures = JSON.parse(features) + + advertising.title = title + advertising.category = category + advertising.description = description + advertising.province = provinceFind + advertising.city = cityFind + advertising.neighbourhood = neighbourhood + advertising.address = address + advertising.lat = lat + advertising.lng = lng + advertising.images = images + advertising.services = servicesWithImages + advertising.features = parsedFeatures + advertising.contactInfo = contactInfo + advertising.mostDiscountPercentage = mostDiscountPercentage + advertising.showDiscount = showDiscount + advertising.type = type + + await advertising.save() + + if (contactInfo && contactInfo.saveInfoForNextAds) { + user.contactInfo = contactInfo + await user.save() + } + res.status(200).json({ + message: 'ویترین با موفقیت ویرایش شد', + id: advertising._id + }) + } catch (error) { + next(error) + } +} +const getUserAdvertisingProfile = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const vitrineId = req.query.vitrineId + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(422).json({ + error: true, + message: 'شما دسترسی به این بخش ندارید' + }) + } + // if (user.is_verified !== 'verified') { + // return res.status(422).json({ + // error: true, + // message: 'مدارک شما تایید نشده است' + // }) + // } + + // دریافت اطلاعات پروفایل تبلیغاتی کاربر + const advertisingProfile = await AdvertisingProfileModel.findById(vitrineId) + if (!advertisingProfile) { + return res.status(404).json({ + error: true, + message: 'پروفایل تبلیغاتی یافت نشد' + }) + } + + // دریافت تبلیغات‌های کاربر + const userAds = await AdvertisingModel.find({ creator_id: advertisingProfile?.user }) + + // جمع‌آوری اطلاعات از تبلیغات‌ها + let allImages = [] + let allServices = [] + let allFeatures = [] + let totalCommentsCount = 0 + let totalLikesCount = 0 + + for (const ad of userAds) { + allImages = allImages.concat(ad.images) + allServices = allServices.concat(ad.services) + allFeatures = allFeatures.concat(ad.features) + totalCommentsCount += ad.commentsCount + totalLikesCount += ad.likesCount + } + + // حذف آیتم‌های null و تکراری از allFeatures + const uniqueFeatures = [] + const featureTitles = new Set() + for (const feature of allFeatures) { + if (feature && !featureTitles.has(feature.title)) { + uniqueFeatures.push(feature) + featureTitles.add(feature.title) + } + } + + // آماده‌سازی اطلاعات نهایی + const profileDetails = { + _id: advertisingProfile._id, + profile_image: advertisingProfile.profile_image, + vitrine_name: advertisingProfile.vitrine_name, + category: advertisingProfile.category, + about_us: advertisingProfile.about_us, + province: advertisingProfile.province, + city: advertisingProfile.city, + lat: advertisingProfile.lat, + lng: advertisingProfile.lng, + neighbourhood: advertisingProfile.neighbourhood, + adTotalRatings: advertisingProfile.adTotalRatings, + adRatingsCount: advertisingProfile.adRatingsCount, + adAverageRating: advertisingProfile.adAverageRating, + contactInfo: advertisingProfile.contactInfo, + address: advertisingProfile.address, + allImages: allImages?.reverse(), + allServices, + allFeatures: uniqueFeatures, + totalCommentsCount, + totalLikesCount, + is_self: !!(advertisingProfile && advertisingProfile?.user == decodedToken.id) + } + + // ارسال پاسخ به کاربر + res.status(200).json({ profileDetails }) + } catch (error) { + next(error) + } +} +const getUserAdvertisingProfileWeb = async (req, res, next) => { + try { + let userId = null + let isSelf = false + + // بررسی توکن (در صورت وجود) + const authHeader = req.header('Authorization') + if (authHeader) { + const tokenParts = authHeader.split(' ') + if (tokenParts.length === 2) { + try { + const decodedToken = jwt.verify(tokenParts[1], process.env.APP_SECRET) + userId = decodedToken.id + } catch (err) { + console.error('Invalid Token:', err.message) + } + } + } + + const vitrineId = req.query.vitrineId + console.log(vitrineId) + + // دریافت اطلاعات پروفایل تبلیغاتی کاربر + const advertisingProfile = await AdvertisingProfileModel.findById(vitrineId) + if (!advertisingProfile) { + return res.status(404).json({ + error: true, + message: 'پروفایل تبلیغاتی یافت نشد' + }) + } + + // دریافت تبلیغات‌های کاربر + const userAds = await AdvertisingModel.find({ creator_id: advertisingProfile?.user }) + + // جمع‌آوری اطلاعات از تبلیغات‌ها + let allImages = [] + let allServices = [] + let allFeatures = [] + let totalCommentsCount = 0 + let totalLikesCount = 0 + + for (const ad of userAds) { + allImages = allImages.concat(ad.images) + allServices = allServices.concat(ad.services) + allFeatures = allFeatures.concat(ad.features) + totalCommentsCount += ad.commentsCount + totalLikesCount += ad.likesCount + } + + // حذف آیتم‌های null و تکراری از allFeatures + const uniqueFeatures = [] + const featureTitles = new Set() + for (const feature of allFeatures) { + if (feature && !featureTitles.has(feature.title)) { + uniqueFeatures.push(feature) + featureTitles.add(feature.title) + } + } + + // بررسی اینکه کاربر خودش صاحب این ویترین است یا نه + if (userId) { + isSelf = advertisingProfile?.user == userId + } + + // آماده‌سازی اطلاعات نهایی + const profileDetails = { + _id: advertisingProfile._id, + profile_image: advertisingProfile.profile_image, + vitrine_name: advertisingProfile.vitrine_name, + category: advertisingProfile.category, + about_us: advertisingProfile.about_us, + province: advertisingProfile.province, + city: advertisingProfile.city, + lat: advertisingProfile.lat, + lng: advertisingProfile.lng, + neighbourhood: advertisingProfile.neighbourhood, + adTotalRatings: advertisingProfile.adTotalRatings, + adRatingsCount: advertisingProfile.adRatingsCount, + adAverageRating: advertisingProfile.adAverageRating, + contactInfo: advertisingProfile.contactInfo, + address: advertisingProfile.address, + allImages: allImages?.reverse(), + allServices, + allFeatures: uniqueFeatures, + totalCommentsCount, + totalLikesCount, + is_self: isSelf + } + + // ارسال پاسخ به کاربر + res.status(200).json({ profileDetails }) + } catch (error) { + next(error) + } +} + +const updateUserAdvertisingProfile = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(422).json({ + error: true, + message: 'شما دسترسی به این بخش ندارید' + }) + } + + const advertisingProfile = await AdvertisingProfileModel.findOne({ user: decodedToken.id }) + if (!advertisingProfile) { + return res.status(404).json({ + error: true, + message: 'پروفایل تبلیغاتی یافت نشد' + }) + } + + if (advertisingProfile.user.toString() !== decodedToken.id) { + return res.status(403).json({ + error: true, + message: 'شما اجازه ویرایش این پروفایل را ندارید' + }) + } + + const { profile_image } = req.files + const { + // profile_image, + vitrine_name, + category, + about_us, + province, + city, + lat, + lng, + address, + neighbourhood, + contactInfo + } = req.body + + const updateFields = {} + const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) + const cityFind = await CityModel.findOne({ id: city }) + // if (profile_image !== undefined && profile_image !== null && !profile_image.startsWith('/profiles/')) { + if (profile_image !== undefined && profile_image !== null) { + const uploadDir = path.join(__dirname, '../../../../storage/profiles') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + const uniqueFileName = `${advertisingProfile?.vitrine_name}-${Date.now()}${path.extname(profile_image.name)}` + const filePath = path.join(uploadDir, uniqueFileName) + await fs.move(profile_image.path, filePath) + updateFields.profile_image = `/profiles/${uniqueFileName}` + } + if (vitrine_name !== undefined) updateFields.vitrine_name = vitrine_name + if (category !== undefined) updateFields.category = category + if (about_us !== undefined) updateFields.about_us = about_us + if (province !== undefined) updateFields.province = provinceFind + if (city !== undefined) updateFields.city = cityFind + if (lat !== undefined) updateFields.lat = lat + if (lng !== undefined) updateFields.lng = lng + if (address !== undefined) updateFields.address = address + if (neighbourhood !== undefined) updateFields.neighbourhood = neighbourhood + if (contactInfo !== undefined) updateFields.contactInfo = contactInfo + + const updatedProfile = await AdvertisingProfileModel.findByIdAndUpdate( + advertisingProfile._id, + { $set: updateFields }, + { new: true } + ) + + res.status(200).json({ + success: true, + message: 'پروفایل با موفقیت به‌روزرسانی شد', + updatedProfile + }) + } catch (error) { + next(error) + } +} + +module.exports = { + createAdvertisingValidationRules, + createAdvertising, + getAdvertisingTypes, + getAdvertisingCategory, + getSingleAdvertising, + getAdvertisingFeatures, + getAdvertisings, + toggleLike, + addComment, + getComments, + rateAdvertising, + getUserAdvertisings, + editAdvertising, + getUserSingleAdvertising, + getUserAdvertisingProfile, + updateUserAdvertisingProfile, + getAdvertisingsWeb, + getSingleAdvertisingWeb, + getUserAdvertisingProfileWeb +} diff --git a/public/modstagram-back/controllers/application/citysController.js b/public/modstagram-back/controllers/application/citysController.js new file mode 100644 index 0000000..0e9e98d --- /dev/null +++ b/public/modstagram-back/controllers/application/citysController.js @@ -0,0 +1,16 @@ +const { CityModel } = require('../../models/StateCity') +const getCities = async (req, res, next) => { + try { + const { id } = req.params + const cities = await CityModel.find({ province_id: id }) + + res.status(200).json({ + cities + }) + } catch (err) { + res.status(500).send('Internal Server Error') + } +} +module.exports = { + getCities +} diff --git a/public/modstagram-back/controllers/application/expertise/expertiseController.js b/public/modstagram-back/controllers/application/expertise/expertiseController.js new file mode 100644 index 0000000..b4cf48d --- /dev/null +++ b/public/modstagram-back/controllers/application/expertise/expertiseController.js @@ -0,0 +1,13 @@ +/* eslint-disable camelcase */ +const ExpertiseModel = require('../../../models/ExpertiseModel') +const getExpertise = async (req, res, next) => { + try { + const expertises = await ExpertiseModel.find().select('expertise sub_expertise') + res.json({ expertises }) + } catch (error) { + next(error) + } +} +module.exports = { + getExpertise +} diff --git a/public/modstagram-back/controllers/application/financial/financialController.js b/public/modstagram-back/controllers/application/financial/financialController.js new file mode 100644 index 0000000..4e60769 --- /dev/null +++ b/public/modstagram-back/controllers/application/financial/financialController.js @@ -0,0 +1,65 @@ +const jwt = require('jsonwebtoken') +const PaymentModel = require('../../../models/PaymentModel') +const ProjectModel = require('../../../models/ProjectModel') +const moment = require('moment-jalaali') + +const getFinancial = async (req, res) => { + try { + // Extract user ID from JWT token + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const options = { + page: req.query.page || 1, // صفحه پیش‌فرض ۱ + limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه + sort: { createdAt: -1 } + } + // Find all payments associated with the user + const financial = await PaymentModel.paginate( + { user_id: userId }, // فیلتر + options // گزینه‌های پیجینیشن + ) + // Prepare the data to be sent back + const userPayments = await Promise.all(financial.docs.map(async (payment) => { + // Find the project associated with the payment + const project = await ProjectModel.findById(payment.project_id) + + if (!project) { + return null + } + // استفاده از کتابخانه moment-jalaali برای تبدیل تاریخ و زمان به شمسی + const shamsiDate = moment(payment.createdAt).format('jYYYY-jMM-jDD') + const shamsiTime = moment(payment.createdAt).format('HH:mm') + + // Extract the required information + const userPayment = { + _id: payment._id, + project_title: project.title, + project_id: project._id, + payment_date: shamsiDate, // Format date as YYYY-MM-DD + payment_time: shamsiTime, + iban: project.creator_id ? project.creator_id.iban : null, // Check if creator_id exists before accessing iban + amount: payment.amount, + payment_status: payment.status + } + + return userPayment + })) + + // Filter out null values + const validUserPayments = userPayments.filter(payment => payment !== null) + + // Send the payments back to the client + res.status(200).json({ + financial: financial, + totalPages: financial.totalPages, // ارسال تعداد کل صفحات + totalItems: financial.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} + +module.exports = { getFinancial } diff --git a/public/modstagram-back/controllers/application/login/changePasswordController.js b/public/modstagram-back/controllers/application/login/changePasswordController.js new file mode 100644 index 0000000..39faaaf --- /dev/null +++ b/public/modstagram-back/controllers/application/login/changePasswordController.js @@ -0,0 +1,77 @@ +/* eslint-disable camelcase */ +const bcrypt = require('bcryptjs') +const { check, validationResult } = require('express-validator') + +const jwt = require('jsonwebtoken') +const UserModel = require('../../../models/UserModel') + +const changePasswordValidationRules = () => { + return [ + check('new_password') + .notEmpty().withMessage('رمز عبور نمی‌تواند خالی باشد') + .isLength({ min: 8, max: 25 }).withMessage('رمز عبور نباید کوتاه تر از 8 کاراکتر باشد') + .matches(/^(?=.*[a-zA-Zآ-ی])(?=.*\d).{8,}$/u).withMessage('رمز عبور باید شامل حروف و اعداد باشد') + ] +} +const changePasswordUser = async (req, res, next) => { + try { + const { new_password } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + // اعتبارسنجی ورودی ها + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + + // یافتن کاربر با شماره موبایل + const user = await UserModel.findById(userId) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + // هش کردن پسورد جدید و ذخیره در دیتابیس + const hashedPassword = await bcrypt.hash(new_password, 10) + user.password = hashedPassword + await user.save() + + return res.json({ + message: 'کلمه عبور با موفقیت ذخیره شد' + }) + } catch (error) { + next(error) + } +} + +const editChangePasswordUser = async (req, res, next) => { + try { + const { mobile, new_password } = req.body + const user = await UserModel.findOne({ mobile }) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + // هش کردن پسورد جدید و ذخیره در دیتابیس + const hashedPassword = await bcrypt.hash(new_password, 10) + user.password = hashedPassword + await user.save() + + return res.json({ + message: 'کلمه عبور با موفقیت تغییر یافت' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + changePasswordUser, changePasswordValidationRules, editChangePasswordUser +} diff --git a/public/modstagram-back/controllers/application/login/loginController.js b/public/modstagram-back/controllers/application/login/loginController.js new file mode 100644 index 0000000..27ad62f --- /dev/null +++ b/public/modstagram-back/controllers/application/login/loginController.js @@ -0,0 +1,87 @@ +const UserModel = require('../../../models/UserModel') +const { check, validationResult } = require('express-validator') +const { default: axios } = require('axios') +const loginValidationRules = () => { + return [ + check('mobile') + .notEmpty().withMessage('شماره موبایل نمی‌تواند خالی باشد') + .isLength({ min: 11, max: 11 }).withMessage('شماره موبایل باید دقیقاً 11 رقم باشد') + .matches(/^09[0-9]{9}$/).withMessage('فرمت شماره موبایل صحیح نیست') + ] +} + +const loginUser = async (req, res, next) => { + try { + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + + const { mobile } = req.body + if (!mobile) { + return res.status(422).json({ + error: true, + message: 'شماره موبایل نمی‌تواند خالی باشد' + }) + } + + // const existingUser = await UserModel.findOne({ mobile }) + // if (!existingUser) { + // return res.status(422).json({ error: true, message: 'کاربری با این شماره موبایل یافت نشد' }) + // } + function generateOTP () { + return Math.floor(100000 + Math.random() * 900000) + } + + const otp = generateOTP() + // eslint-disable-next-line no-unused-vars + const user = await UserModel.findOneAndUpdate( + { mobile }, + { $set: { mobile, otp } }, + { upsert: true, new: true, lean: true } + ) + // زمانبندی تنظیم مقدار otp به null پس از 10 دقیقه + setTimeout(() => { + UserModel.findOneAndUpdate({ mobile }, { $set: { otp: null } }, { new: true }) + .then(() => {}) + .catch(error => console.error('Error setting OTP to null:', error)) + }, 5 * 60 * 1000) + const data = JSON.stringify({ + mobile, + templateId: '930719', + parameters: [ + { name: 'CODE', value: otp.toString() } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + + axios(config) + .then(function (response) { + }) + .catch(function (error) { + console.log(error) + }) + + res.status(200).json({ + success: true, + message: 'کد تایید ارسال شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + loginValidationRules, + loginUser +} diff --git a/public/modstagram-back/controllers/application/login/loginWithUserName.js b/public/modstagram-back/controllers/application/login/loginWithUserName.js new file mode 100644 index 0000000..d171c70 --- /dev/null +++ b/public/modstagram-back/controllers/application/login/loginWithUserName.js @@ -0,0 +1,92 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const bcrypt = require('bcryptjs') +const TokenService = require('../../../services/TokenService') +// const jwt = require('jsonwebtoken') + +const loginWithUserName = async (req, res, next) => { + try { + // اعتبارسنجی ورودی ها + const { user_name, password } = req.body + if (!user_name || !password) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + // یافتن کاربر با نام کاربری + const userLow = user_name.toLowerCase() + const user = await UserModel.findOne({ user_name: userLow }) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این نام کاربری یافت نشد' + }) + } + if (!user.password) { + return res.status(422).json({ + error: true, + message: 'رمز عبور برای این کاربر تنظیم نشده است' + }) + } + const isPasswordValid = await bcrypt.compare(password, user.password) + if (!isPasswordValid) { + return res.status(422).json({ + error: true, + message: 'نام کاربری یا رمز عبور اشتباه است' + }) + } + // اگر هم نام کاربری و هم رمز عبور درست بود، ارسال پیام موفقیت آمیز + const token = TokenService.sign({ id: user._id }) + // if (user.user_name === null) { + // return res.json({ + // message: 'ورود با موفقیت', + // page: 'username' + // }) + // } + + // if (!user.first_name && !user.last_name) { + // return res.json({ + // message: 'ورود با موفقیت', + // page: 'name' + // }) + // } + + // if (!user.user_type) { + // return res.json({ + // message: 'کد تایید صحیح بود', + // page: 'usertype' + // }) + // } + let step = '' + if (user.user_name === null) { step = 'user_name' } else if + (!user.password) { step = 'password' } else if + (!user.first_name) { step = 'first_name' } else if + (!user.user_type) { step = 'user_type' } + if (!user.user_type || user.user_name === null || !user.first_name || !user.last_name) { + return res.json({ + message: 'کد تایید صحیح بود', + token, + step, + user_type: null, + page: 'auth-page', + id: user._id + }) + } + return res.json({ + message: 'کد تایید صحیح بود', + token, + page: 'home', + step, + user_type: user.user_type, + id: user._id + }) + } catch (error) { + next(error) + } +} + +module.exports = { + loginWithUserName +} diff --git a/public/modstagram-back/controllers/application/login/verifyController.js b/public/modstagram-back/controllers/application/login/verifyController.js new file mode 100644 index 0000000..431441c --- /dev/null +++ b/public/modstagram-back/controllers/application/login/verifyController.js @@ -0,0 +1,89 @@ +const UserModel = require('../../../models/UserModel') +const TokenService = require('../../../services/TokenService') +// const jwt = require('jsonwebtoken') + +const verifyUser = async (req, res, next) => { + try { + const { mobile, otp } = req.body + if (!mobile || !otp) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const user = await UserModel.findOne({ mobile }) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + const token = TokenService.sign({ id: user._id }) + if (user.otp === otp) { + // if (user.user_name === null) { + // return res.json({ + // message: 'کد تایید صحیح بود', + // page: 'username' + // }) + // } + + // if (!user.first_name && !user.last_name) { + // return res.json({ + // message: 'کد تایید صحیح بود', + // page: 'name' + // }) + // } + + // if (!user.user_type) { + // return res.json({ + // message: 'کد تایید صحیح بود', + // page: 'usertype' + // }) + // } + + // اگر همه فیلدها پر بودند + // return res.json({ + // message: 'کد تایید صحیح بود', + // token, + // user_type: user.user_type, + // page: 'home', + // id: user._id + // }) + let step = '' + if (user.user_name === null) { step = 'user_name' } else if + (!user.password) { step = 'password' } else if + (!user.first_name) { step = 'first_name' } else if + (!user.user_type) { step = 'user_type' } else { step = 'profile_image' } + if (!user.user_type || user.user_name === null || !user.first_name || !user.last_name) { + return res.json({ + message: 'کد تایید صحیح بود', + token, + step, + user_type: null, + page: 'auth-page', + id: user._id + }) + } + return res.json({ + message: 'کد تایید صحیح بود', + token, + user_type: user.user_type, + step, + page: 'home', + id: user._id + }) + } + + return res.status(422).json({ + error: true, + message: 'کد تایید اشتباه است' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + verifyUser +} diff --git a/public/modstagram-back/controllers/application/messages/messageController.js b/public/modstagram-back/controllers/application/messages/messageController.js new file mode 100644 index 0000000..7147781 --- /dev/null +++ b/public/modstagram-back/controllers/application/messages/messageController.js @@ -0,0 +1,127 @@ +const MessageModel = require('../../../models/MessageModel') +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') +const moment = require('moment-jalaali') +const getMessages = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { search } = req.query + + // پیدا کردن تمام پیام‌هایی که کاربر مورد نظر آنها فرستنده یا گیرنده بوده است + const messageFilter = { + $or: [ + { senderId: userId }, + { receiverId: userId } + ] + } + + // پیدا کردن تمام پیام‌ها با فیلتر و سورت براساس جدیدترین پیام + const messages = await MessageModel.find(messageFilter).sort({ createdAt: -1 }) + + // استخراج شناسه‌های تمام کاربران مرتبط با این پیام‌ها (بدون تکرار) + const userIdToLastMessageDate = {} + messages.forEach(message => { + if (!userIdToLastMessageDate[message.senderId]) { + userIdToLastMessageDate[message.senderId] = message.createdAt + } + if (!userIdToLastMessageDate[message.receiverId]) { + userIdToLastMessageDate[message.receiverId] = message.createdAt + } + }) + + // تبدیل مجموعه شناسه‌های کاربر به آرایه + const userIdsArray = Object.keys(userIdToLastMessageDate) + + // ساخت فیلتر جستجو برای کاربران مرتبط + const userFilter = { _id: { $in: userIdsArray } } + + if (search) { + userFilter.$and = [ + { _id: { $in: userIdsArray } }, // فقط کاربران مرتبط + { + $or: [ + { first_name: { $regex: search, $options: 'i' } }, + { last_name: { $regex: search, $options: 'i' } }, + { user_name: { $regex: search, $options: 'i' } } + ] + } + ] + } + + // پیدا کردن اطلاعات کاربران مرتبط بر اساس فیلتر جستجو و شمارش تعداد پیام‌های خوانده نشده برای هر کاربر + const usersData = await UserModel.find(userFilter) + const usersWithUnreadCount = await Promise.all(usersData.map(async (user) => { + const unreadMessagesCount = await MessageModel.countDocuments({ receiverId: userId, senderId: user._id, readStatus: 0 }) + + let lastOnlineStatus + const now = moment() + const lastOnline = moment(user.last_online) + const diffMinutes = now.diff(lastOnline, 'minutes') + + if (diffMinutes < 1) { + lastOnlineStatus = 'آنلاین' + } else if (diffMinutes < 60) { + lastOnlineStatus = `${diffMinutes} دقیقه پیش` + } else if (diffMinutes < 1440) { + lastOnlineStatus = `${Math.floor(diffMinutes / 60)} ساعت پیش` + } else { + lastOnlineStatus = `${Math.floor(diffMinutes / 1440)} روز پیش` + } + + // بررسی آیا کاربر فعلی در لیست بلاک‌شده‌های این کاربر است یا خیر + const blockedByCurrentUser = user.blocked_by.includes(userId) + const blockedYou = user.blocked_users.includes(userId) + + return { + first_name: user.first_name, + last_name: user.last_name, + user_name: user.user_name, + is_verified: user.is_verified, + profile_image: user.profile_image, + last_online: lastOnlineStatus, + _id: user._id, + unread_messages_count: unreadMessagesCount, + is_blocked: blockedByCurrentUser, + blocked_you: blockedYou, + last_message_date: userIdToLastMessageDate[user._id] + } + })) + + // حذف کاربر فعلی از آرایه و سورت کردن کاربران براساس آخرین پیام + const filteredUsersData = usersWithUnreadCount + .filter(user => user._id.toString() !== userId) + .sort((a, b) => new Date(b.last_message_date) - new Date(a.last_message_date)) + + res.status(200).json({ + filteredUsersData, + totalMessages: messages.length + }) + } catch (error) { + next(error) + } +} + +const getUnreadMessages = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + // پیدا کردن تمام پیام‌های کاربر که هنوز خوانده نشده‌اند + const unreadMessagesCount = await MessageModel.countDocuments({ receiverId: userId, readStatus: 0 }) + + res.status(200).json({ unread_messages_count: unreadMessagesCount }) + } catch (error) { + next(error) + } +} +module.exports = { + getMessages, getUnreadMessages +} diff --git a/public/modstagram-back/controllers/application/notification/notificationController.js b/public/modstagram-back/controllers/application/notification/notificationController.js new file mode 100644 index 0000000..3b44cad --- /dev/null +++ b/public/modstagram-back/controllers/application/notification/notificationController.js @@ -0,0 +1,68 @@ +const jwt = require('jsonwebtoken') +const NotificationModel = require('../../../models/NotificationModel') +const jMoment = require('moment-jalaali') + +const getNotifications = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const { page = 1, limit = 10, search } = req.query // افزودن پارامترهای صفحه‌بندی به درخواست + const filter = { user_id: userId } + if (search) { + filter.$or = [ + { title: { $regex: search, $options: 'i' } }, + { description: { $regex: search, $options: 'i' } } + ] + } + // استفاده از مدل پیجینیت شده برای دریافت نتایج صفحه‌بندی شده + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: { createdAt: -1 } // بر اساس زمان ایجاد (createdAt) مرتب کنید (نزولی) + } + + // دریافت اعلان‌های مربوط به کاربر با استفاده از userId + let notifications = await NotificationModel.paginate(filter, options) + const totalPages = notifications.totalPages + const totalItems = notifications.totalDocs + notifications = notifications?.docs.map(notification => { + const jDate = jMoment(notification.createdAt).format('jYYYY-jMM-jDD HH:mm') + return { + ...notification._doc, + createdAt: jDate + } + }) + // تغییر وضعیت "read" اعلان‌ها به "true" + await NotificationModel.updateMany({ user_id: userId }, { read: true }) + res.json({ + notifications, + totalPages, // ارسال تعداد کل صفحات + totalItems // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + next(error) + } +} +const unreadNotifications = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + // دریافت تعداد اعلان‌های جدید برای کاربر + const newNotificationsCount = await NotificationModel.countDocuments({ user_id: userId, read: false }).exec() + + res.json({ newNotificationsCount }) + } catch (error) { + next(error) + } +} + +module.exports = { + getNotifications, unreadNotifications +} diff --git a/public/modstagram-back/controllers/application/offer/offerController.js b/public/modstagram-back/controllers/application/offer/offerController.js new file mode 100644 index 0000000..cfb9a40 --- /dev/null +++ b/public/modstagram-back/controllers/application/offer/offerController.js @@ -0,0 +1,439 @@ +/* eslint-disable camelcase */ +const jwt = require('jsonwebtoken') +const jMoment = require('moment-jalaali') +const OfferModel = require('../../../models/OfferModel') +const UserModel = require('../../../models/UserModel') +const OfferTypeModel = require('../../../models/OfferTypeModel') +const PaymentModel = require('../../../models/PaymentModel') +const NotificationModel = require('../../../models/NotificationModel') +const { default: axios } = require('axios') +const CommentModel = require('../../../models/CommentModel') + +const getOfferPriceFromDatabase = async (itemName) => { + const item = await OfferTypeModel.findOne({ name: itemName }) + if (!item) { + throw new Error('Item not found in database') + } + return item.price +} + +const getOfferTypes = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const user = await UserModel.findById(userId) + if (!user) { + return res.status(422).json({ + error: true, + message: 'کاربر یافت نشد' + }) + } + let offerTypes = await OfferTypeModel.find({}, 'name price') + + // بررسی برای مواردی مانند پیدا نشدن انواع پروژه + if (!offerTypes) { + return res.status(404).json({ message: 'انواع پروژه یافت نشد.' }) + } + // اگر کاربر درخواست ماهانه نداشته باشد، نوع پروژه ماهانه را حذف کنید + if (user.monthly_free_offer <= 0) { + offerTypes = offerTypes.filter(projectType => projectType.name !== 'free') + } + // ارسال انواع پروژه به کاربر + res.status(200).json({ offerTypes }) + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error('Error in getOfferTypes:', error) + res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' }) + } +} +const getUserOffers = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const { page = 1, limit = 10, status_filter, id } = req.query // افزودن پارامترهای صفحه‌بندی به درخواست + let filter = {} + let filterbyid = {receiver: id} + let filterbyidsender = {sender: id} + if (status_filter === 'درخواست') { + filter = { sender: userId } + } else { + filter = { receiver: userId } + } + + // تنظیم گزینه‌های صفحه‌بندی + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: { createdAt: -1 }, // بر اساس زمان ایجاد (createdAt) مرتب کنید (نزولی) + populate: [ + { + path: 'sender', + select: 'profile_image user_level first_name last_name user_name is_verified user_score rate' + }, + { + path: 'receiver', + select: 'profile_image user_level first_name last_name user_name is_verified user_score rate' + } + ] + } + + // دریافت آفرهای صفحه‌بندی شده + let offer = await OfferModel.paginate(filter, options) + let offerbyid = await OfferModel.paginate(filterbyid, options) + let offerbyidsender = await OfferModel.paginate(filterbyidsender, options) + + const totalPages = offer.totalPages + const totalItems = offer.totalDocs + + // فرمت کردن تاریخ و ارسال پاسخ + offer = offer?.docs.map(offer => { + const jDate = jMoment(offer.createdAt).format('jYYYY-jMM-jDD HH:mm') + return { + ...offer._doc, + createdAt: jDate + } + }) + res.json({ + offerbyidsender, + offerbyid, + offer, + totalPages, // ارسال تعداد کل صفحات + totalItems // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + next(error) + } +} + +const updateOfferStatus = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id // ID کاربری که درخواست را به‌روزرسانی می‌کند + const reciverUser = await UserModel.findById(userId) + + const { offerId, action } = req.body // آیدی آفر و اکشن (accept یا reject) + + // بررسی اعتبار ورودی‌ها + if (!offerId || !['accept', 'reject'].includes(action)) { + return res.status(400).json({ error: 'Invalid input' }) + } + + // یافتن آفر موردنظر + const offer = await OfferModel.findById(offerId) + const senderUser = await UserModel.findById(offer?.sender) + + if (!offer) { + return res.status(404).json({ error: 'Offer not found' }) + } + + // بررسی اینکه آیا کاربر گیرنده این آفر است یا خیر + if (offer.receiver.toString() !== userId) { + return res.status(403).json({ error: 'You are not authorized to update this offer' }) + } + + // بررسی اینکه آیا آفر قبلاً به‌روزرسانی شده یا نه + if (offer.status !== 'pending') { + return res.status(400).json({ error: 'Offer has already been updated', message: 'وضعیت این درخواست قبلا تغییر کرده است.' }) + } + + // به‌روزرسانی وضعیت آفر بر اساس اکشن + offer.status = action === 'accept' ? 'accepted' : 'rejected' + await offer.save() + + if (action === 'accept') { + const data = JSON.stringify({ + mobile: senderUser?.mobile, + templateId: '633448', + parameters: [ + { name: 'USER', value: reciverUser?.first_name + ' ' + reciverUser?.last_name }, + { name: 'EMPLOYER', value: senderUser?.first_name + ' ' + senderUser?.last_name } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + axios(config) + .then(function (response) { + }) + .catch(function (error) { + console.log(error) + }) + } else { + const data = JSON.stringify({ + mobile: senderUser?.mobile, + templateId: '682678', + parameters: [ + { name: 'USER', value: reciverUser?.first_name + ' ' + reciverUser?.last_name }, + { name: 'EMPLOYER', value: senderUser?.first_name + ' ' + senderUser?.last_name } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + axios(config) + .then(function (response) { + }) + .catch(function (error) { + console.log(error) + }) + } + res.status(200).json({ + message: `Offer has been ${offer.status} successfully`, + offerId: offer._id, + status: offer.status + }) + } catch (error) { + next(error) + } +} + +// Controller function for handling successful advertising payment +const handleSuccessfulOfferPayment = async (req, res) => { + try { + const { reciverId, offerType } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + // Check user's free offer eligibility + const user = await UserModel.findById(userId) + if (!user) return res.status(404).json({ error: 'User not found' }) + // Check user's free offer eligibility + const reciverUser = await UserModel.findById(reciverId) + if (!user) return res.status(404).json({ error: 'User not found' }) + + let price + if (user.monthly_free_offer > 0 && offerType === 'free') { + // Use free offer and decrement counter + price = 0 + user.monthly_free_offer -= 1 + await user.save() + } else { + // Retrieve offer price based on type + price = await getOfferPriceFromDatabase(offerType) + + // Create a new payment entry + const payment = new PaymentModel({ + amount: Number(price), + status: 'successful', + authority: '', // Add authority if available + user_id: userId, + type: 'offer', + installment_step: null + }) + await payment.save() + } + // Create a new payment entry + const payment = new PaymentModel({ + amount: Number(price), + status: 'successful', + authority: '', // Add authority if available + user_id: userId, + type: 'offer', + installment_step: null + }) + await payment.save() + + // Create a new offer + const offer = new OfferModel({ + sender: userId, + receiver: reciverId, + transaction_id: payment._id // Link the payment to the offer + }) + await offer.save() + console.log(reciverUser?.first_name) + + // Send notification to selected user + const notification = new NotificationModel({ + user_id: reciverId, + project_post_id: offer?._id, + type: 'new_offer', + title: 'درخواست همکاری جدید', + description: `${reciverUser?.first_name} عزیز یک درخواست همکاری برای شما در مجموعه مدستاگرام ثبت شد` + }) + await notification.save() + + // Send Sms + const data = JSON.stringify({ + mobile: reciverUser?.mobile, + templateId: '569006', + parameters: [ + { name: 'FIRSTNAME', value: reciverUser?.first_name }, + { name: 'LASTNAME', value: reciverUser?.last_name } + + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + axios(config) + .then(function (response) { + }) + .catch(function (error) { + console.log(error) + }) + + // Send event based on payment status + + // Emit a success event + if ('eventEmitter' in req.app) { + req.app.get('eventEmitter').emit('paymentSuccess', { + message: 'Payment and offer created successfully', + offerId: offer._id + }) + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + res.status(200).json({ + message: 'Payment and offer recorded successfully', + offerId: offer._id, + price + }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +// Controller function for handling failed advertising payment +const handleFailedOfferPayment = async (req, res) => { + try { + const { offerType } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const price = await getOfferPriceFromDatabase(offerType) + + // Create a new payment entry + const payment = new PaymentModel({ + amount: Number(price), + status: 'failed', + authority: '', // Add authority if available + user_id: userId, + type: 'offer', + installment_step: null + }) + await payment.save() + + // Emit a failure event + if ('eventEmitter' in req.app) { + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment failed' }) + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + res.status(200).json({ message: 'Payment failed', price }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} + +const createOfferComment = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { offerId, comment, rate, user_id } = req.body + if (!offerId || !comment || !rate || !user_id) { + return res.status(400).send({ message: 'All fields are required' }) + } + // بررسی اینکه آیا کاربر قبلاً برای این پیشنهاد نظر داده است + const existingComment = await CommentModel.findOne({ + offer: offerId, + creator: userId + }) + if (existingComment) { + return res.status(400).send({ message: 'شما قبلاً نظر خود را برای این درخواست ثبت کرده‌اید' }) + } + const newComment = new CommentModel({ + user: user_id, + offer: offerId, + creator: userId, + rating: rate, + comment, + comment_for: 'user', + status: 'pending' + }) + await newComment.save() + + const user = await UserModel.findById(user_id) + + // پیدا کردن کامنت‌ها و محاسبه‌ی امتیاز کل + const comments = await CommentModel.find({ user: user_id, comment_for: 'user' }) + const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0)) + + let userLevel + if (user.expertise === 'مدل') { + if (totalRating <= 50) userLevel = 'تازه وارد' + else if (totalRating <= 100) userLevel = 'استاندارد' + else if (totalRating <= 300) userLevel = 'حرفه‌ای' + else userLevel = 'استاد' + } else if (['زیبایی', 'عکاس'].includes(user.expertise)) { + if (totalRating <= 50) userLevel = 'تازه وارد' + else if (totalRating <= 100) userLevel = 'استاندارد' + else if (totalRating <= 300) userLevel = 'حرفه‌ای' + else userLevel = 'استاد' + } + + user.user_score = totalRating + user.user_level = userLevel + + const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' }) + const averageRating = totalRating / totalComments + user.rate = averageRating.toFixed(1) + await user.save() + + res.status(200).json({ message: 'نظر شما با موفقیت ثبت شد' }) + } catch (error) { + next(error) + } +} + +module.exports = { + getUserOffers, + getOfferTypes, + handleSuccessfulOfferPayment, + handleFailedOfferPayment, + updateOfferStatus, + createOfferComment +} diff --git a/public/modstagram-back/controllers/application/payment/paymentController.js b/public/modstagram-back/controllers/application/payment/paymentController.js new file mode 100644 index 0000000..eaca055 --- /dev/null +++ b/public/modstagram-back/controllers/application/payment/paymentController.js @@ -0,0 +1,1185 @@ +/* eslint-disable eqeqeq */ +const axios = require('axios') +const TypeAndPriceModel = require('../../../models/TypeAndPriceModel') +const ProjectModel = require('../../../models/ProjectModel') +const PaymentModel = require('../../../models/PaymentModel') +const jwt = require('jsonwebtoken') +const RequestModel = require('../../../models/RequestModel') +const NotificationModel = require('../../../models/NotificationModel') +const UserModel = require('../../../models/UserModel') +const AdvertisingTypeModel = require('../../../models/AdvertisingTypeModel') +const AdvertisingModel = require('../../../models/AdvertisingModel') + +const apiKey = process.env.MERCHENT_CODE // Replace with your ZarinPal API Key + +// Function to get price based on item name from database +const getPriceFromDatabase = async (itemName) => { + const item = await TypeAndPriceModel.findOne({ name: itemName }) + if (!item) { + throw new Error('Item not found in database') + } + return item.price +} +const getAdvertisingPriceFromDatabase = async (itemName) => { + const item = await AdvertisingTypeModel.findOne({ name: itemName }) + if (!item) { + throw new Error('Item not found in database') + } + return item.price +} + +// Controller function for initiating payment +const initiatePayment = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const itemName = req.body.item_name // Get item name from request body + const price = await getPriceFromDatabase(itemName) // Get price from database + const projectId = req.body.projectId // Get project ID from request body + // Save project ID for later use in callback URL + req.session.projectId = projectId + const item = await TypeAndPriceModel.findOne({ name: itemName }) + const user = await UserModel.findById(userId) + + if (item.name === 'free' && item.price === 0) { + if (user.daily_free_request > 0) { + user.daily_free_request -= 1 + await user.save() + const project = await ProjectModel.findById(projectId) + if (!project) { + res.status(404).send('Project not found') + return + } + project.payment_status = 'done' // Set project status to 'done' + project.status = 'paid' // Set project status to 'done' + await project.save() + res.status(200).json({ message: 'پروژه رایگان با موفقیت ایجاد شد', projectId, type: 'free' }) + } else { + res.status(403).json({ message: 'شما قبلاً از درخواست رایگان امروز استفاده کرده‌اید.' }) + } + } else { + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: apiKey, + Amount: Number(price), + Description: `پرداخت برای سفارش شماره ${projectId}`, + CallbackURL: `${process.env.APP_URL}/projects/payment?projectId=${projectId}&itemName=${itemName}&userId=${userId}` // Assuming your backend URL for handling payment callback + }) + + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority (شناسه پرداخت) + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} + +// Controller function for handling payment callback from ZarinPal +const handlePaymentCallback = async (req, res) => { + try { + // console.log(req.query) + // Extract payment status and authority from ZarinPal callback + const status = req.query.Status + const authority = req.query.Authority + const projectId = req.query.projectId // Get project ID from session + const itemName = req.query.itemName // Get project ID from session + const userId = req.query.userId // Get project ID from session + // Clear project ID from session + // Query ZarinPal API to verify payment status + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const price = await getPriceFromDatabase(itemName) // Get price from database + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: Number(price) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + const payment = new PaymentModel({ + amount: Number(price), + status: 'successful', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + project_id: projectId, + type: 'create', + installment_step: null + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + + // Payment verification is successful + // Now, update project status to 'done' or desired status + const project = await ProjectModel.findById(projectId) + if (!project) { + res.status(404).send('Project not found') + return + } + project.payment_status = 'done' // Set project status to 'done' + project.status = 'paid' // Set project status to 'done' + await project.save() + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + // Emit an event to be listened to in the frontend + // Example event name: 'paymentSuccess' + // Example data: { message: 'Payment successful' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + // Emit an event to be listened to in the frontend + // Example event name: 'paymentFailed' + // Example data: { message: 'Payment canceled or failed' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + // Redirect to the callback URL with the project ID + res.redirect(`modstagram://SuccessPay?projectId=${projectId}&price=${price}&type=create`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: Number(price), + status: 'failed', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + project_id: projectId, + type: 'create' + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + res.redirect(`modstagram://FailedPay?projectId=${projectId}&price=${price}&type=create`) + } + } catch (error) { + // Error occurred while verifying payment + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} + +// Bazaar +const handleSuccessfulPayment = async (req, res) => { + try { + const { projectId } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const project = await ProjectModel.findById(projectId) + if (!project) { + res.status(404).send('Project not found') + return + } + + const price = await getPriceFromDatabase(project.project_type) + + // Create a new payment entry + const payment = new PaymentModel({ + amount: Number(price), + status: 'successful', + authority: '', // Add authority if available + user_id: userId, + project_id: projectId, + type: 'create', + installment_step: null + }) + await payment.save() + + // Update the project status to 'done' or 'paid' + project.payment_status = 'done' + project.status = 'paid' + await project.save() + + // Emit a success event + if ('eventEmitter' in req.app) { + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + res.status(200).json({ message: 'Payment recorded successfully', projectId, price }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +// Controller function for handling failed payment +const handleFailedPayment = async (req, res) => { + try { + const { projectId } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const project = await ProjectModel.findById(projectId) + if (!project) { + res.status(404).send('Project not found') + return + } + + const price = await getPriceFromDatabase(project.project_type) + + // Create a new payment entry + const payment = new PaymentModel({ + amount: Number(price), + status: 'failed', + authority: '', // Add authority if available + user_id: userId, + project_id: projectId, + type: 'create' + }) + await payment.save() + + // Emit a failure event + if ('eventEmitter' in req.app) { + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment failed' }) + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + res.status(200).json({ message: 'Payment failed', projectId, price }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} + +const paymentRequestStepOne = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const projectId = req.body.projectId + // Find the project + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ error: 'Project not found' }) + } + + // Get the final price from the request model + const requestId = req.body.requestId + const request = await RequestModel.findById(requestId) + if (!request) { + return res.status(404).json({ error: 'Request not found' }) + } + const halfAmount = request.price / 2 + + // Proceed with ZarinPal payment request + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: apiKey, + Amount: parseInt(halfAmount + halfAmount / 100 * 9), + Description: `پرداخت برای سفارش شماره ${projectId}`, + CallbackURL: `${process.env.APP_URL}/projects/payment-request-step-one-callback?projectId=${projectId}&requestId=${requestId}&userId=${userId}` // Callback URL including requestId + }) + + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const paymentRequestStepTwo = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const projectId = req.body.projectId + const installmentNumber = req.body.installmentNumber + // Find the project + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ error: 'Project not found' }) + } + + // Calculate the amount for the second installment (1/4 of the total price) + const totalAmount = project.final_price + const secondInstallmentAmount = totalAmount / 4 + // Proceed with ZarinPal payment request for the second installment + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: apiKey, + Amount: parseInt(secondInstallmentAmount + secondInstallmentAmount / 100 * 9), + Description: `پرداخت برای سفارش شماره ${projectId}`, + CallbackURL: `${process.env.APP_URL}/projects/payment-request-step-two-callback?projectId=${projectId}&userId=${userId}&installmentNumber=${installmentNumber}` // Callback URL + }) + + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const paymentRequestStepAll = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const projectId = req.body.projectId + + // Find the project + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ error: 'Project not found' }) + } + + // Calculate the amount for the second installment (1/4 of the total price) + const totalAmount = project.final_price + const secondInstallmentAmount = totalAmount / 2 + + // Proceed with ZarinPal payment request for the second installment + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: apiKey, + Amount: parseInt(secondInstallmentAmount + secondInstallmentAmount / 100 * 9), + Description: `پرداخت برای سفارش شماره ${projectId}`, + CallbackURL: `${process.env.APP_URL}/projects/payment-request-step-all-callback?projectId=${projectId}&userId=${userId}` // Callback URL + }) + + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const paymentRequestStepOneCallback = async (req, res) => { + try { + const status = req.query.Status + const authority = req.query.Authority + const projectId = req.query.projectId + const requestId = req.query.requestId + const userId = req.query.userId + + // Verify payment status with ZarinPal + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const request = await RequestModel.findById(requestId) + if (!request) { + return res.status(404).json({ error: 'Request not found' }) + } + const price = request.price / 2 + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: parseInt(price + price / 100 * 9) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + // Payment verification is successful + const payment = new PaymentModel({ + amount: price, + status: 'successful', + authority, + user_id: userId, + project_id: projectId, + type: 'installment', + installment_step: 1 + }) + await payment.save() + // Update project's installment details + + // Update project status + request.status = 'accepted' + await request.save() + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ error: 'Project not found' }) + } + project.selected_user = request.user + project.status = 'ongoing' + project.installments.push({ installment_number: 1, amount: price, due_date: new Date() }) + project.final_price = request.price + project.final_time = request.time + await project.save() + // Send notification to selected user + const notification = new NotificationModel({ + user_id: request.user, + project_post_id: projectId, + type: 'request_accepted', + title: 'انتخاب پیشنهاد', + description: `کارفرما پیشنهاد کاری شما برای پروژه ${project.title} را پذیرفت.` + }) + await notification.save() + + // Sms + + const userReciver = await UserModel.findById(request.user) + + const data = JSON.stringify({ + mobile: userReciver?.mobile, + templateId: '302876', + parameters: [ + { name: 'USER', value: userReciver?.first_name + ' ' + userReciver?.last_name }, + { name: 'PROJECT', value: project?.title } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + axios(config) + .then(function (response) { + }) + .catch(function (error) { + console.log(error) + }) + + // End Sms + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + // Redirect to the callback URL with the project ID + res.redirect(`modstagram://SuccessPay?projectId=${projectId}&price=${price}&type=steps&requestId=${requestId}`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: price, + status: 'failed', + authority, + user_id: userId, + project_id: projectId, + type: 'installment' + }) + await payment.save() + res.redirect(`modstagram://FailedPay?projectId=${projectId}&price=${price}&type=steps&requestId=${requestId}`) + } + } catch (error) { + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} + +const paymentRequestStepTwoCallback = async (req, res) => { + try { + const status = req.query.Status + const authority = req.query.Authority + const projectId = req.query.projectId + const userId = req.query.userId + const installmentNumber = req.query.installmentNumber + + // Verify payment status with ZarinPal + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ error: 'Project not found' }) + } + const totalAmount = project.final_price + const secondInstallmentAmount = totalAmount / 4 + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: parseInt(secondInstallmentAmount + secondInstallmentAmount / 100 * 9) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + // Payment verification is successful + const payment = new PaymentModel({ + amount: secondInstallmentAmount, + status: 'successful', + authority, + user_id: userId, + project_id: projectId, + type: 'installment', + installment_step: installmentNumber == 2 ? 2 : 3 + + }) + await payment.save() + + // Update project's installment details + project.installments.push({ installment_number: 2, amount: secondInstallmentAmount, due_date: new Date() }) + await project.save() + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + let description + // eslint-disable-next-line eqeqeq + if (installmentNumber == 2) { + description = 'پرداخت' + } else { + description = 'کارفرما کل مبلغ پروژه را پرداخت کرد.' + } + const notification = new NotificationModel({ + user_id: project.selected_user, + project_post_id: projectId, + type: 'payment_progress', + title: description, + description + }) + await notification.save() + // Redirect to the callback URL with the project ID + res.redirect(`modstagram://SuccessPay?projectId=${projectId}&price=${secondInstallmentAmount}&type=steps`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: secondInstallmentAmount, + status: 'failed', + authority, + user_id: userId, + project_id: projectId, + type: 'installment' + }) + await payment.save() + res.redirect(`modstagram://FailedPay?projectId=${projectId}&price=${secondInstallmentAmount}&type=steps`) + } + } catch (error) { + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} +const paymentRequestStepAllCallback = async (req, res) => { + try { + const status = req.query.Status + const authority = req.query.Authority + const projectId = req.query.projectId + const userId = req.query.userId + + // Verify payment status with ZarinPal + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ error: 'Project not found' }) + } + const totalAmount = project.final_price + const secondInstallmentAmount = totalAmount / 2 + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: parseInt(secondInstallmentAmount + secondInstallmentAmount / 100 * 9) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + // Payment verification is successful + const payment = new PaymentModel({ + amount: secondInstallmentAmount, + status: 'successful', + authority, + user_id: userId, + project_id: projectId, + type: 'installment', + installment_step: 'all' + + }) + await payment.save() + + // Update project's installment details + project.installments.push({ installment_number: 2, amount: secondInstallmentAmount, due_date: new Date() }) + await project.save() + const notification = new NotificationModel({ + user_id: project.selected_user, + project_post_id: projectId, + type: 'payment_progress', + title: 'پرداخت', + description: 'کارفرما کل مبلغ پروژه را پرداخت کرد.' + }) + await notification.save() + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + // Redirect to the callback URL with the project ID + res.redirect(`modstagram://SuccessPay?projectId=${projectId}&price=${secondInstallmentAmount}&type=steps`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: secondInstallmentAmount, + status: 'failed', + authority, + user_id: userId, + project_id: projectId, + type: 'installment' + }) + await payment.save() + res.redirect(`modstagram://FailedPay?projectId=${projectId}&price=${secondInstallmentAmount}&type=steps`) + } + } catch (error) { + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} + +const initiateAdvertisingPayment = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const itemName = req.body.item_name // Get item name from request body + const price = await getAdvertisingPriceFromDatabase(itemName) // Get price from database + const advertisingId = req.body.advertisingId // Get project ID from request body + const showDiscount = req.body.showDiscount + + // Save project ID for later use in callback URL + req.session.advertisingId = advertisingId + const item = await AdvertisingTypeModel.findOne({ name: itemName }) + const user = await UserModel.findById(userId) + + if (item.name === 'free' && item.price === 0) { + if (user.daily_free_request > 0) { + user.daily_free_request -= 1 + await user.save() + const project = await ProjectModel.findById(advertisingId) + if (!project) { + res.status(404).send('Project not found') + return + } + project.payment_status = 'done' // Set project status to 'done' + project.status = 'paid' // Set project status to 'done' + await project.save() + res.status(200).json({ message: 'پروژه رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' }) + } else { + res.status(403).json({ message: 'شما قبلاً از درخواست رایگان امروز استفاده کرده‌اید.' }) + } + } else { + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: apiKey, + Amount: showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price), + Description: `پرداخت برای سفارش شماره ${advertisingId}`, + CallbackURL: `${process.env.APP_URL}/advertising/payment?advertisingId=${advertisingId}&itemName=${itemName}&userId=${userId}&showDiscount=${showDiscount}` // Assuming your backend URL for handling payment callback + }) + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority (شناسه پرداخت) + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const handleAdvertisingPaymentCallback = async (req, res) => { + try { + // console.log(req.query) + // Extract payment status and authority from ZarinPal callback + const status = req.query.Status + const authority = req.query.Authority + const advertisingId = req.query.advertisingId // Get project ID from session + const itemName = req.query.itemName // Get project ID from session + const userId = req.query.userId // Get project ID from session + const showDiscount = req.query.showDiscount // Get project ID from session + // Clear project ID from session + // Query ZarinPal API to verify payment status + + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const price = await getAdvertisingPriceFromDatabase(itemName) // Get price from database + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price), + status: 'successful', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + advertising_id: advertisingId, + type: 'advertising', + installment_step: null + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + + // Payment verification is successful + // Now, update project status to 'done' or desired status + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + res.status(404).send('Advertising not found') + return + } + advertising.payment_status = 'done' // Set advertising status to 'done' + advertising.status = 'paid' // Set advertising status to 'done' + await advertising.save() + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + // Emit an event to be listened to in the frontend + // Example event name: 'paymentSuccess' + // Example data: { message: 'Payment successful' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + // Emit an event to be listened to in the frontend + // Example event name: 'paymentFailed' + // Example data: { message: 'Payment canceled or failed' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + // Redirect to the callback URL with the advertising ID + res.redirect(`modstagram://SuccessPay?projectId=${advertisingId}&price=${showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price)}&type=advertising&showDiscount=${showDiscount}`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: showDiscount ? Number(price + 20000) : Number(price), + status: 'failed', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + advertising_id: advertisingId, + type: 'advertising' + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + res.redirect(`modstagram://FailedPay?projectId=${advertisingId}&price=${showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price)}&type=advertising&showDiscount=${showDiscount}`) + } + } catch (error) { + // Error occurred while verifying payment + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} + +// Controller function for handling successful advertising payment +const handleSuccessfulAdvertisingPayment = async (req, res) => { + try { + const { advertisingId } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const showDiscount = req.query.showDiscount // Get project ID from session + + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + res.status(404).send('Advertising not found') + return + } + + const price = await getAdvertisingPriceFromDatabase(advertising.type) + + // Create a new payment entry + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price), + status: 'successful', + authority: '', // Add authority if available + user_id: userId, + advertising_id: advertisingId, + type: 'advertising', + installment_step: null + }) + await payment.save() + + // Update the advertising status to 'done' or 'paid' + advertising.payment_status = 'done' + advertising.status = 'paid' + await advertising.save() + + // Emit a success event + if ('eventEmitter' in req.app) { + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + res.status(200).json({ message: 'Payment recorded successfully', advertisingId, price }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +// Controller function for handling failed advertising payment +const handleFailedAdvertisingPayment = async (req, res) => { + try { + const { advertisingId } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const showDiscount = req.query.showDiscount // Get project ID from session + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + res.status(404).send('Advertising not found') + return + } + + const price = await getAdvertisingPriceFromDatabase(advertising.type) + + // Create a new payment entry + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price), + status: 'failed', + authority: '', // Add authority if available + user_id: userId, + advertising_id: advertisingId, + type: 'advertising' + }) + await payment.save() + + // Emit a failure event + if ('eventEmitter' in req.app) { + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment failed' }) + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + res.status(200).json({ message: 'Payment failed', advertisingId, price }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} + +const republishAdvertisingPayment = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const itemName = req.body.item_name // Get item name from request body + const price = await getAdvertisingPriceFromDatabase(itemName) // Get price from database + const advertisingId = req.body.advertisingId // Get project ID from request body + const showDiscount = req.body.showDiscount + // Save project ID for later use in callback URL + req.session.advertisingId = advertisingId + const item = await AdvertisingTypeModel.findOne({ name: itemName }) + const user = await UserModel.findById(userId) + + if (item.name === 'free' && item.price === 0) { + if (user.daily_free_request > 0) { + user.daily_free_request -= 1 + await user.save() + const project = await ProjectModel.findById(advertisingId) + if (!project) { + res.status(404).send('Project not found') + return + } + project.payment_status = 'done' // Set project status to 'done' + project.status = 'paid' // Set project status to 'done' + await project.save() + res.status(200).json({ message: 'پروژه رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' }) + } else { + res.status(403).json({ message: 'شما قبلاً از درخواست رایگان امروز استفاده کرده‌اید.' }) + } + } else { + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: apiKey, + Amount: showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100), + Description: `پرداخت برای سفارش شماره ${advertisingId}`, + CallbackURL: `${process.env.APP_URL}/advertising/republish-verify-payment?advertisingId=${advertisingId}&itemName=${itemName}&userId=${userId}&showDiscount=${showDiscount}` // Assuming your backend URL for handling payment callback + }) + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority (شناسه پرداخت) + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const handleAdvertisingRepublishPaymentCallback = async (req, res) => { + try { + // console.log(req.query) + // Extract payment status and authority from ZarinPal callback + const status = req.query.Status + const authority = req.query.Authority + const advertisingId = req.query.advertisingId // Get project ID from session + const itemName = req.query.itemName // Get project ID from session + const userId = req.query.userId // Get project ID from session + const showDiscount = req.query.showDiscount // Get project ID from session + // Clear project ID from session + // Query ZarinPal API to verify payment status + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const price = await getAdvertisingPriceFromDatabase(itemName) // Get price from database + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100), + status: 'successful', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + advertising_id: advertisingId, + type: 'advertising', + installment_step: null + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + + // Payment verification is successful + // Now, update project status to 'done' or desired status + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + res.status(404).send('Advertising not found') + return + } + advertising.payment_status = 'done' // Set advertising status to 'done' + advertising.status = 'accepted' // Set advertising status to 'done' + advertising.acceptedAt = new Date() + await advertising.save() + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + // Emit an event to be listened to in the frontend + // Example event name: 'paymentSuccess' + // Example data: { message: 'Payment successful' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + // Emit an event to be listened to in the frontend + // Example event name: 'paymentFailed' + // Example data: { message: 'Payment canceled or failed' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + // Redirect to the callback URL with the advertising ID + res.redirect(`modstagram://SuccessPay?projectId=${advertisingId}&price=${showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100)}&type=advertising-republish&showDiscount=${showDiscount}`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100), + status: 'failed', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + advertising_id: advertisingId, + type: 'advertising' + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + res.redirect(`modstagram://FailedPay?projectId=${advertisingId}&price=${showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100)}&type=advertising-republish&showDiscount=${showDiscount}`) + } + } catch (error) { + // Error occurred while verifying payment + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} +// Controller function for handling successful republish advertising payment +const handleSuccessfulAdvertisingRepublishPayment = async (req, res) => { + try { + const { advertisingId } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const showDiscount = req.query.showDiscount + + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + res.status(404).send('Advertising not found') + return + } + + const price = await getAdvertisingPriceFromDatabase(advertising.type) + + // Create a new payment entry + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number((price + 20000) * 0.7) : Number(price * 0.7), + status: 'successful', + authority: '', // Add authority if available + user_id: userId, + advertising_id: advertisingId, + type: 'advertising-republish', + installment_step: null + }) + await payment.save() + + // Update the advertising status to 'done' or 'accepted' + advertising.payment_status = 'done' + advertising.status = 'accepted' + advertising.acceptedAt = new Date() + await advertising.save() + + // Emit a success event + if ('eventEmitter' in req.app) { + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Republish payment successful' }) + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + res.status(200).json({ message: 'Republish payment recorded successfully', advertisingId, price }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +// Controller function for handling failed republish advertising payment +const handleFailedAdvertisingRepublishPayment = async (req, res) => { + try { + const { advertisingId } = req.body + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const showDiscount = req.query.showDiscount + + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + res.status(404).send('Advertising not found') + return + } + + const price = await getAdvertisingPriceFromDatabase(advertising.type) + + // Create a new payment entry + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number((price + 20000) * 0.7) : Number(price * 0.7), + status: 'failed', + authority: '', // Add authority if available + user_id: userId, + advertising_id: advertisingId, + type: 'advertising-republish' + }) + await payment.save() + + // Emit a failure event + if ('eventEmitter' in req.app) { + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Republish payment failed' }) + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + res.status(200).json({ message: 'Republish payment failed', advertisingId, price }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} + +module.exports = { + initiatePayment, + handlePaymentCallback, + paymentRequestStepOne, + paymentRequestStepTwo, + paymentRequestStepAll, + paymentRequestStepOneCallback, + paymentRequestStepTwoCallback, + paymentRequestStepAllCallback, + initiateAdvertisingPayment, + handleAdvertisingPaymentCallback, + republishAdvertisingPayment, + handleAdvertisingRepublishPaymentCallback, + handleSuccessfulPayment, + handleFailedPayment, + handleSuccessfulAdvertisingPayment, + handleFailedAdvertisingPayment, + handleSuccessfulAdvertisingRepublishPayment, + handleFailedAdvertisingRepublishPayment +} diff --git a/public/modstagram-back/controllers/application/payment/paymentControllerWeb.js b/public/modstagram-back/controllers/application/payment/paymentControllerWeb.js new file mode 100644 index 0000000..d409670 --- /dev/null +++ b/public/modstagram-back/controllers/application/payment/paymentControllerWeb.js @@ -0,0 +1,935 @@ +/* eslint-disable eqeqeq */ + +const TypeAndPriceModel = require('../../../models/TypeAndPriceModel'); +const ProjectModel = require('../../../models/ProjectModel'); +const PaymentModel = require('../../../models/PaymentModel'); +const jwt = require('jsonwebtoken'); +const RequestModel = require('../../../models/RequestModel'); +const NotificationModel = require('../../../models/NotificationModel'); +const UserModel = require('../../../models/UserModel'); +const AdvertisingTypeModel = require('../../../models/AdvertisingTypeModel'); +const AdvertisingModel = require('../../../models/AdvertisingModel'); +const OfferTypeModel = require('../../../models/OfferTypeModel'); +const OfferModel = require('../../../models/OfferModel'); +const { default: axios } = require('axios'); + +const apiKey = "c7c41e8a-918f-4741-bcd5-58f3bc51db73"; // اصلاح نام متغیر محیطی + +// Function to get price based on item name from database +const getPriceFromDatabase = async (itemName) => { + const item = await TypeAndPriceModel.findOne({ name: itemName }); + if (!item) { + throw new Error(`Item "${itemName}" not found in TypeAndPriceModel`); + } + return item.price; +}; + +const getAdvertisingPriceFromDatabase = async (itemName) => { + const item = await AdvertisingTypeModel.findOne({ name: itemName }); + if (!item) { + throw new Error(`Item "${itemName}" not found in AdvertisingTypeModel`); + } + return item.price; +}; + +const getOfferPriceFromDatabase = async (offerType) => { + const item = await OfferTypeModel.findOne({ name: offerType }); + if (!item) { + throw new Error(`Offer type "${offerType}" not found in OfferTypeModel`); + } + return item.price; +}; +// Controller function for initiating payment +const initiatePaymentWeb = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const itemName = req.body.item_name // Get item name from request body + const price = await getPriceFromDatabase(itemName) // Get price from database + const projectId = req.body.projectId // Get project ID from request body + // Save project ID for later use in callback URL + req.session.projectId = projectId + const item = await TypeAndPriceModel.findOne({ name: itemName }) + const user = await UserModel.findById(userId) + + if (item.name === 'free' && item.price === 0) { + if (user.daily_free_request > 0) { + user.daily_free_request -= 1 + await user.save() + const project = await ProjectModel.findById(projectId) + if (!project) { + res.status(404).send('Project not found') + return + } + project.payment_status = 'done' // Set project status to 'done' + project.status = 'paid' // Set project status to 'done' + await project.save() + res.status(200).json({ message: 'پروژه رایگان با موفقیت ایجاد شد', projectId, type: 'free' }) + } else { + res.status(403).json({ message: 'شما قبلاً از درخواست رایگان امروز استفاده کرده‌اید.' }) + } + } else { + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: apiKey, + Amount: Number(price), + Description: `پرداخت برای سفارش شماره ${projectId}`, + CallbackURL: `${process.env.APP_URL}/projects/payment-web?projectId=${projectId}&itemName=${itemName}&userId=${userId}` // Assuming your backend URL for handling payment callback + }) + + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority (شناسه پرداخت) + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +// Controller function for handling payment callback from ZarinPal +const handlePaymentCallbackWeb = async (req, res) => { + try { + // console.log(req.query) + // Extract payment status and authority from ZarinPal callback + const status = req.query.Status + const authority = req.query.Authority + const projectId = req.query.projectId // Get project ID from session + const itemName = req.query.itemName // Get project ID from session + const userId = req.query.userId // Get project ID from session + // Clear project ID from session + // Query ZarinPal API to verify payment status + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const price = await getPriceFromDatabase(itemName) // Get price from database + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: Number(price) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + const payment = new PaymentModel({ + amount: Number(price), + status: 'successful', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + project_id: projectId, + type: 'create', + installment_step: null + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + + // Payment verification is successful + // Now, update project status to 'done' or desired status + const project = await ProjectModel.findById(projectId) + if (!project) { + res.status(404).send('Project not found') + return + } + project.payment_status = 'done' // Set project status to 'done' + project.status = 'paid' // Set project status to 'done' + await project.save() + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + // Emit an event to be listened to in the frontend + // Example event name: 'paymentSuccess' + // Example data: { message: 'Payment successful' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + // Emit an event to be listened to in the frontend + // Example event name: 'paymentFailed' + // Example data: { message: 'Payment canceled or failed' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + // Redirect to the callback URL with the project ID + res.redirect(`https://modstagram.com/projects/payment/success?projectId=${projectId}&price=${price}&type=create`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: Number(price), + status: 'failed', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + project_id: projectId, + type: 'create' + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + res.redirect(`https://modstagram.com/projects/payment/failed?projectId=${projectId}&price=${price}&type=create`) + } + } catch (error) { + // Error occurred while verifying payment + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} + +const paymentRequestAcceptWeb = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const projectId = req.body.projectId + // Find the project + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ error: 'Project not found' }) + } + if (project.status == 'ongoing') { + return res.status(400).json({ message: 'برای این پروژه از قبل کاربر انتخاب شده' }) + } + // eslint-disable-next-line eqeqeq + if (userId != project.creator_id.toString()) { + return res.status(422).json({ + error: true, + message: 'شما نمیتوانید این پروژه را ویرایش کنید' + }) + } + + // Get the final price from the request model + const requestId = req.body.requestId + const request = await RequestModel.findById(requestId) + if (!request) { + return res.status(404).json({ error: 'Request not found' }) + } + request.status = 'accepted' + await request.save() + + project.selected_user = request.user + project.status = 'ongoing' + project.final_price = request.price + project.final_time = request.time + await project.save() + // Send notification to selected user + const notification = new NotificationModel({ + user_id: request.user, + project_post_id: projectId, + type: 'request_accepted', + title: 'انتخاب پیشنهاد', + description: `کارفرما پیشنهاد کاری شما برای پروژه ${project.title} را پذیرفت.` + }) + await notification.save() + + // Sms + const userReciver = await UserModel.findById(request.user) + const data = JSON.stringify({ + mobile: userReciver?.mobile, + templateId: '302876', + parameters: [ + { name: 'USER', value: userReciver?.first_name + ' ' + userReciver?.last_name }, + { name: 'PROJECT', value: project?.title } + ] + }) + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + axios(config) + .then(function (response) { + }) + .catch(function (error) { + console.log(error) + }) + res.status(200).json({ + message: 'درخواست با موفقیت تایید شد' + }) + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const initiateAdvertisingPaymentWeb = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const itemName = req.body.item_name // Get item name from request body + const price = await getAdvertisingPriceFromDatabase(itemName) // Get price from database + const advertisingId = req.body.advertisingId // Get project ID from request body + const showDiscount = req.body.showDiscount + + // Save project ID for later use in callback URL + req.session.advertisingId = advertisingId + const item = await AdvertisingTypeModel.findOne({ name: itemName }) + const user = await UserModel.findById(userId) + + if (item.name === 'free' && item.price === 0) { + if (user.daily_free_request > 0) { + user.daily_free_request -= 1 + await user.save() + const project = await AdvertisingModel.findById(advertisingId) + if (!project) { + res.status(404).send('Advertising not found') + return + } + project.payment_status = 'done' // Set project status to 'done' + project.status = 'paid' // Set project status to 'done' + await project.save() + res.status(200).json({ message: 'بیلبورد رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' }) + } else { + res.status(403).json({ message: 'شما قبلاً از بیلبورد رایگان این ماه استفاده کرده‌اید.' }) + } + } else { + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: process.env.ZARINPAL_MERCHANT_ID, + Amount: showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price), + Description: `پرداخت برای سفارش شماره ${advertisingId}`, + CallbackURL: `${process.env.APP_SITE_CallBack}/advertising/payment-web?advertisingId=${advertisingId}&itemName=${itemName}&userId=${userId}&showDiscount=${showDiscount}` // Assuming your backend URL for handling payment callback + }) + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority (شناسه پرداخت) + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const handleAdvertisingPaymentCallbackWeb = async (req, res) => { + try { + // console.log(req.query) + // Extract payment status and authority from ZarinPal callback + const status = req.query.Status + const authority = req.query.Authority + const advertisingId = req.query.advertisingId // Get project ID from session + const itemName = req.query.itemName // Get project ID from session + const userId = req.query.userId // Get project ID from session + const showDiscount = req.query.showDiscount // Get project ID from session + // Clear project ID from session + // Query ZarinPal API to verify payment status + + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const price = await getAdvertisingPriceFromDatabase(itemName) // Get price from database + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price), + status: 'successful', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + advertising_id: advertisingId, + type: 'advertising', + installment_step: null + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + + // Payment verification is successful + // Now, update project status to 'done' or desired status + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + res.status(404).send('Advertising not found') + return + } + advertising.payment_status = 'done' // Set advertising status to 'done' + advertising.status = 'paid' // Set advertising status to 'done' + await advertising.save() + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + // Emit an event to be listened to in the frontend + // Example event name: 'paymentSuccess' + // Example data: { message: 'Payment successful' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + // Emit an event to be listened to in the frontend + // Example event name: 'paymentFailed' + // Example data: { message: 'Payment canceled or failed' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + // Redirect to the callback URL with the advertising ID + res.redirect(`https://modstagram.com/billboards/payment/success?projectId=${advertisingId}&price=${showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price)}&type=advertising&showDiscount=${showDiscount}`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: showDiscount ? Number(price + 20000) : Number(price), + status: 'failed', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + advertising_id: advertisingId, + type: 'advertising' + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + console.log('ss') + + await payment.save() + res.redirect(`https://modstagram.com/billboards/payment/failed?projectId=${advertisingId}&price=${showDiscount === true || showDiscount === 'true' ? Number(price + 20000) : Number(price)}&type=advertising&showDiscount=${showDiscount}`) + } + } catch (error) { + // Error occurred while verifying payment + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} + +const republishAdvertisingPaymentWeb = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const itemName = req.body.item_name // Get item name from request body + const price = await getAdvertisingPriceFromDatabase(itemName) // Get price from database + const advertisingId = req.body.advertisingId // Get project ID from request body + const showDiscount = req.body.showDiscount + // Save project ID for later use in callback URL + req.session.advertisingId = advertisingId + const item = await AdvertisingTypeModel.findOne({ name: itemName }) + const user = await UserModel.findById(userId) + + if (item.name === 'free' && item.price === 0) { + if (user.daily_free_request > 0) { + user.daily_free_request -= 1 + await user.save() + const project = await AdvertisingModel.findById(advertisingId) + if (!project) { + res.status(404).send('Project not found') + return + } + project.payment_status = 'done' // Set project status to 'done' + project.status = 'paid' // Set project status to 'done' + await project.save() + res.status(200).json({ message: 'پروژه رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' }) + } else { + res.status(403).json({ message: 'شما قبلاً از درخواست رایگان امروز استفاده کرده‌اید.' }) + } + } else { + const response = await axios.post('https://www.zarinpal.com/pg/rest/WebGate/PaymentRequest.json', { + MerchantID: apiKey, + Amount: showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100), + Description: `پرداخت برای سفارش شماره ${advertisingId}`, + CallbackURL: `${process.env.APP_URL}/advertising/republish-verify-payment-web?advertisingId=${advertisingId}&itemName=${itemName}&userId=${userId}&showDiscount=${showDiscount}` // Assuming your backend URL for handling payment callback + }) + const data = response.data + if (data.Status === 100) { + // Payment request was successful + const authority = data.Authority // The payment authority (شناسه پرداخت) + res.status(200).json({ authority }) + } else { + // Payment request failed + console.error('Error occurred while initiating payment:', data) + res.status(500).json({ error: 'Error occurred while initiating payment' }) + } + } + } catch (error) { + // Error occurred while getting price from database or sending the request + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const handleAdvertisingRepublishPaymentCallbackWeb = async (req, res) => { + try { + // console.log(req.query) + // Extract payment status and authority from ZarinPal callback + const status = req.query.Status + const authority = req.query.Authority + const advertisingId = req.query.advertisingId // Get project ID from session + const itemName = req.query.itemName // Get project ID from session + const userId = req.query.userId // Get project ID from session + const showDiscount = req.query.showDiscount // Get project ID from session + // Clear project ID from session + // Query ZarinPal API to verify payment status + const verificationUrl = 'https://www.zarinpal.com/pg/rest/WebGate/PaymentVerification.json' + const price = await getAdvertisingPriceFromDatabase(itemName) // Get price from database + const verificationResponse = await axios.post(verificationUrl, { + MerchantID: apiKey, + Authority: authority, + Amount: showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100) + }) + + const verificationData = verificationResponse.data + if (verificationData.Status === 100) { + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100), + status: 'successful', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + advertising_id: advertisingId, + type: 'advertising', + installment_step: null + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + + // Payment verification is successful + // Now, update project status to 'done' or desired status + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + res.status(404).send('Advertising not found') + return + } + advertising.payment_status = 'done' // Set advertising status to 'done' + advertising.status = 'accepted' // Set advertising status to 'done' + advertising.acceptedAt = new Date() + await advertising.save() + + // Send event based on payment status + if ('eventEmitter' in req.app) { + if (status === 'OK') { + // Payment is successful + // Emit an event to be listened to in the frontend + // Example event name: 'paymentSuccess' + // Example data: { message: 'Payment successful' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }) + } else { + // Payment is canceled or failed + // Emit an event to be listened to in the frontend + // Example event name: 'paymentFailed' + // Example data: { message: 'Payment canceled or failed' } + // You can customize the event name and data as needed + req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment canceled or failed' }) + } + } else { + console.error('Error: eventEmitter is not defined or not properly configured.') + } + + // Redirect to the callback URL with the advertising ID + res.redirect(`https://modstagram.com/billboards/payment/success?projectId=${advertisingId}&price=${showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100)}&type=advertising-republish&showDiscount=${showDiscount}`) + } else { + // Payment verification failed + const payment = new PaymentModel({ + amount: showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100), + status: 'failed', + authority, + user_id: userId, // فرضاً شما از نوع میان‌افزارهای مدیریت کاربر استفاده می‌کنید و اطلاعات کاربر را از طریق `req.user` در دسترس دارید + advertising_id: advertisingId, + type: 'advertising' + // دیگر اطلاعات مورد نیاز برای ثبت پرداخت + }) + await payment.save() + res.redirect(`https://modstagram.com/billboards/payment/failed?projectId=${advertisingId}&price=${showDiscount === true || showDiscount === 'true' ? Number(((price + 20000) * 70) / 100) : Number(((price) * 70) / 100)}&type=advertising-republish&showDiscount=${showDiscount}`) + } + } catch (error) { + // Error occurred while verifying payment + console.error('Error occurred:', error) + res.status(500).send('Internal server error') + } +} +// const initiateOfferPaymentWeb = async (req, res) => { +// try { +// const token = req.header('Authorization')?.split(' ')[1]; +// if (!token) { +// return res.status(401).json({ error: 'Access Denied: No token provided' }); +// } + +// let decodedToken; +// try { +// decodedToken = jwt.verify(token, process.env.APP_SECRET); +// } catch (err) { +// return res.status(401).json({ error: 'Invalid token' }); +// } + +// const userId = decodedToken.id; +// const { receiverId, offerType } = req.body; + +// // اعتبارسنجی ورودی‌ها +// if (!receiverId || !offerType) { +// return res.status(400).json({ error: 'receiverId and offerType are required' }); +// } + +// const user = await UserModel.findById(userId); +// if (!user) { +// return res.status(404).json({ error: 'User not found' }); +// } + +// const receiverUser = await UserModel.findById(receiverId); +// if (!receiverUser) { +// return res.status(404).json({ error: 'Receiver not found' }); +// } + +// let price; +// if (user.monthly_free_offer > 0 && offerType === 'free') { +// price = 0; +// user.monthly_free_offer -= 1; +// await user.save(); +// } else { +// price = await getOfferPriceFromDatabase(offerType); +// } + +// if (price === 0) { +// const offer = new OfferModel({ +// sender: userId, +// receiver: receiverId, +// transaction_id: null, +// }); +// await offer.save(); +// return res.status(200).json({ message: 'آفر رایگان با موفقیت ثبت شد', offerId: offer._id, type: 'free' }); +// } +// console.log('🔹 Initiating ZarinPal Payment'); +// console.log('MerchantID:', apiKey); +// console.log('Amount:', Number(price * 10)); +// console.log('Description:', `پرداخت برای ارسال آفر به ${receiverUser.first_name}`); +// console.log('CallbackURL:', `${process.env.APP_URL}/offers/payment-web?receiverId=${receiverId}&offerType=${offerType}&userId=${userId}`); + +// const ZARINPAL_URL = 'https://api.zarinpal.com/pg/v4/payment/request.json'; +// // +// const response = await axios.post(ZARINPAL_URL, { +// merchant_id: process.env.ZARINPAL_MERCHANT_ID, // ❌ MerchantID نیست! +// amount: Number(price), // ✅ به ریال +// description: `پرداخت برای ارسال آفر به ${receiverUser.first_name}`, +// callback_url: `${process.env.APP_SITE_CallBack}/offer/payment-web?receiverId=${receiverId}&offerType=${offerType}&userId=${userId}`, +// }, { headers: { 'Content-Type': 'application/json' } }); + +// const result = response.data.data; // ✅ data.data + +// if (result.code === 100) { // ✅ code === 100 +// return res.status(200).json({ +// authority: result.authority, +// paymentUrl: `https://www.zarinpal.com/pg/StartPay/${result.authority}` +// }); +// } else { +// console.error('ZarinPal error:', data); +// return res.status(500).json({ error: `Failed to initiate payment: ZarinPal Status ${data.Status}` }); +// } +// } catch (error) { +// console.error('❌ Error in initiateOfferPaymentWeb:', error.message, error.stack); +// return res.status(500).json({ error: error.message || 'Internal server error' }); +// } +// } +const initiateOfferPaymentWeb = async (req, res) => { + try { + const token = req.header('Authorization')?.split(' ')[1]; + if (!token) return res.status(401).json({ error: 'No token' }); + + const decoded = jwt.verify(token, process.env.APP_SECRET); + const userId = decoded.id; + + const { receiverId, offerType } = req.body; + if (!receiverId || !offerType) + return res.status(400).json({ error: 'Invalid data' }); + + const user = await UserModel.findById(userId); + const receiver = await UserModel.findById(receiverId); + if (!user || !receiver) + return res.status(404).json({ error: 'User not found' }); + + let price = await getOfferPriceFromDatabase(offerType); // ✅ ریال + + // 🎁 free offer + if (offerType === 'free' && user.monthly_free_offer > 0) { + const offer = await OfferModel.create({ + sender: userId, + receiver: receiverId, + transaction_id: null, + }); + + user.monthly_free_offer -= 1; + await user.save(); + + return res.json({ + type: 'free', + offerId: offer._id, + }); + } + + const amount = Number(price) * 10; // ✅ ریال – بدون ×10 + const callbackUrl = `https://api.modstagram.com/api/v1/offers/payment-web?receiverId=${receiverId}&offerType=${offerType}&userId=${userId}`; + + const zarinpalRes = await axios.post( + 'https://api.zarinpal.com/pg/v4/payment/request.json', + { + merchant_id:"c7c41e8a-918f-4741-bcd5-58f3bc51db73", + amount, + description: `ارسال آفر به ${receiver.first_name}`, + callback_url: callbackUrl + + // callback_url: `${process.env.APP_SITE_CallBack}/offers/payment-web?receiverId=${receiverId}&offerType=${offerType}&userId=${userId}`, + }, + { headers: { 'Content-Type': 'application/json' } } + ); + + // console.log(`${process.env.APP_SITE_CallBack}/offers/payment-web?receiverId=${receiverId}&offerType=${offerType}&userId=${userId}`); + + + const result = zarinpalRes.data.data; + console.log(result); + console.log("ZarinPal Callback URL:", callbackUrl); + console.log("Initiate payment request:", { userId, receiverId, offerType, price }); + + + + + + if (result.code === 100) { + return res.json({ + authority: result.authority, + paymentUrl: `https://www.zarinpal.com/pg/StartPay/${result.authority}`, + }); + } + + return res.status(500).json({ error: 'ZarinPal error' }); + } catch (err) { + console.error(err); + return res.status(500).json({ error: 'Server error' }); + } +}; + + + +// try { +// const { receiverId, offerType, userId, Authority, Status } = req.query; + +// // ❗ چک اولیه +// if (Status !== 'OK' || !Authority) { +// return res.status(400).json({ +// success: false, +// message: 'پرداخت ناموفق یا لغو شد' +// }); +// } + +// if (!receiverId || !offerType || !userId) { +// return res.status(400).json({ +// success: false, +// message: 'پارامترهای ناقص' +// }); +// } + +// // پیدا کردن کاربرها +// const user = await UserModel.findById(userId); +// const receiverUser = await UserModel.findById(receiverId); + +// if (!user || !receiverUser) { +// return res.status(404).json({ +// success: false, +// message: 'کاربر یافت نشد' +// }); +// } + +// const price = await getOfferPriceFromDatabase(offerType); + +// const verifyResponse = await axios.post( +// 'https://api.zarinpal.com/pg/v4/payment/verify.json', +// { +// merchant_id: process.env.ZARINPAL_MERCHANT_ID, // یا MERCHENT_CODE +// authority: Authority, +// amount: price, // به ریال +// }, +// { headers: { 'Content-Type': 'application/json' } } +// ); + +// const verifyData = verifyResponse.data.data; + +// if (verifyData.code === 100) { +// // ✅ پرداخت موفق +// const payment = new PaymentModel({ +// amount: Number(price), +// status: 'successful', +// authority: Authority, +// ref_id: verifyData.ref_id, +// user_id: userId, +// type: 'offer', +// }); +// await payment.save(); + +// const offer = new OfferModel({ +// sender: userId, +// receiver: receiverId, +// transaction_id: payment._id, +// }); +// await offer.save(); + +// // نوتیفیکیشن و SMS (همون کد قبلی) +// const notification = new NotificationModel({ +// user_id: receiverId, +// project_post_id: offer._id, +// type: 'new_offer', +// title: 'درخواست همکاری جدید', +// description: `${user.first_name} یک درخواست همکاری برای شما ارسال کرده است`, +// }); +// await notification.save(); + +// const data = JSON.stringify({ +// mobile: receiverUser?.mobile, +// templateId: '569006', +// parameters: [ +// { name: 'FIRSTNAME', value: receiverUser?.first_name }, +// { name: 'LASTNAME', value: receiverUser?.last_name }, +// ], +// }); + +// const config = { +// method: 'post', +// url: 'https://api.sms.ir/v1/send/verify', +// headers: { +// 'Content-Type': 'application/json', +// Accept: 'text/plain', +// 'x-api-key': process.env.SMS_VERIFY_KEY, +// }, +// data, +// }; + +// await axios(config).catch((error) => { +// console.error('SMS error:', error.message); +// }); + +// if ('eventEmitter' in req.app && status === 'OK') { +// req.app.get('eventEmitter').emit('paymentSuccess', { message: 'Payment successful' }); +// } else { +// req.app.get('eventEmitter')?.emit('paymentFailed', { message: 'Payment canceled or failed' }); +// } + +// res.redirect(`https://modstagram.com/offer/payment/success?userId=${userId}`); + +// return res.status(200).json({ +// success: true, +// message: 'پرداخت و آفر با موفقیت ثبت شد', +// ref_id: verifyData.ref_id, +// offerId: offer._id +// }); +// } else { +// // پرداخت ناموفق +// const payment = new PaymentModel({ +// amount: Number(price), +// status: 'failed', +// authority: Authority, +// user_id: userId, +// type: 'offer', +// }); +// await payment.save(); +// res.redirect(`https://modstagram.com/offer/payment/failed?userId=${userId}`); +// return res.status(400).json({ +// success: false, +// message: `خطا در تأیید پرداخت: ${verifyData.code}` +// }); + +// } +// } catch (error) { +// console.error('❌ Callback Error:', error.message); +// return res.status(500).json({ +// success: false, +// message: 'خطای سرور' +// }); +// } +// }; + +const handleOfferPaymentCallback = async (req, res) => { + + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); + + console.log('🔔 CALLBACK QUERY:', req.query); + + try { + const { Authority, Status, receiverId, offerType, userId } = req.query; + + if (Status !== 'OK') + return res.redirect(`${process.env.APP_SITE}/offer/payment/failed`); + + const price = await getOfferPriceFromDatabase(offerType); // ریال + const amount = Number(price) * 10; + + const verify = await axios.post( + 'https://api.zarinpal.com/pg/v4/payment/verify.json', + { + merchant_id: "c7c41e8a-918f-4741-bcd5-58f3bc51db73", + authority: Authority, + amount, + }, + { headers: { 'Content-Type': 'application/json' } } + ); + + const data = verify.data.data; + console.log('🔔payment:', data.code); + if (data.code === 100) { + const payment = await PaymentModel.create({ + amount : (amount / 10), + status: 'successful', + authority: Authority, + ref_id: data.ref_id, + user_id: userId, + type: 'offer', + }); + + console.log('🔔payment:', payment); + + const offer = await OfferModel.create({ + sender: userId, + receiver: receiverId, + transaction_id: payment._id, + }); + + return res.redirect( + `${process.env.APP_SITE}/offer/payment/success?offerId=${offer._id}` + ); + } + + return res.redirect(`${process.env.APP_SITE}/offer/payment/failed`); + } catch (err) { + console.error(err); + return res.redirect(`${process.env.APP_SITE}/offer/payment/failed`); + } +}; + + + + + + +module.exports = { + initiatePaymentWeb, + handlePaymentCallbackWeb, + paymentRequestAcceptWeb, + initiateAdvertisingPaymentWeb, + handleAdvertisingPaymentCallbackWeb, + republishAdvertisingPaymentWeb, + handleAdvertisingRepublishPaymentCallbackWeb, + initiateOfferPaymentWeb, + handleOfferPaymentCallback, +}; diff --git a/public/modstagram-back/controllers/application/posts/likeController.js b/public/modstagram-back/controllers/application/posts/likeController.js new file mode 100644 index 0000000..a223cd0 --- /dev/null +++ b/public/modstagram-back/controllers/application/posts/likeController.js @@ -0,0 +1,64 @@ +/* eslint-disable camelcase */ +const PostModel = require('../../../models/PostModel'); +const jwt = require('jsonwebtoken'); +const UserModel = require('../../../models/UserModel'); +const LikeModel = require('../../../models/LikeModel'); + +const toggleLike = async (req, res, next) => { + try { + const { postId } = req.body; + const token = req.header('Authorization')?.split(' ')[1]; + + if (!token) { + return res.status(401).json({ message: 'توکن ارائه نشده است' }); + } + + let userId; + try { + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + userId = decodedToken.id; + } catch (err) { + return res.status(401).json({ message: 'توکن نامعتبر است' }); + } + + if (!postId) { + return res.status(400).json({ message: 'شناسه پست الزامی است' }); + } + + const post = await PostModel.findById(postId); + if (!post) { + return res.status(404).json({ message: 'پست مورد نظر یافت نشد' }); + } + + const isLiked = post.likes.includes(userId); + if (isLiked) { + // unlike + post.likes.pull(userId); + await post.save(); + await LikeModel.findOneAndDelete({ postId, userId }); + + return res.status(200).json({ + message: 'لایک با موفقیت حذف شد', + is_liked: false, + likesCount: post.likes.length, + }); + } else { + // like + post.likes.push(userId); + await post.save(); + await LikeModel.create({ postId, userId }); + + return res.status(200).json({ + message: 'پست با موفقیت لایک شد', + is_liked: true, + likesCount: post.likes.length, + }); + } + } catch (error) { + console.error('خطا در toggleLike:', error); + res.status(500).json({ message: 'خطا در سرور' }); + next(error); + } +}; + +module.exports = { toggleLike }; \ No newline at end of file diff --git a/public/modstagram-back/controllers/application/posts/postController.js b/public/modstagram-back/controllers/application/posts/postController.js new file mode 100644 index 0000000..57721b6 --- /dev/null +++ b/public/modstagram-back/controllers/application/posts/postController.js @@ -0,0 +1,182 @@ +/* eslint-disable camelcase */ +const PostModel = require('../../../models/PostModel'); +const UserModel = require('../../../models/UserModel'); +const { check, validationResult } = require('express-validator'); +const jwt = require('jsonwebtoken'); +const path = require('path'); +const { default: mongoose } = require('mongoose'); + +const createPostValidationRules = () => { + console.log(4); + return [ + check('caption') + .notEmpty().withMessage('توضیحات نمی‌تواند خالی باشد'), + ]; +}; + +const createPost = async (req, res) => { + try { + console.log('DEBUG: createPost called'); + console.log('DEBUG: req.files:', req.files); + console.log('DEBUG: req.body:', req.body); + + const { caption } = req.body; + const files = req.files || []; + const userId = req.user.id; // از میدل‌ویر auth + + if (!files || files.length === 0) { + console.log('DEBUG: No files provided'); + return res.status(400).json({ error: true, message: 'هیچ فایلی آپلود نشده است' }); + } + + if (!caption) { + console.log('DEBUG: No caption provided'); + return res.status(400).json({ error: true, message: 'کپشن الزامی است' }); + } + + const filePaths = files.map((file) => ({ + path: file.path, + type: file.mimetype.startsWith('video/') ? 'video' : 'image', + })); + + console.log('DEBUG: Saving post to MongoDB, filePaths:', filePaths); + const post = new PostModel({ + user_id: userId, + caption, + files: filePaths, + type: files[0].mimetype.startsWith('video/') ? 'video' : 'image', // اضافه کردن فیلد type + createdAt: new Date(), + }); + + await post.save(); + console.log('DEBUG: Post saved:', post._id); + res.status(201).json({ message: 'پست با موفقیت ایجاد شد', postId: post._id }); + } catch (err) { + console.error('DEBUG: createPost error:', err.message); + res.status(500).json({ error: true, message: `خطا در سرور: ${err.message}` }); + } +}; + + + + + + + +const getUserPosts = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const user_id = req.query.user_id + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userReqId = decodedToken.id + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }) + } + const user = await UserModel.findById(user_id) + + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + const response = {} + const options = { + page: req.query.page || 1, // صفحه پیش‌فرض ۱ + limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه + sort: { createdAt: -1 } + } + if (user_id.toString() === userReqId.toString()) { + // کاربر خودش است، همه پست‌هایش را بررسی می‌کند + const posts = await PostModel.paginate( + { user_id: user._id, status: { $in: ['pending', 'accept'] } }, // فیلتر + options // گزینه‌های پیجینیشن + ) + response.posts = posts.docs + response.postsCount = posts.totalDocs + response.totalPages = posts.totalPages // ارسال تعداد کل صفحات + response.totalItems = posts.totalDocs + } else { + // دیگران، فقط پست‌هایی که وضعیتشان "accept" است را ببینند + const posts = await PostModel.paginate( + { user_id: user._id, status: 'accept' }, // فیلتر + options // گزینه‌های پیجینیشن + ) + response.posts = posts.docs + response.postsCount = posts.totalDocs + response.totalPages = posts.totalPages // ارسال تعداد کل صفحات + response.totalItems = posts.totalDocs + } + return res.status(200).json({ data: response }) + } catch (error) { + next(error) + } +} +const getUserPostsWeb = async (req, res, next) => { + try { + let userReqId = null + + // دریافت توکن و بررسی معتبر بودنش (اگر وجود داشت) + const authHeader = req.header('Authorization') + if (authHeader) { + const token = authHeader.split(' ')[1] + try { + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + userReqId = decodedToken.id + } catch (err) { + console.warn('توکن نامعتبر است، ادامه بدون احراز هویت') // فقط هشدار، نه ارور + } + } + + const user_id = req.query.user_id + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }) + } + + const user = await UserModel.findById(user_id) + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + + const data = {} + const options = { + page: req.query.page || 1, + limit: req.query.limit || 10, + sort: { createdAt: -1 } + } + + if (userReqId && user_id.toString() === userReqId.toString()) { + // اگر کاربر لاگین کرده و درخواست برای خودش است، همه پست‌هایش را ببیند + const posts = await PostModel.paginate( + { user_id: user._id, status: { $in: ['pending', 'accept'] } }, + options + ) + data.posts = posts.docs + data.postsCount = posts.totalDocs + data.totalPages = posts.totalPages + data.totalItems = posts.totalDocs + } else { + // برای بقیه، فقط پست‌هایی که وضعیتشان "accept" است نمایش داده شود + const posts = await PostModel.paginate( + { user_id: user._id, status: 'accept' }, + options + ) + data.posts = posts.docs + data.postsCount = posts.totalDocs + data.totalPages = posts.totalPages + data.totalItems = posts.totalDocs + } + + return res.status(200).json(data) + } catch (error) { + next(error) + } +} + +module.exports = { + createPostValidationRules, + createPost, + getUserPosts, + getUserPostsWeb +} diff --git a/public/modstagram-back/controllers/application/profile/profileController.js b/public/modstagram-back/controllers/application/profile/profileController.js new file mode 100644 index 0000000..c127f5c --- /dev/null +++ b/public/modstagram-back/controllers/application/profile/profileController.js @@ -0,0 +1,139 @@ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + + +// GET user by ID from URL +const getUserById = async (req, res, next) => { + try { + const userId = req.params.id; // گرفتن آیدی از پارامتر URL + const service = req.query.services; + + const user = await UserModel.findById(userId); + if (!user) { + return res.status(404).json({ message: "کاربر مورد نظر یافت نشد" }); + } + + let isRegister = true; + // if ( + // !user.user_name || + // !user.first_name || + // !user.last_name || + // !user.user_type || + // !user.national_card_image || + // !user.password || + // !user.national_code + // ) { + // isRegister = false; + // } + + const response = { + _id: user._id, + user_type: user.user_type, + user_level: user.user_level, + first_name: user.first_name, + last_name: user.last_name, + user_name: user.user_name, + show_location: user.show_location, + is_verified: user.is_verified, + user_score: user.user_score, + rate: user.rate, + bio: user.bio, + height: user.height, + weight: user.weight, + size: user.size, + eye_color: user.eye_color, + hair_color: user.hair_color, + profile_image: user.profile_image, + lat: user.lat, + lng: user.lng, + address: user.address, + province: user.province, + city: user.city, + shaba: user.shaba, + national_code: user.national_code, + mobile: user.mobile, + cooperation_abroad: user.cooperation_abroad, + cooperation_type: user.cooperation_type, + conversation_projects: user.conversation_projects, + expertise: user.expertise, + sub_expertise: user.sub_expertise, + isRegister, + user, + services: service === "1" ? user.services : null + }; + + return res.status(200).json({ user: response }); + } catch (error) { + next(error); + } +}; + +const getProfile = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const service = req.query.services + + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const user = await UserModel.findById(userId) + let isRegister = true + if (!user.user_name || + !user.first_name || + !user.last_name || + !user.user_type || + !user.national_card_image || + !user.password || + !user.national_code + ) { + isRegister = false + } + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + const response = { + _id: user._id, + user_type: user.user_type, + user_level: user.user_level, + first_name: user.first_name, + last_name: user.last_name, + user_name: user.user_name, + show_location: user.show_location, + is_verified: user.is_verified, + is_Register: user.is_Register, + user_score: user.user_score, + rate: user.rate, + bio: user.bio, + height: user.height, + weight: user.weight, + size: user.size, + eye_color: user.eye_color, + hair_color: user.hair_color, + profile_image: user.profile_image, + lat: user.lat, + lng: user.lng, + address: user.address, + province: user.province, + city: user.city, + shaba: user.shaba, + national_code: user.national_code, + mobile: user.mobile, + cooperation_abroad: user.cooperation_abroad, + cooperation_type: user.cooperation_type, + conversation_projects: user.conversation_projects, + expertise: user.expertise, + sub_expertise: user.sub_expertise, + isRegister, + services: service === '1' ? user.services : null + } + return res.status(200).json({ user: response }) + } catch (error) { + next(error) + } +} + +module.exports = { + getProfile, + getUserById +}; diff --git a/public/modstagram-back/controllers/application/projects/createProjectController.js b/public/modstagram-back/controllers/application/projects/createProjectController.js new file mode 100644 index 0000000..c77c4a1 --- /dev/null +++ b/public/modstagram-back/controllers/application/projects/createProjectController.js @@ -0,0 +1,220 @@ +/* eslint-disable camelcase */ +const { ProvinceModel, CityModel } = require('../../../models/StateCity') +const ProjectModel = require('../../../models/ProjectModel') +const UserModel = require('../../../models/UserModel') +const { check, validationResult } = require('express-validator') +const jwt = require('jsonwebtoken') +const createProjectValidationRules = () => { + return [ + check('title').notEmpty().withMessage('عنوان نمی‌تواند خالی باشد'), + + check('expertise').notEmpty().withMessage('تخصص نمی‌تواند خالی باشد'), + + check('gender') + .isIn(['male', 'female']) + .withMessage('جنسیت باید male یا female باشد'), + + check('age').notEmpty().withMessage('سن نمی‌تواند خالی باشد'), + + check('conversation_projects') + .notEmpty() + .withMessage('پروژه‌های مکالمه نمی‌تواند خالی باشد') + .isBoolean() + .withMessage('مقدار پروژه‌های مکالمه باید یک مقدار boolean باشد'), + + check('province').notEmpty().withMessage('استان نمی‌تواند خالی باشد'), + + check('city').notEmpty().withMessage('شهر نمی‌تواند خالی باشد'), + + check('offer_time') + .notEmpty() + .withMessage('زمان پروژه نمی‌تواند خالی باشد'), + + check('offer_price') + .notEmpty() + .withMessage('قیمت پیشنهادی نمی‌تواند خالی باشد'), + + check('description') + .notEmpty() + .withMessage('توضیحات نمی‌تواند خالی باشد'), + + check('project_type') + .notEmpty() + .withMessage('نوع پروژه نمی‌تواند خالی باشد') + .isIn(['free', 'normal', 'force', 'highlight']) + .withMessage('نوع پروژه باید normal یا force یا highlight باشد') + ] +} + +const createProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(422).json({ + error: true, + message: 'شما دسترسی به این بخش ندارید' + }) + } + if (user.is_verified !== 'verified') { + return res.status(422).json({ + error: true, + message: 'مدارک شما تایید نشده است' + }) + } + // اعتبارسنجی درخواست + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + const { + title, + expertise, + sub_expertise, + gender, + age, + conversation_projects, + province, + city, + offer_time, + offer_price, + description, + project_type, + public_status, + created_for_user, + number_of_person + } = req.body + if ( + !title || + !expertise || + !age || + conversation_projects === null || + !province || + !city || + !offer_time || + !offer_price || + !description || + !project_type + ) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const provinceFind = await ProvinceModel.findOne( + { id: province }, + { _id: 0 } + ) + const cityFind = await CityModel.findOne({ id: city }) + // اگر پروژه برای یک کاربر خاص باید ساخته شود + if (public_status && public_status === 'private' && created_for_user) { + const createdUser = await UserModel.findById(created_for_user) + if (!createdUser) { + return res.status(422).json({ + error: true, message: 'کاربر مورد نظر برای ساخت پروژه یافت نشد' + }) + } + // ایجاد شیء پروژه + const projectData = { + title, + expertise, + sub_expertise, + gender, + age, + conversation_projects, + province, + city, + offer_time, + offer_price, + description, + project_type, + creator_id: user._id, // ارتباط با کاربر + public_status, + created_for_user + } + + // ساخت شیء پروژه + const project = new ProjectModel(projectData) + + // ذخیره کردن رکورد در پایگاه داده + await project.save() + + res.status(201).json({ message: 'پروژه با موفقیت ساخته شد', id: project._id } + ) + } else { + if (number_of_person > 1) { + for (let i = 1; i <= number_of_person; i++) { + let currentProjectType + + if (project_type === 'free' && i === 1) { + currentProjectType = 'free' + } else if (project_type === 'highlight' || project_type === 'force') { + currentProjectType = project_type + } else { + currentProjectType = 'normal' + } + + const newProject = new ProjectModel({ + title: `${title}_${i}`, + expertise, + sub_expertise, + gender, + age, + conversation_projects, + province: provinceFind, + city: cityFind, + offer_time, + offer_price, + description, + creator_id: user._id, // ارتباط با کاربر + project_type: currentProjectType, + public_status, + created_for_user + }) + + // ذخیره کردن رکورد در پایگاه داده + await newProject.save() + } + + res.status(201).json({ + message: 'پروژه‌ها با موفقیت ساخته شدند' + }) + } else { + const project = new ProjectModel({ + title, + expertise, + sub_expertise, + gender, + age, + conversation_projects, + province: provinceFind, + city: cityFind, + offer_time, + offer_price, + description, + creator_id: user._id, // ارتباط با کاربر + project_type + }) + + // ذخیره کردن رکورد در پایگاه داده + await project.save() + + res.status(201).json({ + message: 'پروژه با موفقیت ساخته شد', + id: project._id + }) + } + } + } catch (error) { + next(error) + } +} + +module.exports = { + createProjectValidationRules, + createProject +} diff --git a/public/modstagram-back/controllers/application/projects/getProjectController.js b/public/modstagram-back/controllers/application/projects/getProjectController.js new file mode 100644 index 0000000..b302743 --- /dev/null +++ b/public/modstagram-back/controllers/application/projects/getProjectController.js @@ -0,0 +1,406 @@ +/* eslint-disable camelcase */ +const { default: mongoose } = require('mongoose') +const ProjectModel = require('../../../models/ProjectModel') +const RequestModel = require('../../../models/RequestModel') +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') +const calculateRemainingTime = (milliseconds) => { + const days = Math.floor(milliseconds / (1000 * 60 * 60 * 24)) + const hours = Math.floor((milliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) + + return `${days} روز و ${hours} ساعت` +} +const getProjects = async (req, res, next) => { + try { + // eslint-disable-next-line no-unused-vars + const { expertise, page = 1, limit = 10, most_price, most_requests, age, gender } = req.query + // ساخت فیلتر برای استفاده در جستجوی MongoDB + const filter = { + payment_status: 'done', + status: 'accepted', + public_status: 'public', + $or: [ + { isExpired: false }, // پروژه‌هایی که isExpired برابر با false است + { isExpired: { $exists: false } } // پروژه‌هایی که فیلد isExpired وجود ندارد + ] + } + if (expertise) { + filter.expertise = expertise + } + if (age) { + filter.age = age + } + if (gender) { + filter.gender = gender + } + // استفاده از مدل پیجینیت شده برای دریافت نتایج صفحه‌بندی شده + + if (most_price || most_requests) { + // دریافت لیست پروژه‌ها با استفاده از فیلتر و گزینه‌های صفحه‌بندی + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: most_price === 'true' ? { offer_price: -1 } : { requested_users: 'desc' } + } + const projects = await ProjectModel.paginate(filter, options) + + const newProj = projects.docs + res.status(200).json({ + projects: newProj, + totalPages: projects.totalPages, // ارسال تعداد کل صفحات + totalItems: projects.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } else { + // دریافت لیست پروژه‌ها با استفاده از فیلتر و گزینه‌های صفحه‌بندی + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: { acceptedAt: -1, createdAt: -1 } // مرتب‌سازی بر اساس acceptedAt و سپس createdAt + } + const projects = await ProjectModel.paginate(filter, options) + const newProj = projects.docs + res.status(200).json({ + projects: newProj, + totalPages: projects.totalPages, // ارسال تعداد کل صفحات + totalItems: projects.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } + } catch (error) { + next(error) + } + // try { + // const token = req.header('Authorization').split(' ')[1] + // if (!token) return res.status(401).send('Access Denied') + + // // eslint-disable-next-line no-unused-vars + // const decodedToken = jwt.verify(token, process.env.APP_SECRET) + + // const { expertise, page = 1, limit = 10 } = req.query // افزودن پارامترهای صفحه‌بندی به درخواست + + // // ساخت فیلتر برای استفاده در جستجوی MongoDB + // const filter = { + // payment_status: 'done', + // status: 'accepted', + // public_status: 'public' + // } // افزودن شرط‌های دیگر برای فیلتر + + // if (expertise) { + // filter.expertise = expertise + // } + + // // استفاده از مدل پیجینیت شده برای دریافت نتایج صفحه‌بندی شده + // const options = { + // page: parseInt(page), // تبدیل صفحه به عدد صحیح + // limit: parseInt(limit) // تبدیل محدودیت به عدد صحیح + // } + + // // دریافت لیست پروژه‌ها با استفاده از فیلتر و گزینه‌های صفحه‌بندی + // const projects = await ProjectModel.paginate(filter, options) + + // // تبدیل نتایج به فرمت مورد نیاز + // const projectsWithUserInfo = await Promise.all(projects.docs.map(async project => { + // const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate') + // const projectWithUserInfo = { + // ...project.toJSON(), // تبدیل آبجکت پروژه به JSON + // creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه + // } + + // // محاسبه مدت زمان باقی‌مانده برای هر پروژه + // const currentTime = new Date() + // const projectCreatedAt = new Date(project.createdAt) + // const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt) + // const remainingTime = calculateRemainingTime(timeDiff) + // projectWithUserInfo.remainingTime = remainingTime + + // return projectWithUserInfo + // })) + + // res.status(200).json({ + // projects: projectsWithUserInfo, + // totalPages: projects.totalPages, // ارسال تعداد کل صفحات + // totalItems: projects.totalDocs // ارسال تعداد کل آیتم‌ها + // }) + // } catch (error) { + // next(error) + // } +} +const getUserProjects = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const user_id = req.query.user_id + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + // const userReqId = decodedToken.id + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }) + } + const user = await UserModel.findById(user_id) + + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + const response = {} + if (user.user_type === 'user') { + const options = { + page: req.query.page || 1, // صفحه پیش‌فرض ۱ + limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه + sort: { createdAt: -1 } + } + + // پیجینیشن بر روی لیست پروژه‌های کاربر اعمال می‌شود + const projects = await ProjectModel.paginate( + { selected_user: user._id, status: 'done' }, // فیلتر + options // گزینه‌های پیجینیشن + ) + response.projects = projects.docs + response.totalPages = projects.totalPages // ارسال تعداد کل صفحات + response.totalItems = projects.totalDocs // ارسال تعداد کل آیتم‌ها + response.allProjectsCount = await ProjectModel.countDocuments({ selected_user: user._id }) + const completedProjects = await Promise.all([ + ProjectModel.countDocuments({ selected_user: user._id, status: 'done' }) + ]) + response.successfulProjects = completedProjects + } else { + const options = { + page: req.query.page || 1, // صفحه پیش‌فرض ۱ + limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه + sort: { createdAt: -1 } + } + + // پیجینیشن بر روی لیست پروژه‌های کاربر اعمال می‌شود + const projects = await ProjectModel.paginate( + { creator_id: user._id, status: { $in: ['done', 'accepted'] } }, // فیلتر + options // گزینه‌های پیجینیشن + ) + response.projects = projects.docs + response.totalPages = projects.totalPages // ارسال تعداد کل صفحات + response.totalItems = projects.totalDocs + response.allProjectsCount = await ProjectModel.countDocuments({ creator_id: user._id, payment_status: 'done' }) + // تعداد پروژه‌های موفق را به دست آورید + const successfulProjects = await ProjectModel.countDocuments({ creator_id: user._id, status: 'done' }) + response.successfulProjects = successfulProjects + } + return res.status(200).json({ data: response }) + } catch (error) { + next(error) + } +} +const getUserProjectsWeb = async (req, res, next) => { + try { + const user_id = req.query.user_id + // eslint-disable-next-line no-unused-vars + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }) + } + const user = await UserModel.findById(user_id) + + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + const data = {} + if (user.user_type === 'user') { + const options = { + page: req.query.page || 1, // صفحه پیش‌فرض ۱ + limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه + sort: { createdAt: -1 } + } + + // پیجینیشن بر روی لیست پروژه‌های کاربر اعمال می‌شود + const projects = await ProjectModel.paginate( + { selected_user: user._id, status: 'done' }, // فیلتر + options // گزینه‌های پیجینیشن + ) + data.projects = projects.docs + data.totalPages = projects.totalPages // ارسال تعداد کل صفحات + data.totalItems = projects.totalDocs // ارسال تعداد کل آیتم‌ها + data.allProjectsCount = await ProjectModel.countDocuments({ selected_user: user._id }) + const completedProjects = await Promise.all([ + ProjectModel.countDocuments({ selected_user: user._id, status: 'done' }) + ]) + data.successfulProjects = completedProjects + } else { + const options = { + page: req.query.page || 1, // صفحه پیش‌فرض ۱ + limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه + sort: { createdAt: -1 } + } + + // پیجینیشن بر روی لیست پروژه‌های کاربر اعمال می‌شود + const projects = await ProjectModel.paginate( + { creator_id: user._id, status: { $in: ['done', 'accepted'] } }, // فیلتر + options // گزینه‌های پیجینیشن + ) + data.projects = projects.docs + data.totalPages = projects.totalPages // ارسال تعداد کل صفحات + data.totalItems = projects.totalDocs + data.allProjectsCount = await ProjectModel.countDocuments({ creator_id: user._id, payment_status: 'done' }) + // تعداد پروژه‌های موفق را به دست آورید + const successfulProjects = await ProjectModel.countDocuments({ creator_id: user._id, status: 'done' }) + data.successfulProjects = successfulProjects + } + return res.status(200).json(data) + } catch (error) { + next(error) + } +} +const getSingleProjects = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const projectId = req.params.projectId + const projectRequests = await RequestModel.find({ project: projectId }) + .populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image') + .sort({ status: 1 }) + .lean() + const modifiedRequests = projectRequests.map(request => ({ + ...request, + time: request.user._id.toString() === userId ? request.time : null, + price: request.user._id.toString() === userId ? request.price : null + })) + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' }) + } + // محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده + // تابع محاسبه مبلغ پرداخت شده + const getTotalPaidAmount = (installments) => { + let totalPaidAmount = 0 + installments.forEach(installment => { + totalPaidAmount += installment.amount + }) + return totalPaidAmount + } + + // تابع محاسبه مبلغ باقیمانده + const getRemainingAmount = (project) => { + const totalPaidAmount = getTotalPaidAmount(project.installments) + const remainingAmount = project.final_price - totalPaidAmount + return remainingAmount + } + + const totalPaidAmount = getTotalPaidAmount(project.installments) + const remainingAmount = getRemainingAmount(project) + // اطلاعات کاربر سازنده را نیز دریافت کنید و به آبجکت پروژه اضافه کنید + const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate') + + const projectWithUserInfo = { + ...project._doc, + creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه + } + const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score') + projectWithUserInfo.selected_user = selectedUser + // محاسبه مدت زمان باقی‌مانده برای پروژه + const currentTime = new Date() + const projectCreatedAt = new Date(project.createdAt) + const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt) + const remainingTime = calculateRemainingTime(timeDiff) + projectWithUserInfo.remainingTime = remainingTime + let projectDetails = projectWithUserInfo + if ((project.selected_user && project.selected_user.toString()) === userId || project.creator_id.toString() === userId) { + projectDetails = { + ...projectWithUserInfo, + total_paid_amount: totalPaidAmount, + remaining_amount: remainingAmount + } + } else { + projectDetails = + projectWithUserInfo + } + // } + res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests }) + } catch (error) { + next(error) + } +} +const getSingleProjectsWeb = async (req, res, next) => { + try { + let userId = null + let token = req.header('Authorization') + + if (token) { + try { + token = token.split(' ')[1] + if (token) { + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + userId = decodedToken.id + } + } catch (err) { + console.warn('Invalid token:', err.message) + } + } + + const projectId = req.params.projectId + const projectRequests = await RequestModel.find({ project: projectId }) + .populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image') + .sort({ status: 1 }) + .lean() + + // اگر کاربر لاگین کرده باشد، زمان و قیمت را نشان بده، در غیر این صورت حذف کن + const modifiedRequests = projectRequests.map(request => ({ + ...request, + time: userId && request.user._id.toString() === userId ? request.time : null, + price: userId && request.user._id.toString() === userId ? request.price : null + })) + + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' }) + } + + // محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده + const getTotalPaidAmount = (installments) => { + return installments.reduce((total, installment) => total + installment.amount, 0) + } + + const getRemainingAmount = (project) => { + return project.final_price - getTotalPaidAmount(project.installments) + } + + const totalPaidAmount = getTotalPaidAmount(project.installments) + const remainingAmount = getRemainingAmount(project) + + // دریافت اطلاعات سازنده پروژه + const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate') + + const projectWithUserInfo = { + ...project._doc, + creator + } + + // دریافت اطلاعات کاربر منتخب در صورت وجود + const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score') + projectWithUserInfo.selected_user = selectedUser + + // محاسبه زمان باقی‌مانده برای پیشنهادات پروژه + const currentTime = new Date() + const projectCreatedAt = new Date(project.createdAt) + const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt) + projectWithUserInfo.remainingTime = calculateRemainingTime(timeDiff) + + let projectDetails = projectWithUserInfo + + // فقط اگر کاربر احراز هویت شده باشد و سازنده یا برنده پروژه باشد، اطلاعات مالی را برگردان + if (userId && (project.selected_user?.toString() === userId || project.creator_id.toString() === userId)) { + projectDetails = { + ...projectWithUserInfo, + total_paid_amount: totalPaidAmount, + remaining_amount: remainingAmount + } + } + + res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests }) + } catch (error) { + next(error) + } +} + +// const projectDetails = await ProjectModel.findById(projectId).populate('requested_users', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image') // جزییات درخواست‌های کاربران + +module.exports = { + getProjects, getSingleProjects, getUserProjects, getUserProjectsWeb, getSingleProjectsWeb +} diff --git a/public/modstagram-back/controllers/application/projects/projectTypesController.js b/public/modstagram-back/controllers/application/projects/projectTypesController.js new file mode 100644 index 0000000..14d9b05 --- /dev/null +++ b/public/modstagram-back/controllers/application/projects/projectTypesController.js @@ -0,0 +1,41 @@ +const TypeAndPriceModel = require('../../../models/TypeAndPriceModel') +const jwt = require('jsonwebtoken') +const UserModel = require('../../../models/UserModel') + +const getProjectTypes = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const user = await UserModel.findById(userId) + if (!user) { + return res.status(422).json({ + error: true, + message: 'کاربر یافت نشد' + }) + } + // درخواست انواع پروژه از دیتابیس + let projectTypes = await TypeAndPriceModel.find({}, 'name price') + + // بررسی برای مواردی مانند پیدا نشدن انواع پروژه + if (!projectTypes) { + return res.status(404).json({ message: 'انواع پروژه یافت نشد.' }) + } + // اگر کاربر درخواست رایگان روزانه نداشته باشد، نوع پروژه رایگان را حذف کنید + if (user.daily_free_request <= 0) { + projectTypes = projectTypes.filter(projectType => projectType.name !== 'free') + } + // ارسال انواع پروژه به کاربر + res.status(200).json({ projectTypes }) + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error('Error in getProjectTypes:', error) + res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' }) + } +} + +module.exports = { + getProjectTypes +} diff --git a/public/modstagram-back/controllers/application/projects/requestProjectController.js b/public/modstagram-back/controllers/application/projects/requestProjectController.js new file mode 100644 index 0000000..2c08a5a --- /dev/null +++ b/public/modstagram-back/controllers/application/projects/requestProjectController.js @@ -0,0 +1,195 @@ +/* eslint-disable camelcase */ +const { default: axios } = require('axios') +const NotificationModel = require('../../../models/NotificationModel') +const ProjectModel = require('../../../models/ProjectModel') +const RequestModel = require('../../../models/RequestModel') +const UserModel = require('../../../models/UserModel') +const { check, validationResult } = require('express-validator') +const jwt = require('jsonwebtoken') +const requestProjectValidationRules = () => { + return [ + check('project_id') + .notEmpty().withMessage('آیدی پروژه نمی‌تواند خالی باشد'), + check('request_time') + .notEmpty().withMessage('زمان پروژه نمی‌تواند خالی باشد'), + + check('offer_price') + .notEmpty().withMessage('قیمت پیشنهادی نمی‌تواند خالی باشد') + ] +} + +const requestProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user || user.user_type !== 'user') { + return res.status(422).json({ + error: true, message: 'شما دسترسی به این بخش ندارید' + }) + } + if (user.is_verified !== 'verified') { + return res.status(422).json({ + error: true, message: 'مدارک شما تایید نشده است' + }) + } + // اعتبارسنجی درخواست + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + const { request_time, offer_price, project_id } = req.body + if (!project_id || !offer_price || !request_time + ) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + // چک کردن برای وجود درخواست قبلی + const existingRequest = await RequestModel.findOne({ project: project_id, user: user._id }) + if (existingRequest) { + return res.status(422).json({ + error: true, + message: 'شما قبلاً برای این پروژه درخواست داده‌اید' + }) + } + // ایجاد یک درخواست جدید + const request = new RequestModel({ + project: project_id, + user: user._id, + time: request_time, + price: offer_price + }) + await request.save() + + // ثبت اعلان برای سازنده پروژه + const project = await ProjectModel.findById(project_id) + const creatorId = project.creator_id + + const notification = new NotificationModel({ + user_id: creatorId, + project_post_id: project_id, + type: 'request', + title: 'پیشنهاد جدید', + description: `کاربر ${user.user_name} یک پیشنهاد جدید برای پروژه شما ارسال کرده است.` + }) + await notification.save() + + const userReciver = await UserModel.findById(project.creator_id) + + const data = JSON.stringify({ + mobile: userReciver?.mobile, + templateId: '876533', + parameters: [ + { name: 'EMPLOYER', value: userReciver?.first_name + ' ' + userReciver?.last_name }, + { name: 'PROJECT', value: project?.title } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + axios(config) + .then(function (response) { + }) + .catch(function (error) { + console.log(error) + }) + + // به روز رسانی پروژه با افزودن کاربر به لیست کاربران درخواست دهنده + const updatedProject = await ProjectModel.findOneAndUpdate( + { _id: project_id }, + { $push: { requested_users: user._id } }, + { new: true } + ) + + if (!updatedProject) { + console.error('Error adding requested user: Project not found') + return res.status(404).json({ error: true, message: 'پروژه پیدا نشد' }) + } + + res.status(201).json({ message: 'درخواست با موفقیت شد', id: project_id } + ) + } catch (error) { + next(error) + } +} + +const editRequestProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user || user.user_type !== 'user') { + return res.status(422).json({ + error: true, message: 'شما دسترسی به این بخش ندارید' + }) + } + if (user.is_verified !== 'verified') { + return res.status(422).json({ + error: true, message: 'مدارک شما تایید نشده است' + }) + } + // اعتبارسنجی درخواست + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + const { request_time, offer_price, project_id } = req.body + if (!project_id || !offer_price || !request_time + ) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + // چک کردن برای وجود درخواست قبلی + const existingRequest = await RequestModel.findOne({ project: project_id, user: user._id }) + if (!existingRequest) { + return res.status(422).json({ + error: true, + message: 'شما قبلاً برای این پروژه درخواست نداده‌اید' + }) + } + // اکنون می‌توانید اطلاعات درخواست را ویرایش کنید + existingRequest.time = request_time + existingRequest.price = offer_price + await existingRequest.save() + + // ثبت اعلان برای سازنده پروژه + const project = await ProjectModel.findById(project_id) + const creatorId = project.creator_id + + const notification = new NotificationModel({ + user_id: creatorId, + project_post_id: project_id, + type: 'request', + title: 'ویرایش پیشنهاد', + description: `کاربر ${user.user_name} پیشنهاد خود را ویرایش کرد.` + }) + await notification.save() + res.status(200).json({ + message: 'درخواست با موفقیت ویرایش شد', + id: project_id + }) + } catch (error) { + next(error) + } +} +const acceptProject = async (req, res, next) => { } +module.exports = { + requestProjectValidationRules, + requestProject, + acceptProject, + editRequestProject +} diff --git a/public/modstagram-back/controllers/application/projects/updateProjectController.js b/public/modstagram-back/controllers/application/projects/updateProjectController.js new file mode 100644 index 0000000..0caa0c6 --- /dev/null +++ b/public/modstagram-back/controllers/application/projects/updateProjectController.js @@ -0,0 +1,381 @@ +/* eslint-disable camelcase */ +const ProjectModel = require('../../../models/ProjectModel') +const jwt = require('jsonwebtoken') +const UserModel = require('../../../models/UserModel') +const { check, validationResult } = require('express-validator') +const { ProvinceModel, CityModel } = require('../../../models/StateCity') +const NotificationModel = require('../../../models/NotificationModel') +const CommentModel = require('../../../models/CommentModel') + +const doneProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { project_id, comment, rate, user_id } = req.body + if (!project_id || !comment || !rate || !user_id) { + return res.status(400).send({ message: 'All fields are required' }) + } + + const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId }) + if (!project) { + return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' }) + } + + const getTotalPaidAmount = (installments) => { + return installments.reduce((total, installment) => total + installment.amount, 0) + } + + const getRemainingAmount = (project) => { + const totalPaidAmount = getTotalPaidAmount(project.installments) + return project.final_price - totalPaidAmount + } + + const remainingAmount = getRemainingAmount(project) + if (remainingAmount !== 0) { + return res.status(422).send({ message: 'مبلغ کامل پرداخت نشده است' }) + } + + project.status = 'done' + await project.save() + + const newComment = new CommentModel({ + user: user_id, + project: project_id, + creator: userId, + rating: rate, + comment, + comment_for: 'user', + status: 'pending' + }) + await newComment.save() + + const user = await UserModel.findById(user_id) + + // پیدا کردن کامنت‌ها و محاسبه‌ی امتیاز کل + const comments = await CommentModel.find({ user: user_id, comment_for: 'user' }) + const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0)) + + let userLevel + if (user.expertise === 'مدل') { + if (totalRating <= 50) userLevel = 'تازه وارد' + else if (totalRating <= 100) userLevel = 'استاندارد' + else if (totalRating <= 300) userLevel = 'حرفه‌ای' + else userLevel = 'استاد' + } else if (['زیبایی', 'عکاس'].includes(user.expertise)) { + if (totalRating <= 50) userLevel = 'تازه وارد' + else if (totalRating <= 100) userLevel = 'استاندارد' + else if (totalRating <= 300) userLevel = 'حرفه‌ای' + else userLevel = 'استاد' + } + + user.user_score = totalRating + user.user_level = userLevel + + const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' }) + const averageRating = totalRating / totalComments + user.rate = averageRating.toFixed(1) + await user.save() + + const notification = new NotificationModel({ + user_id: user._id, + project_post_id: project_id, + type: 'end_project', + title: 'اتمام پروژه', + description: `کارفرما پروژه ${project?.title} را به وضعیت انجام شده تغییر داد و برای شما نظر ثبت کرد(برای ثبت نظر لمس کنید) +نظر کارفرما : ${comment} + ` + }) + await notification.save() + + res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' }) + } catch (error) { + next(error) + } +} +const doneProjectWeb = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { project_id, comment, rate, user_id } = req.body + if (!project_id || !comment || !rate || !user_id) { + return res.status(400).send({ message: 'All fields are required' }) + } + + const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId }) + if (!project) { + return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' }) + } + + project.status = 'done' + await project.save() + + const newComment = new CommentModel({ + user: user_id, + project: project_id, + creator: userId, + rating: rate, + comment, + comment_for: 'user', + status: 'pending' + }) + await newComment.save() + + const user = await UserModel.findById(user_id) + + // پیدا کردن کامنت‌ها و محاسبه‌ی امتیاز کل + const comments = await CommentModel.find({ user: user_id, comment_for: 'user' }) + const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0)) + + let userLevel + if (user.expertise === 'مدل') { + if (totalRating <= 50) userLevel = 'تازه وارد' + else if (totalRating <= 100) userLevel = 'استاندارد' + else if (totalRating <= 300) userLevel = 'حرفه‌ای' + else userLevel = 'استاد' + } else if (['زیبایی', 'عکاس'].includes(user.expertise)) { + if (totalRating <= 50) userLevel = 'تازه وارد' + else if (totalRating <= 100) userLevel = 'استاندارد' + else if (totalRating <= 300) userLevel = 'حرفه‌ای' + else userLevel = 'استاد' + } + + user.user_score = totalRating + user.user_level = userLevel + + const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' }) + const averageRating = totalRating / totalComments + user.rate = averageRating.toFixed(1) + await user.save() + + const notification = new NotificationModel({ + user_id: user._id, + project_post_id: project_id, + type: 'end_project', + title: 'اتمام پروژه', + description: `کارفرما پروژه ${project?.title} را به وضعیت انجام شده تغییر داد و برای شما نظر ثبت کرد(برای ثبت نظر لمس کنید) +نظر کارفرما : ${comment} + ` + }) + await notification.save() + + res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' }) + } catch (error) { + next(error) + } +} + +const cancleProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { project_id, comment, rate, user_id } = req.body + + if (!project_id || !comment || !rate || !user_id) { + return res.status(400).send({ message: 'All fields are required' }) + } + + const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId }) + if (!project) { + return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' }) + } + + project.status = 'cancled' + await project.save() + + const newComment = new CommentModel({ + user: user_id, + project: project_id, + creator: userId, + rating: rate, + comment, + comment_for: 'project', + status: 'pending' + }) + await newComment.save() + + res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' }) + } catch (error) { + next(error) + } +} + +const editProjectValidationRules = () => { + return [ + check('title').notEmpty().withMessage('عنوان نمی‌تواند خالی باشد'), + + check('expertise').notEmpty().withMessage('تخصص نمی‌تواند خالی باشد'), + + check('gender') + .isIn(['male', 'female']) + .withMessage('جنسیت باید male یا female باشد'), + + check('age').notEmpty().withMessage('سن نمی‌تواند خالی باشد'), + + check('conversation_projects') + .notEmpty() + .withMessage('پروژه‌های مکالمه نمی‌تواند خالی باشد') + .isBoolean() + .withMessage('مقدار پروژه‌های مکالمه باید یک مقدار boolean باشد'), + + check('province').notEmpty().withMessage('استان نمی‌تواند خالی باشد'), + + check('city').notEmpty().withMessage('شهر نمی‌تواند خالی باشد'), + + check('offer_time') + .notEmpty() + .withMessage('زمان پروژه نمی‌تواند خالی باشد'), + + check('offer_price') + .notEmpty() + .withMessage('قیمت پیشنهادی نمی‌تواند خالی باشد'), + + check('description') + .notEmpty() + .withMessage('توضیحات نمی‌تواند خالی باشد') + ] +} + +const editProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(422).json({ + error: true, + message: 'شما دسترسی به این بخش ندارید' + }) + } + if (user.is_verified !== 'verified') { + return res.status(422).json({ + error: true, + message: 'مدارک شما تایید نشده است' + }) + } + + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + + const { + title, + expertise, + sub_expertise, + gender, + age, + conversation_projects, + province, + city, + offer_time, + offer_price, + description, + projectId + } = req.body + + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ + error: true, + message: 'پروژه مورد نظر یافت نشد' + }) + } + // eslint-disable-next-line eqeqeq + if (user._id.toString() != project.creator_id.toString()) { + return res.status(422).json({ + error: true, + message: 'شما نمیتوانید این پروژه را ویرایش کنید' + }) + } + if (project.status !== 'paid' && project.status !== 'pre_payment') { + return res.status(422).json({ + error: true, + message: 'شما نمیتوانید این پروژه را ویرایش کنید' + }) + } + // اعتبارسنجی اطلاعات ویرایش شده + if ( + !title || + !expertise || + !age || + conversation_projects === null || + !province || + !city || + !offer_time || + !offer_price || + !description + ) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + const provinceFind = await ProvinceModel.findOne( + { id: province }, + { _id: 0 } + ) + const cityFind = await CityModel.findOne({ id: city }) + // ویرایش یک نسخه از پروژه + project.title = title + project.expertise = expertise + project.sub_expertise = sub_expertise + project.gender = gender + project.age = age + project.conversation_projects = conversation_projects + project.province = provinceFind + project.city = cityFind + project.offer_time = offer_time + project.offer_price = offer_price + project.description = description + // ذخیره کردن تغییرات در پایگاه داده + await project.save() + res.status(200).json({ + message: 'پروژه با موفقیت ویرایش شد', + id: project._id + }) + } catch (error) { + next(error) + } +} +const setRateProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { project_id, comment, rate } = req.body + const project = await ProjectModel.findOne({ _id: project_id, selected_user: userId }) + if (!project) { + return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' }) + } + project.ratings.push({ + project_id, + rating: rate, + comment, + creator_id: userId + }) + await project.save() + + res.status(200).json({ message: 'نظر شما با موفقیت ثبت شد.' }) + } catch (error) { + next(error) + } +} +module.exports = { + doneProject, cancleProject, editProject, editProjectValidationRules, setRateProject, doneProjectWeb +} diff --git a/public/modstagram-back/controllers/application/provincesController.js b/public/modstagram-back/controllers/application/provincesController.js new file mode 100644 index 0000000..11ab4a3 --- /dev/null +++ b/public/modstagram-back/controllers/application/provincesController.js @@ -0,0 +1,15 @@ +const { ProvinceModel } = require('../../models/StateCity') + +const getProvinces = async (req, res, next) => { + try { + const provinces = await ProvinceModel.find({}) + res.status(200).json({ + provinces + }) + } catch (err) { + res.status(500).send('Internal Server Error') + } +} +module.exports = { + getProvinces +} diff --git a/public/modstagram-back/controllers/application/register/registerController.js b/public/modstagram-back/controllers/application/register/registerController.js new file mode 100644 index 0000000..fbb2ce6 --- /dev/null +++ b/public/modstagram-back/controllers/application/register/registerController.js @@ -0,0 +1,89 @@ +const { default: axios } = require('axios') +const UserModel = require('../../../models/UserModel') +const { check, validationResult } = require('express-validator') +// const { Token, VerificationCode } = require('sms-ir') + +const registerValidationRules = () => { + return [ + check('mobile') + .notEmpty().withMessage('شماره موبایل نمی‌تواند خالی باشد') + .isLength({ min: 11, max: 11 }).withMessage('شماره موبایل باید دقیقاً 11 رقم باشد') + .matches(/^09[0-9]{9}$/).withMessage('فرمت شماره موبایل صحیح نیست') + ] +} + +const registerUser = async (req, res, next) => { + try { + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + + const { mobile } = req.body + if (!mobile) { + return res.status(422).json({ + error: true, + message: 'شماره موبایل نمی‌تواند خالی باشد' + }) + } + + const existingUser = await UserModel.findOne({ mobile }) + if (existingUser && existingUser.national_code !== null) { + return res.status(422).json({ error: true, message: 'شماره موبایل تکراری است' }) + } + function generateOTP () { + return Math.floor(100000 + Math.random() * 900000) + } + + const otp = generateOTP() + // eslint-disable-next-line no-unused-vars + const user = await UserModel.findOneAndUpdate( + { mobile }, + { $set: { mobile, otp } }, + { upsert: true, new: true, lean: true } + ) + setTimeout(() => { + UserModel.findOneAndUpdate({ mobile }, { $set: { otp: null } }, { new: true }) + .then(() => {}) + .catch(error => console.error('Error setting OTP to null:', error)) + }, 5 * 60 * 1000) + const data = JSON.stringify({ + mobile, + templateId: '930719', + parameters: [ + { name: 'CODE', value: otp.toString() } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + + axios(config) + .then(function (response) { + // console.log(JSON.stringify(response.data)) + }) + .catch(function (error) { + console.log(error) + }) + + res.status(200).json({ + success: true, + message: 'کد تایید ارسال شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + registerValidationRules, + registerUser +} diff --git a/public/modstagram-back/controllers/application/register/userFullNameController.js b/public/modstagram-back/controllers/application/register/userFullNameController.js new file mode 100644 index 0000000..7f5b22e --- /dev/null +++ b/public/modstagram-back/controllers/application/register/userFullNameController.js @@ -0,0 +1,51 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const { check, validationResult } = require('express-validator') +const jwt = require('jsonwebtoken') + +const setUserFullNameValidationRules = () => { + return [ + check('first_name') + .notEmpty().withMessage('نام نمی‌تواند خالی باشد'), + check('last_name') + .notEmpty().withMessage('نام خانوادگی نمی‌تواند خالی باشد') + ] +} + +const setUserFullName = async (req, res, next) => { + try { + const { first_name, last_name } = req.body + + // اعتبارسنجی داده‌های ورودی + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + // آپدیت نام کاربری به صورت lowercase + user.first_name = first_name.toLowerCase() + user.last_name = last_name.toLowerCase() + await user.save() + + return res.json({ + message: 'نام و نام خانوادگی با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + setUserFullName, setUserFullNameValidationRules +} diff --git a/public/modstagram-back/controllers/application/register/userTypeController.js b/public/modstagram-back/controllers/application/register/userTypeController.js new file mode 100644 index 0000000..50cdaf5 --- /dev/null +++ b/public/modstagram-back/controllers/application/register/userTypeController.js @@ -0,0 +1,44 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setUserType = async (req, res, next) => { + try { + const { user_type } = req.body + if (!user_type || !['user', 'employer'].includes(user_type)) { + return res.status(422).json({ + error: true, + message: 'نوع یوزر معتبر نیست' + }) + } + + // جستجوی کاربر با شماره موبایل ارسالی + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + // آپدیت نوع یوزر + user.user_type = user_type.toLowerCase() + await user.save() + + return res.json({ + message: 'نوع کاربر با موفقیت به‌روزرسانی شد', + id: user._id + }) + } catch (error) { + next(error) + } +} + +module.exports = { + setUserType +} diff --git a/public/modstagram-back/controllers/application/register/usernameController.js b/public/modstagram-back/controllers/application/register/usernameController.js new file mode 100644 index 0000000..23ead69 --- /dev/null +++ b/public/modstagram-back/controllers/application/register/usernameController.js @@ -0,0 +1,95 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setUserName = async (req, res, next) => { + try { + const { mobile, user_name } = req.body + if (!mobile || !user_name) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + // جستجوی کاربر با شماره موبایل ارسالی + const user = await UserModel.findOne({ mobile }) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + // بررسی حداقل طول نام کاربری + if (user_name.length < 5) { + return res.status(422).json({ + error: true, + message: 'نام کاربری باید حداقل 5 کاراکتر باشد' + }) + } + // بررسی محدودیت‌های مجاز در نام کاربری + // const usernameRegex = /^[a-zA-Z0-9_]+$/ + // if (!usernameRegex.test(user_name)) { + // return res.status(422).json({ + // error: true, + // message: 'نام کاربری فقط می‌تواند شامل حروف الفبای انگلیسی، اعداد و کاراکتر _ باشد' + // }) + // } + // بررسی تکراری بودن user_name + const existingUser = await UserModel.findOne({ user_name: { $regex: new RegExp('^' + user_name + '$', 'i') } }) + if (existingUser && existingUser._id.toString() !== user._id.toString()) { + return res.status(422).json({ + error: true, + message: 'نام کاربری تکراری است' + }) + } + + // آپدیت نام کاربری به صورت lowercase + user.user_name = user_name.toLowerCase() + await user.save() + + return res.json({ + message: 'نام کاربری با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +const updateUserName = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { user_name } = req.body + + if (!user_name) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const user = await UserModel.findByIdAndUpdate(userId, { user_name }, { new: true }) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شناسه یافت نشد' + }) + } + + return res.json({ + message: 'نام کاربری با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + setUserName, updateUserName +} diff --git a/public/modstagram-back/controllers/application/register/verifyController.js b/public/modstagram-back/controllers/application/register/verifyController.js new file mode 100644 index 0000000..95989cc --- /dev/null +++ b/public/modstagram-back/controllers/application/register/verifyController.js @@ -0,0 +1,47 @@ +const UserModel = require('../../../models/UserModel') +const TokenService = require('../../../services/TokenService') +// const jwt = require('jsonwebtoken') + +const verifyUser = async (req, res, next) => { + try { + const { mobile, otp } = req.body + if (!mobile || !otp) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const user = await UserModel.findOne({ mobile }) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + const token = TokenService.sign({ id: user._id }) + let step = '' + if (user.user_name === null) { step = 'user_name' } else if + (!user.password) { step = 'password' } else if + (!user.first_name) { step = 'first_name' } else if + (!user.user_type) { step = 'user_type' } else { step = 'profile_image' } + if (user.otp === otp) { + return res.json({ + message: 'کد تایید صحیح بود', + token, + step + }) + } + + return res.status(422).json({ + error: true, + message: 'کد تایید اشتباه است' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + verifyUser +} diff --git a/public/modstagram-back/controllers/application/search-web/searchController.js b/public/modstagram-back/controllers/application/search-web/searchController.js new file mode 100644 index 0000000..5790ba1 --- /dev/null +++ b/public/modstagram-back/controllers/application/search-web/searchController.js @@ -0,0 +1,52 @@ +const ProjectModel = require('../../../models/ProjectModel') +const UserModel = require('../../../models/UserModel') +const getSearch = async (req, res, next) => { + try { + const { search, type, page = 1, limit = 10 } = req.query + let result + const selectedFields = '_id user_name first_name last_name user_type is_verified profile_image expertise rate user_level user_score' + let filter + let totalPages + let totalItems + if (search) { + if (!type) { + res.status(422).json({ success: false, message: 'نوع جستجو را مشخص کنید' }) + } else if (type === 'project') { + // جستجو در مدل Project با فیلتر کردن برای user_type === "employer" + + filter = { $or: [{ title: new RegExp(search, 'i'), status: 'accepted' }, { description: new RegExp(search, 'i'), status: 'accepted' }] } + result = await ProjectModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), sort: { createdAt: -1 } }) + totalPages = result?.totalPages + totalItems = result?.totalDocs + } else if (type === 'user') { + // جستجو در مدل User با فیلتر کردن برای user_type === "user" + filter = { user_type: 'user', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] } + result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields }) + totalPages = result?.totalPages + totalItems = result?.totalDocs + } else if (type === 'employer') { + // جستجو در مدل User با فیلتر کردن برای user_type === "employer" + filter = { user_type: 'employer', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] } + result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields }) + totalPages = result?.totalPages + totalItems = result?.totalDocs + } + + res.status(200).json({ + success: true, + result: result?.docs, + type, + totalPages, + totalItems + }) + } else { + res.status(422).json({ success: false, message: 'چیزی تایپ کنید' }) + } + } catch (error) { + next(error) + } +} + +module.exports = { + getSearch +} diff --git a/public/modstagram-back/controllers/application/search/searchController.js b/public/modstagram-back/controllers/application/search/searchController.js new file mode 100644 index 0000000..b099c3f --- /dev/null +++ b/public/modstagram-back/controllers/application/search/searchController.js @@ -0,0 +1,51 @@ +const ProjectModel = require('../../../models/ProjectModel') +const UserModel = require('../../../models/UserModel') +const getSearch = async (req, res, next) => { + try { + const { search, type, page = 1, limit = 10 } = req.query + let result + const selectedFields = '_id user_name first_name last_name user_type is_verified profile_image expertise rate user_level user_score' + let filter + let totalPages + let totalItems + if (search) { + if (!type) { + res.status(422).json({ success: false, message: 'نوع جستجو را مشخص کنید' }) + } else if (type === 'project') { + // جستجو در مدل Project با فیلتر کردن برای user_type === "employer" + + filter = { $or: [{ title: new RegExp(search, 'i'), status: 'accepted' }, { description: new RegExp(search, 'i'), status: 'accepted' }] } + result = await ProjectModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), sort: { createdAt: -1 } }) + totalPages = result?.totalPages + totalItems = result?.totalDocs + } else if (type === 'user') { + // جستجو در مدل User با فیلتر کردن برای user_type === "user" + filter = { user_type: 'user', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] } + result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields }) + totalPages = result?.totalPages + totalItems = result?.totalDocs + } else if (type === 'employer') { + // جستجو در مدل User با فیلتر کردن برای user_type === "employer" + filter = { user_type: 'employer', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] } + result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields }) + totalPages = result?.totalPages + totalItems = result?.totalDocs + } + res.status(200).json({ + success: true, + result: result?.docs, + type, + totalPages, + totalItems + }) + } else { + res.status(422).json({ success: false, message: 'چیزی تایپ کنید' }) + } + } catch (error) { + next(error) + } +} + +module.exports = { + getSearch +} diff --git a/public/modstagram-back/controllers/application/settings/settingsController.js b/public/modstagram-back/controllers/application/settings/settingsController.js new file mode 100644 index 0000000..bd76195 --- /dev/null +++ b/public/modstagram-back/controllers/application/settings/settingsController.js @@ -0,0 +1,19 @@ +// controllers/settingController.js + +const SettingModel = require('../../../models/SettingsModel') + +// متد برای دریافت تنظیمات بر اساس key +const getSetting = async (req, res, next) => { + try { + const { key } = req.params + const setting = await SettingModel.findOne({ key }) + if (!setting) { + return res.status(404).json({ message: 'تنظیمات مورد نظر یافت نشد' }) + } + res.status(200).json(setting) + } catch (error) { + next(error) + } +} + +module.exports = { getSetting } diff --git a/public/modstagram-back/controllers/application/tickets/ticketsController.js b/public/modstagram-back/controllers/application/tickets/ticketsController.js new file mode 100644 index 0000000..bc67d3b --- /dev/null +++ b/public/modstagram-back/controllers/application/tickets/ticketsController.js @@ -0,0 +1,147 @@ +const jwt = require('jsonwebtoken') +const TicketModel = require('../../../models/TicketModel') +const TicketMessageModel = require('../../../models/TicketMessageModel') +const jMoment = require('moment-jalaali') +const path = require('path') +const fs = require('fs-extra') + +const getUserTickets = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const { page = 1, limit = 10, search } = req.query // افزودن پارامترهای صفحه‌بندی به درخواست + const filter = { user: userId } + if (search) { + filter.$or = [ + { title: { $regex: search, $options: 'i' } } + ] + } + const options = { + page: parseInt(page) || 1, + limit: parseInt(limit) || 10, + sort: { updatedAt: -1 } + } + const tickets = await TicketModel.paginate(filter, options) + const ticketList = tickets?.docs.map(ticket => { + const jDate = jMoment(ticket.createdAt).format('jYYYY-jMM-jDD HH:mm') + return { + ...ticket._doc, + createdAt: jDate + } + }) + res.json({ + tickets: ticketList, + totalPages: tickets.totalPages, // ارسال تعداد کل صفحات + totalItems: tickets.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }) + } +} + +const createTicket = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { title } = req.body + + const newTicket = new TicketModel({ + title, + user: userId + }) + await newTicket.save() + + res.status(201).json(newTicket) + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }) + } +} +const addUserMessageToTicket = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const { ticketId } = req.query + const { text } = req.body + const { file } = req.files + let fileUrl = null + if (file) { + // اگر فایل ارسال شده است، آن را ذخیره کنید + const uploadDir = path.join(__dirname, '../../../../storage/tickets') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + + const uniqueFileName = `${Date.now()}-${file.name}` + const filePath = path.join(uploadDir, uniqueFileName) + await fs.move(file.path, filePath) + + fileUrl = `/tickets/${uniqueFileName}` + } + const newMessage = new TicketMessageModel({ + text, + senderType: 'User', + senderId: userId, + ticket: ticketId, + file: fileUrl + }) + await newMessage.save() + + const ticket = await TicketModel.findById(ticketId) + if (!ticket) { + return res.status(404).json({ error: 'Ticket not found' }) + } + + ticket.status = 'Customer Response' + await ticket.save() + const newMessageWithJalaliDate = { + ...newMessage._doc, + createdAt: jMoment(newMessage.createdAt).format('jYYYY-jMM-jDD HH:mm') + } + res.status(201).json(newMessageWithJalaliDate) + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }) + } +} +const getTicketMessages = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { ticketId } = req.query + const { page = 1, limit = 10 } = req.query + const options = { + page: parseInt(page) || 1, + limit: parseInt(limit) || 10, + sort: { createdAt: -1 } + } + const messages = await TicketMessageModel.paginate({ ticket: ticketId }, options) + const ticket = await TicketModel.findById(ticketId) + ticket.new_message = false + await ticket.save() + const messageList = messages?.docs.map(message => { + const jDate = jMoment(message.createdAt).format('jYYYY-jMM-jDD HH:mm') + return { + ...message._doc, + createdAt: jDate + } + }) + res.json({ + messages: messageList.reverse(), + totalPages: messages.totalPages, // ارسال تعداد کل صفحات + totalItems: messages.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }) + } +} +module.exports = { getUserTickets, createTicket, addUserMessageToTicket, getTicketMessages } diff --git a/public/modstagram-back/controllers/application/users/getUserController.js b/public/modstagram-back/controllers/application/users/getUserController.js new file mode 100644 index 0000000..8df2dcb --- /dev/null +++ b/public/modstagram-back/controllers/application/users/getUserController.js @@ -0,0 +1,1378 @@ +/* eslint-disable camelcase */ +const { default: mongoose } = require("mongoose"); +const LikeModel = require("../../../models/LikeModel"); +const UserModel = require("../../../models/UserModel"); +const jwt = require("jsonwebtoken"); +const moment = require("moment-jalaali"); +const NotificationModel = require("../../../models/NotificationModel"); +const CommentModel = require("../../../models/CommentModel"); +const { ProvinceModel, CityModel } = require("../../../models/StateCity"); +const OfferModel = require("../../../models/OfferModel"); +const PostModel = require("../../../models/PostModel"); +const ProjectModel = require("../../../models/ProjectModel"); +const LicenseModel = require("../../../models/license") + + +const getAllLicenses = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + jwt.verify(token, process.env.APP_SECRET); + + const { page = 1, limit = 10 } = req.query; + + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { createdAt: -1 }, + populate: { + path: "userId", + model: UserModel, + select: "user_name first_name last_name is_verified profile_image", + }, + }; + + const licenses = await LicenseModel.paginate({}, options); + + const formattedLicenses = licenses.docs.map((license) => ({ + _id: license._id, + userId: license.userId, + Confirmation: license.Confirmation, + licenseImg: license.licenseImg, // چون خودش Base64 هست + createdAt: moment(license.createdAt).format("jYYYY-jMM-jDD HH:mm"), + updatedAt: moment(license.updatedAt).format("jYYYY-jMM-jDD HH:mm"), + user: license.userId, + })); + + res.status(200).json({ + licenses: formattedLicenses, + totalPages: licenses.totalPages, + totalItems: licenses.totalDocs, + currentPage: licenses.page, + }); + } catch (error) { + console.error("Error fetching licenses:", error); + next(error); + } +}; + + +// GET: دریافت License بر اساس userId +const getLicenseByUserId = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + jwt.verify(token, process.env.APP_SECRET); + + const { userId } = req.params; + + if (!mongoose.Types.ObjectId.isValid(userId)) { + return res.status(400).json({ message: "شناسه کاربر معتبر نیست" }); + } + + const license = await LicenseModel.findOne({ userId }).populate({ + path: "userId", + model: UserModel, + select: "user_name first_name last_name is_verified profile_image", + }); + + if (!license) { + return res.status(404).json({ message: "License یافت نشد" }); + } + + res.status(200).json(license); // licenseImg همان Base64 است + } catch (error) { + console.error("Error fetching license:", error); + next(error); + } +}; + + + +// POST: ذخیره License به صورت Base64 +const createLicense = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + jwt.verify(token, process.env.APP_SECRET); + + const { userId, image } = req.body; + + if (!userId || !image) { + return res.status(400).json({ message: "userId و تصویر الزامی هستند" }); + } + + if (!mongoose.Types.ObjectId.isValid(userId)) { + return res.status(400).json({ message: "شناسه کاربر معتبر نیست" }); + } + + if (!image.startsWith("data:image/")) { + return res.status(400).json({ message: "فقط فایل‌های تصویری مجاز هستند" }); + } + + const existingLicense = await LicenseModel.findOne({ userId }); + if (existingLicense) { + existingLicense.licenseImg = image; + existingLicense.Confirmation = false; // نیاز به تأیید دوباره + await existingLicense.save(); + + return res.status(200).json({ + message: "تصویر مجوز با موفقیت به‌روزرسانی شد", + license: existingLicense, + }); + } + + const license = new LicenseModel({ + userId, + Confirmation: false, + licenseImg: image, + }); + await license.save(); + + res.status(201).json({ message: "License با موفقیت ذخیره شد", license }); + } catch (error) { + console.error("Error saving license:", error); + next(error); + } +}; + + +// PUT: به‌روزرسانی Confirmation و is_verified +const updateLicenseConfirmation = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + jwt.verify(token, process.env.APP_SECRET); + + const { userId } = req.params; + const { Confirmation } = req.body; + + if (!mongoose.Types.ObjectId.isValid(userId)) { + return res.status(400).json({ message: "شناسه کاربر معتبر نیست" }); + } + + if (typeof Confirmation !== "boolean") { + return res.status(400).json({ message: "Confirmation باید بولین باشد" }); + } + + const license = await LicenseModel.findOneAndUpdate( + { userId }, + { Confirmation }, + { new: true } + ); + + if (!license) { + return res.status(404).json({ message: "License یافت نشد" }); + } + + // اگر Confirmation به true تغییر کند، is_verified را به "true" به‌روزرسانی کن + if (Confirmation) { + await UserModel.findByIdAndUpdate(userId, { is_verified: "true" }); + } + + res.status(200).json({ message: "Confirmation به‌روزرسانی شد", license }); + } catch (error) { + console.error("Error updating license:", error); + next(error); + } +}; + + +// const getUsers = async (req, res, next) => { +// try { +// const token = req.header('Authorization').split(' ')[1] +// if (!token) return res.status(401).send('Access Denied') + +// const decodedToken = jwt.verify(token, process.env.APP_SECRET) +// const { expertise, page = 1, limit = 10 } = req.query +// const filter = {} +// if (expertise) { +// filter.expertise = expertise +// } + +// let users = await UserModel.aggregate([ +// { $match: filter }, +// { $match: { last_post: { $ne: null } } }, +// { +// $addFields: { +// 'last_post.likesCount': { $size: { $ifNull: ['$last_post.likes', []] } } +// } +// }, +// { +// $lookup: { +// from: 'comments', +// let: { userId: '$_id' }, +// pipeline: [ +// { $match: { $expr: { $and: [{ $eq: ['$user', '$$userId'] }, { $eq: ['$status', 'accepted'] }] } } }, +// { $count: 'commentsCount' } +// ], +// as: 'comments' +// } +// }, +// { +// $addFields: { +// commentsCount: { $arrayElemAt: ['$comments.commentsCount', 0] } +// } +// }, +// { +// $project: { +// user_level: 1, +// first_name: 1, +// last_name: 1, +// user_name: 1, +// is_verified: 1, +// user_score: 1, +// rate: 1, +// profile_image: 1, +// last_post: { +// _id: 1, +// post_image: 1, +// caption: 1, +// status: 1, +// user_id: 1, +// updatedAt: 1, +// createdAt: 1, +// __v: 1, +// likesCount: 1, +// is_liked: 1 +// }, +// commentsCount: 1 +// } +// }, +// { $sort: { 'last_post.createdAt': -1 } } +// ]) + +// users = users.filter(user => user.last_post !== null) + +// if (!users || users.length === 0) { +// return res.status(404).json({ message: 'هیچ کاربری با این مشخصات یافت نشد' }) +// } +// users = await Promise.all(users.map(async (user) => { +// const isLikedDocument = await LikeModel.findOne({ postId: user.last_post._id, userId: decodedToken.id }) +// user.last_post.is_liked = !!isLikedDocument +// return user +// })) + +// const startIndex = (page - 1) * limit +// const endIndex = page * limit +// const totalItems = users.length + +// const paginatedUsers = users.slice(startIndex, endIndex) +// if (!users || users.length === 0) { +// return res.status(404).json({ message: 'هیچ کاربری با این مشخصات یافت نشد' }) +// } + +// return res.status(200).json({ +// users: paginatedUsers, +// totalPages: Math.ceil(totalItems / limit), +// totalItems +// }) +// } catch (error) { +// next(error) +// } +// } +const getUsers = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const { + expertise, + page = 1, + limit = 10, + province, + city, + userLevel, + rateFilter, + } = req.query; + const filter = {}; + if (expertise) { + filter.expertise = expertise; + } + if (province) { + const provinceFind = await ProvinceModel.findOne( + { id: province }, + { _id: 0 } + ); + console.log("provinceFind:", provinceFind); + if (provinceFind) { + filter["province.id"] = provinceFind.id; + } + } + if (city) { + const cityFind = await CityModel.findOne({ id: city }); + console.log("cityFind:", cityFind); + if (cityFind) { + filter["city.id"] = cityFind.id; + } + } + if (userLevel) { + filter.user_level = userLevel; + } + + let users = await UserModel.aggregate([ + { $match: filter }, + { $match: { last_post: { $ne: null } } }, + { + $addFields: { + "last_post.likesCount": { + $size: { $ifNull: ["$last_post.likes", []] }, + }, + }, + }, + { + $lookup: { + from: "comments", + let: { userId: "$_id" }, + pipeline: [ + { + $match: { + $expr: { + $and: [ + { $eq: ["$user", "$$userId"] }, + { $eq: ["$status", "accepted"] }, + ], + }, + }, + }, + { $count: "commentsCount" }, + ], + as: "comments", + }, + }, + { + $addFields: { + commentsCount: { $arrayElemAt: ["$comments.commentsCount", 0] }, + }, + }, + { + $project: { + user_level: 1, + first_name: 1, + last_name: 1, + user_name: 1, + is_verified: 1, + user_score: 1, + rate: 1, + profile_image: 1, + expertise: 1, + hair_color: 1, + eye_color: 1, + height: 1, + weight: 1, + size: 1, + services: 1, + last_post: { + _id: 1, + post_image: 1, + caption: 1, + status: 1, + user_id: 1, + updatedAt: 1, + createdAt: 1, + __v: 1, + likesCount: 1, + is_liked: 1, + }, + commentsCount: 1, + }, + }, + { $sort: { "last_post.createdAt": -1 } }, + ]); + + users = users.filter((user) => user.last_post !== null); + + if (!users || users.length === 0) { + return res + .status(404) + .json({ message: "هیچ کاربری با این مشخصات یافت نشد" }); + } + + users = await Promise.all( + users.map(async (user) => { + const isLikedDocument = await LikeModel.findOne({ + postId: user.last_post._id, + userId: decodedToken.id, + }); + user.last_post.is_liked = !!isLikedDocument; + return user; + }) + ); + + if (rateFilter) { + users.sort((a, b) => { + if (rateFilter === "کمترین") { + return a.rate - b.rate; + } else if (rateFilter === "بیشترین") { + return b.rate - a.rate; + } + return 0; + }); + } + + const startIndex = (page - 1) * limit; + const endIndex = page * limit; + const totalItems = users.length; + + const paginatedUsers = users.slice(startIndex, endIndex); + + return res.status(200).json({ + users: paginatedUsers, + totalPages: Math.ceil(totalItems / limit), + totalItems, + }); + } catch (error) { + next(error); + } +}; +// const getUsersWeb = async (req, res, next) => { +// try { +// const token = req.header('Authorization')?.split(' ')[1] +// const decodedToken = token && jwt.verify(token, process.env.APP_SECRET) + +// const { expertise, page = 1, limit = 10, province, city, userLevel, rateFilter } = req.query +// const filter = {} +// if (expertise) { +// filter.expertise = expertise +// } +// if (province) { +// const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) +// if (provinceFind) { +// filter['province.id'] = provinceFind.id +// } +// } +// if (city) { +// const cityFind = await CityModel.findOne({ id: city }) +// if (cityFind) { +// filter['city.id'] = cityFind.id +// } +// } +// if (userLevel) { +// filter.user_level = userLevel +// } + +// let users = await UserModel.aggregate([ +// { $match: filter }, +// { $match: { last_post: { $ne: null } } }, +// { +// $addFields: { +// 'last_post.likesCount': { $size: { $ifNull: ['$last_post.likes', []] } } +// } +// }, +// { +// $lookup: { +// from: 'comments', +// let: { userId: '$_id' }, +// pipeline: [ +// { $match: { $expr: { $and: [{ $eq: ['$user', '$$userId'] }, { $eq: ['$status', 'accepted'] }] } } }, +// { $count: 'commentsCount' } +// ], +// as: 'comments' +// } +// }, +// { +// $addFields: { +// commentsCount: { $arrayElemAt: ['$comments.commentsCount', 0] } +// } +// }, +// { +// $project: { +// user_level: 1, +// first_name: 1, +// last_name: 1, +// user_name: 1, +// is_verified: 1, +// user_score: 1, +// rate: 1, +// profile_image: 1, +// expertise: 1, +// hair_color: 1, +// eye_color: 1, +// height: 1, +// weight: 1, +// size: 1, +// services: 1, +// last_post: { +// _id: 1, +// post_image: 1, +// caption: 1, +// status: 1, +// user_id: 1, +// updatedAt: 1, +// createdAt: 1, +// __v: 1, +// likesCount: 1, +// is_liked: 1 +// }, +// commentsCount: 1 +// } +// }, +// { $sort: { 'last_post.createdAt': -1 } } +// ]) +// const getUsersWeb = async (req, res, next) => { +// try { +// const token = req.header('Authorization')?.split(' ')[1] +// const decodedToken = token && jwt.verify(token, process.env.APP_SECRET) + +// const { expertise, page = 1, limit = 10, province, city, userLevel, rateFilter, userId } = req.query +// const filter = {} + +// if (expertise) filter.expertise = expertise +// if (province) { +// const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) +// if (provinceFind) filter['province.id'] = provinceFind.id +// } +// if (city) { +// const cityFind = await CityModel.findOne({ id: city }) +// if (cityFind) filter['city.id'] = cityFind.id +// } +// if (userLevel) filter.user_level = userLevel + +// // ← اضافه کردن userId به فیلتر +// if (userId) { +// if (!mongoose.Types.ObjectId.isValid(userId)) { +// return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }) +// } +// filter._id = mongoose.Types.ObjectId(userId) +// } + +// let users = await UserModel.aggregate([ +// { $match: filter }, +// { $match: { last_post: { $ne: null } } }, +// { +// $addFields: { +// 'last_post.likesCount': { $size: { $ifNull: ['$last_post.likes', []] } } +// } +// }, +// { +// $lookup: { +// from: 'comments', +// let: { userId: '$_id' }, +// pipeline: [ +// { $match: { $expr: { $and: [{ $eq: ['$user', '$$userId'] }, { $eq: ['$status', 'accepted'] }] } } }, +// { $count: 'commentsCount' } +// ], +// as: 'comments' +// } +// }, +// { +// $addFields: { +// commentsCount: { $arrayElemAt: ['$comments.commentsCount', 0] } +// } +// }, +// { +// $project: { +// user_level: 1, +// first_name: 1, +// last_name: 1, +// user_name: 1, +// is_verified: 1, +// user_score: 1, +// rate: 1, +// profile_image: 1, +// expertise: 1, +// hair_color: 1, +// eye_color: 1, +// height: 1, +// weight: 1, +// size: 1, +// services: 1, +// last_post: 1, +// commentsCount: 1 +// } +// }, +// { $sort: { 'last_post.createdAt': -1 } } +// ]) + +// users = users.filter(user => user.last_post !== null) + +// if (!users || users.length === 0) { +// return res.status(404).json({ message: 'هیچ کاربری با این مشخصات یافت نشد' }) +// } +// // بررسی لایک‌ها فقط در صورت وجود توکن +// if (token) { +// users = await Promise.all(users.map(async (user) => { +// const isLikedDocument = await LikeModel.findOne({ postId: user.last_post._id, userId: decodedToken.id }) +// user.last_post.is_liked = !!isLikedDocument +// return user +// })) +// } else { +// // اگر توکن وجود ندارد، مقدار پیش‌فرض را تنظیم کنید +// users = users.map(user => { +// user.last_post.is_liked = false +// return user +// }) +// } + +// if (rateFilter) { +// users.sort((a, b) => { +// if (rateFilter === 'کمترین') { +// return a.rate - b.rate +// } else if (rateFilter === 'بیشترین') { +// return b.rate - a.rate +// } +// return 0 +// }) +// } + +// const startIndex = (page - 1) * limit +// const endIndex = page * limit +// const totalItems = users.length + +// const paginatedUsers = users.slice(startIndex, endIndex) + +// return res.status(200).json({ +// users: paginatedUsers, +// totalPages: Math.ceil(totalItems / limit), +// totalItems +// }) +// } catch (error) { +// next(error) +// } +// } + +// const getUsersWeb = async (req, res, next) => { +// try { +// const token = req.header("Authorization")?.split(" ")[1]; +// const decodedToken = token && jwt.verify(token, process.env.APP_SECRET); + +// const { +// expertise, +// page = 1, +// limit = 10, +// province, +// city, +// userLevel, +// rateFilter, +// _id, +// } = req.query; + +// const filter = {}; +// if (expertise) filter.expertise = expertise; + +// if (province) { +// const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }); +// if (provinceFind) filter["province.id"] = provinceFind.id; +// } + +// if (city) { +// const cityFind = await CityModel.findOne({ id: city }); +// if (cityFind) filter["city.id"] = cityFind.id; +// } + +// if (userLevel) filter.user_level = userLevel; +// if (_id) filter._id = _id; + +// // پیدا کردن کاربران +// let users = await UserModel.find(filter) +// .select("-password -blocked_users -blocked_by") +// .lean(); + +// if (!users || users.length === 0) { +// return res.status(404).json({ message: "هیچ کاربری با این مشخصات یافت نشد" }); +// } + +// // آماده‌سازی لیست userIds برای گرفتن همه پست‌ها یکجا +// const userIds = users.map(u => u._id); + +// // گرفتن همه پست‌ها یکجا (به جای N+1 query) +// let posts = await PostModel.find({ user_id: { $in: userIds }, status: { $ne: null } }) +// .sort({ createdAt: -1 }) +// .lean(); + +// // گرفتن همه لایک‌های کاربران یکجا (برای بهبود کارایی) +// let likeFilter = {}; +// if (decodedToken) likeFilter.userId = decodedToken.id; +// const likes = decodedToken +// ? await LikeModel.find({ userId: decodedToken.id, postId: { $in: posts.map(p => p._id) } }).lean() +// : []; + +// const likesMap = {}; +// likes.forEach(l => { likesMap[l.postId.toString()] = true; }); + +// // گرفتن تعداد کامنت‌ها یکجا برای همه کاربران +// const comments = await CommentModel.aggregate([ +// { $match: { user: { $in: userIds }, status: "accepted" } }, +// { $group: { _id: "$user", count: { $sum: 1 } } } +// ]); +// const commentsMap = {}; +// comments.forEach(c => { commentsMap[c._id.toString()] = c.count; }); + +// // اتصال پست‌ها و کامنت‌ها به کاربران +// users = users.map(user => { +// const userPosts = posts.filter(p => p.user_id.toString() === user._id.toString()); +// user.posts = userPosts.map(p => ({ +// ...p, +// likesCount: p.likes ? p.likes.length : 0, +// is_liked: !!likesMap[p._id.toString()] +// })); +// user.commentsCount = commentsMap[user._id.toString()] || 0; +// return user; +// }); + +// // حذف کاربران بدون پست +// users = users.filter(u => u.posts.length > 0); + +// // مرتب‌سازی +// if (rateFilter) { +// users.sort((a, b) => { +// if (rateFilter === 'کمترین') return a.rate - b.rate; +// if (rateFilter === 'بیشترین') return b.rate - a.rate; +// return 0; +// }); +// } else { +// // مرتب‌سازی بر اساس جدیدترین پست آخر +// users.sort((a, b) => new Date(b.posts[0].createdAt) - new Date(a.posts[0].createdAt)); +// } + +// // صفحه‌بندی +// const startIndex = (page - 1) * limit; +// const endIndex = page * limit; +// const totalItems = users.length; +// const paginatedUsers = users.slice(startIndex, endIndex); + +// return res.status(200).json({ +// users: paginatedUsers, +// totalPages: Math.ceil(totalItems / limit), +// totalItems, +// }); + +// } catch (error) { +// console.error(error); +// next(error); +// } +// }; + +const getPostsWeb = async (req, res, next) => { + try { + const token = req.header("Authorization")?.split(" ")[1]; + const decodedToken = token ? jwt.verify(token, process.env.APP_SECRET) : null; + + const { + expertise, + page = 1, + limit = 10, + province, + city, + userLevel, + rateFilter, + _id, + type, + } = req.query; + + const postFilter = { status: { $ne: null } }; + if (type === 'video' || type === 'image') { + postFilter.type = type; + } + + // اکسپلور: ویدئوهای همه کاربران بدون فیلتر تخصص + if (type === 'video' && !expertise && !_id && !province && !city) { + let explorePosts = await PostModel.find(postFilter) + .sort({ createdAt: -1 }) + .lean(); + const userIds = [...new Set(explorePosts.map((p) => String(p.user_id)))]; + const usersMap = await UserModel.find({ _id: { $in: userIds } }) + .select('_id user_name first_name last_name expertise province city user_level') + .lean(); + const usersById = Object.fromEntries(usersMap.map((u) => [String(u._id), u])); + explorePosts = explorePosts.map((post) => { + const user = usersById[String(post.user_id)] || {}; + return { + ...post, + user_name: user.user_name || '', + first_name: user.first_name || '', + last_name: user.last_name || '', + expertise: user.expertise || '', + province: user.province || {}, + city: user.city || {}, + user_level: user.user_level || '', + likesCount: post.likes ? post.likes.length : 0, + is_liked: false, + commentsCount: 0 + }; + }); + const startIndex = (page - 1) * limit; + const paginatedPosts = explorePosts.slice(startIndex, startIndex + parseInt(limit)); + return res.status(200).json({ + posts: paginatedPosts, + totalPages: Math.ceil(explorePosts.length / limit) || 1, + totalItems: explorePosts.length + }); + } + + const userFilter = {}; + + if (expertise) userFilter.expertise = expertise; + if (province) { + const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }); + if (provinceFind) userFilter["province.id"] = provinceFind.id; + } + if (city) { + const cityFind = await CityModel.findOne({ id: city }); + if (cityFind) userFilter["city.id"] = cityFind.id; + } + if (userLevel) userFilter.user_level = userLevel; + if (_id) userFilter._id = _id; + + const users = await UserModel.find(userFilter) + .select("_id user_name first_name last_name expertise province city user_level") + .lean(); + + if (!users || users.length === 0) { + return res.status(200).json({ posts: [], totalPages: 0, totalItems: 0 }); + } + + const userIds = users.map(u => u._id); + postFilter.user_id = { $in: userIds }; + + let posts = await PostModel.find(postFilter) + .sort({ createdAt: -1 }) + .lean(); + + if (!posts || posts.length === 0) { + return res.status(200).json({ posts: [], totalPages: 0, totalItems: 0 }); + } + + let likeFilter = {}; + if (decodedToken) likeFilter.userId = decodedToken.id; + const likes = decodedToken + ? await LikeModel.find({ userId: decodedToken.id, postId: { $in: posts.map(p => p._id) } }).lean() + : []; + + const likesMap = {}; + likes.forEach(l => { likesMap[l.postId.toString()] = true; }); + + const comments = await CommentModel.aggregate([ + { $match: { post: { $in: posts.map(p => p._id) }, status: "accepted" } }, + { $group: { _id: "$post", count: { $sum: 1 } } } + ]); + const commentsMap = {}; + comments.forEach(c => { commentsMap[c._id.toString()] = c.count; }); + + posts = posts.map(post => { + const user = users.find(u => u._id.toString() === post.user_id.toString()); + return { + ...post, + user_name: user?.user_name || "", + first_name: user?.first_name || "", + last_name: user?.last_name || "", + expertise: user?.expertise || "", + province: user?.province || {}, + city: user?.city || {}, + user_level: user?.user_level || "", + likesCount: post.likes ? post.likes.length : 0, + is_liked: !!likesMap[post._id.toString()], + commentsCount: commentsMap[post._id.toString()] || 0, + }; + }); + + if (rateFilter) { + posts.sort((a, b) => { + if (rateFilter === 'کمترین') return (a.rate || 0) - (b.rate || 0); + if (rateFilter === 'بیشترین') return (b.rate || 0) - (a.rate || 0); + return 0; + }); + } + + const startIndex = (page - 1) * limit; + const endIndex = page * limit; + const totalItems = posts.length; + const paginatedPosts = posts.slice(startIndex, endIndex); + + return res.status(200).json({ + posts: paginatedPosts, + totalPages: Math.ceil(totalItems / limit), + totalItems, + }); + + } catch (error) { + console.error("Error in getPostsWeb:", error.message, error.stack); + return res.status(500).json({ message: "خطای سرور: " + error.message }); + } +}; + +const getSingleUser = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const user_id = req.query.user_id; + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userReqId = decodedToken.id; + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: "شناسه کاربر معتبر نیست" }); + } + const user = await UserModel.findById(user_id); + + if (!user) { + return res.status(404).json({ message: "کاربر مورد نظر یافت نشد" }); + } + const shamsiDate = moment(user.created_at).format("jYYYY-jMM-jDD"); + const lastOnline = moment(user.last_online).format("jYYYY-jMM-jDD"); + + // بررسی بلاک شدن + const blockedByCurrentUser = user.blocked_by.includes(userReqId); + const blockedYou = user.blocked_users.includes(userReqId); + + // Allow chat + const offerExists = await OfferModel.exists({ + $or: [ + { sender: userReqId, receiver: user_id }, + { sender: user_id, receiver: userReqId }, + ], + }); + const response = { + is_self: user_id.toString() === userReqId.toString() ? "true" : "false", + _id: user._id, + last_online: lastOnline, + created_at: shamsiDate, + user_type: user.user_type, + user_level: user.user_level, + first_name: user.first_name, + last_name: user.last_name, + user_name: user.user_name, + show_location: user.show_location, + is_verified: user.is_verified, + user_score: user.user_score, + rate: user.rate, + bio: user.bio, + height: user.height, + weight: user.weight, + size: user.size, + eye_color: user.eye_color, + hair_color: user.hair_color, + profile_image: user.profile_image, + lat: user.show_location ? user.lat : null, + lng: user.show_location ? user.lng : null, + province: user.province, + city: user.city, + address: user.show_location ? user.address : null, + is_blocked: blockedByCurrentUser, + blocked_you: blockedYou, + offer_status: !!offerExists, + monthly_free_offer: user.monthly_free_offer, + services: user.services, + expertise: user.expertise, + sub_expertise: user.sub_expertise, + }; + return res.status(200).json({ user: response }); + } catch (error) { + next(error); + } +}; +const getSingleUserWeb = async (req, res, next) => { + try { + let userReqId = null; + + // دریافت توکن و بررسی معتبر بودنش (اگر وجود داشت) + const authHeader = req.header("Authorization"); + if (authHeader) { + const token = authHeader.split(" ")[1]; + try { + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + userReqId = decodedToken.id; + } catch (err) { + console.warn("توکن نامعتبر است، ادامه بدون احراز هویت"); // فقط هشدار، نه ارور + } + } + + let user; + const { user_id, user_name } = req.query; + + if (user_id) { + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: "شناسه کاربر معتبر نیست" }); + } + user = await UserModel.findById(user_id); + } else if (user_name) { + user = await UserModel.findOne({ user_name }); + } else { + return res + .status(400) + .json({ message: "لطفاً user_id یا user_name ارسال کنید" }); + } + + if (!user) { + return res.status(404).json({ message: "کاربر مورد نظر یافت نشد" }); + } + + const shamsiDate = moment(user.created_at).format("jYYYY-jMM-jDD"); + const lastOnline = moment(user.last_online).format("jYYYY-jMM-jDD"); + + // بررسی بلاک شدن (فقط اگر توکن معتبر داشتیم) + let blockedByCurrentUser = false; + let blockedYou = false; + let offerExists = false; + + if (userReqId) { + blockedByCurrentUser = user.blocked_by.includes(userReqId); + blockedYou = user.blocked_users.includes(userReqId); + offerExists = await OfferModel.exists({ + sender: userReqId, + receiver: user._id, + }); + } + // دریافت تعداد پست‌ها و پروژه‌ها + const postsCount = await PostModel.countDocuments({ + user_id: user._id, + status: { $in: ["accept"] }, + }); + const allProjectsCount = await ProjectModel.countDocuments({ + selected_user: user._id, + }); + const successfulProjectsCount = await ProjectModel.countDocuments({ + selected_user: user._id, + status: "done", + }); + + const response = { + is_self: userReqId + ? user._id.toString() === userReqId.toString() + : "false", + _id: user._id, + last_online: lastOnline, + created_at: shamsiDate, + user_type: user.user_type, + user_level: user.user_level, + first_name: user.first_name, + last_name: user.last_name, + user_name: user.user_name, + show_location: user.show_location, + is_verified: user.is_verified, + user_score: user.user_score, + rate: user.rate, + bio: user.bio, + height: user.height, + weight: user.weight, + size: user.size, + eye_color: user.eye_color, + hair_color: user.hair_color, + profile_image: user.profile_image, + lat: user.show_location ? user.lat : null, + lng: user.show_location ? user.lng : null, + province: user.province, + city: user.city, + address: user.show_location ? user.address : null, + is_blocked: blockedByCurrentUser, + blocked_you: blockedYou, + offer_status: !!offerExists, + services: user.services, + expertise: user.expertise, + sub_expertise: user.sub_expertise, + postsCount, + allProjectsCount, + successfulProjectsCount, + }; + + return res.status(200).json({ user: response }); + } catch (error) { + next(error); + } +}; +const getUserContactInfo = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const user_id = decodedToken.id; + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: "شناسه کاربر معتبر نیست" }); + } + const user = await UserModel.findById(user_id); + + if (!user) { + return res.status(404).json({ message: "کاربر مورد نظر یافت نشد" }); + } + + const response = { + contactInfo: user?.contactInfo, + _id: user._id, + }; + return res.status(200).json({ data: response }); + } catch (error) { + next(error); + } +}; +const blockUser = async (req, res) => { + try { + const { user_to_block } = req.body; + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userReqId = decodedToken.id; + + const currentUser = await UserModel.findById(userReqId); // Req + const userToBlock = await UserModel.findById(user_to_block); // To Block + + userToBlock.blocked_by.push(currentUser); + currentUser.blocked_users.push(userToBlock); + + // بررسی تعداد بلاک ها و تنظیم block_status + if (userToBlock.blocked_by.length >= 3) { + userToBlock.block_status = true; + } + + await currentUser.save(); + await userToBlock.save(); + + res.status(200).json({ message: "کاربر با موفقیت بلاک شد" }); + } catch (error) { + console.error("Error blocking user:", error); + res.status(500).json({ error: "Server error" }); + } +}; + +const unblockUser = async (req, res) => { + try { + const { user_to_unblock } = req.body; + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userReqId = decodedToken.id; + + const currentUser = await UserModel.findById(userReqId); // Req + const userToUnblock = await UserModel.findById(user_to_unblock); // To Unblock + + // حذف کاربر از لیست blocked_by کاربر فعلی + currentUser.blocked_users.pull(userToUnblock._id); + // حذف کاربر از لیست blocked_users کاربر مورد نظر + userToUnblock.blocked_by.pull(currentUser._id); + + // بررسی تعداد بلاک ها و تنظیم block_status + if (userToUnblock.blocked_by.length < 3) { + userToUnblock.block_status = null; + } + + await currentUser.save(); + await userToUnblock.save(); + + res.status(200).json({ message: "کاربر با موفقیت آنبلاک شد" }); + } catch (error) { + console.error("Error unblocking user:", error); + res.status(500).json({ error: "Server error" }); + } +}; + +const getComments = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const user_id = req.query.user_id; + const post_id = req.query.post_id; + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: "شناسه کاربر معتبر نیست" }); + } + const user = await UserModel.findById(user_id); + const { page = 1, limit = 10 } = req.query; + if (!user) { + return res.status(404).json({ message: "کاربر مورد نظر یافت نشد" }); + } + + const filter = { user: user_id, status: "accepted" }; + if (post_id && mongoose.Types.ObjectId.isValid(post_id)) { + filter.post = post_id; + } + + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { createdAt: -1 }, + populate: [ + { path: "creator", select: "user_name profile_image is_verified" }, + { path: "project", select: "project_name" }, + ], + }; + + const comments = await CommentModel.paginate(filter, options); + + const formattedComments = comments.docs.map((comment) => ({ + _id: comment._id, + comment: comment.comment, + rating: comment.rating, + createdAt: moment(comment.createdAt).format("jYYYY-jMM-jDD HH:mm"), + status: comment.status, + user: { + profile_image: comment.creator.profile_image, + user_name: comment.creator.user_name, + is_verified: comment.creator.is_verified, + _id: comment.creator._id, + }, + project: comment.project ? comment.project.project_name : null, + post_id: comment.post ? comment.post.toString() : null, + })); + + res.status(200).json({ + comments: formattedComments, + totalPages: comments.totalPages, + totalItems: comments.totalDocs, + currentPage: comments.page, + }); + } catch (error) { + next(error); + } +}; +const createUserComment = async (req, res, next) => { + try { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const creatorId = decodedToken.id; + + const { user_id, comment, rate, post_id } = req.body; + if (!user_id || !comment) { + return res.status(400).send({ message: "All fields are required" }); + } + + const existingRating = await CommentModel.findOne({ + user: user_id, + creator: creatorId, + comment_for: post_id ? "post" : "user", + rating: { $exists: true, $ne: null } + }); + + let ratingValue = rate; + if (existingRating) { + ratingValue = existingRating.rating; + } else { + if (!rate || rate < 1 || rate > 5) { + return res.status(400).send({ message: "Rating must be between 1 and 5" }); + } + } + + const newComment = new CommentModel({ + user: user_id, + creator: creatorId, + rating: ratingValue, + comment, + comment_for: post_id ? "post" : "user", + post: post_id || undefined, + status: "pending", + }); + await newComment.save(); + + const user = await UserModel.findById(user_id); + + // محاسبه امتیاز جدید کاربر + const comments = await CommentModel.find({ + user: user_id, + comment_for: "user", + }); + const totalRating = comments.reduce( + (acc, comment) => acc + comment.rating, + 0 + ); + const totalComments = comments.length; + const averageRating = totalRating / totalComments; + + // تعیین سطح کاربر + let userLevel; + if (user.expertise === "مدل") { + if (totalRating <= 50) userLevel = "تازه وارد"; + else if (totalRating <= 100) userLevel = "استاندارد"; + else if (totalRating <= 300) userLevel = "حرفه‌ای"; + else userLevel = "استاد"; + } else if (["زیبایی", "عکاس"].includes(user.expertise)) { + if (totalRating <= 50) userLevel = "تازه وارد"; + else if (totalRating <= 100) userLevel = "استاندارد"; + else if (totalRating <= 300) userLevel = "حرفه‌ای"; + else userLevel = "استاد"; + } + + // به‌روزرسانی اطلاعات کاربر + user.user_score = totalRating; + user.user_level = userLevel; + user.rate = averageRating.toFixed(1); + await user.save(); + + // ارسال نوتیفیکیشن + const notification = new NotificationModel({ + user_id: user._id, + type: "user_comment", + title: "نظر جدید", + description: `یک کاربر جدید برای شما نظر ثبت کرد: + ${comment} + امتیاز: ${rate} از 5`, + }); + await notification.save(); + + res.status(201).json({ + message: "نظر با موفقیت ثبت شد و بعد از تایید، منتشر میشود.", + comment: newComment, + }); + } catch (error) { + next(error); + } +}; + +const inviteEmployer = async (req, res, next) => { + const token = req.header("Authorization").split(" ")[1]; + if (!token) return res.status(401).send("Access Denied"); + const user_id = req.query.user_id; + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET); + const userReqId = decodedToken.id; + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: "شناسه کاربر معتبر نیست" }); + } + const user = await UserModel.findById(user_id); + const creatorUser = await UserModel.findById(userReqId); + + if (!user) { + return res.status(404).json({ message: "کاربر مورد نظر یافت نشد" }); + } + + const today = new Date(); + today.setHours(0, 0, 0, 0); + + const existingNotification = await NotificationModel.findOne({ + user_id: user._id, + project_post_id: userReqId, + type: "invite", + createdAt: { $gte: today }, + }); + + if (existingNotification) { + return res + .status(400) + .json({ + message: "شما امروز برای این کارفرما درخواست همکاری ارسال کرده اید.", + type: "today", + }); + } + const notification = new NotificationModel({ + user_id: user._id, + project_post_id: userReqId, + type: "invite", + title: "دعوت به همکاری", + description: `کاربر ${creatorUser.user_name} شما را برای همکاری دعوت کرده است.`, + }); + await notification.save(); + + res.status(201).json({ message: "درخواست همکاری با موفقیت ثبت شد" }); +}; + +module.exports = { + getUsers, + getSingleUser, + blockUser, + unblockUser, + getComments, + inviteEmployer, + getUserContactInfo, + getPostsWeb, + getSingleUserWeb, + createUserComment, + getAllLicenses, + getLicenseByUserId, + createLicense, + updateLicenseConfirmation, +}; diff --git a/public/modstagram-back/controllers/application/verify/addressController.js b/public/modstagram-back/controllers/application/verify/addressController.js new file mode 100644 index 0000000..4f021ba --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/addressController.js @@ -0,0 +1,112 @@ +/* eslint-disable camelcase */ +const { ProvinceModel, CityModel } = require('../../../models/StateCity') +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setAddress = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { province_id, city_id, address, lat, lng, show_location } = req.body + // اعتبارسنجی داده‌ها + if (!province_id || !city_id || !address || !lat || !lng || show_location === 'undefined') { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی ناقص است' + }) + } + + // یافتن کاربر با شماره موبایل + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + // یافتن استان و شهر + const province = await ProvinceModel.findOne({ id: province_id }) + const city = await CityModel.findOne({ id: city_id }) + if (!province || !city) { + return res.status(404).json({ + error: true, + message: 'استان یا شهر موردنظر یافت نشد' + }) + } + + user.province = province + user.city = city + user.address = address + user.lat = lat + user.lng = lng + user.show_location = show_location + + await user.save() + + return res.json({ + message: 'آدرس با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +const updateAddress = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { province_id, city_id, address, lat, lng, show_location } = req.body + + // اعتبارسنجی داده‌ها + if (!province_id || !city_id || !address || !lat || !lng || show_location === undefined) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی ناقص است' + }) + } + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + // یافتن کاربر با استفاده از شناسه کاربر + const user = await UserModel.findById(userId) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شناسه یافت نشد' + }) + } + + // یافتن استان و شهر با استفاده از شناسه استان و شهر + const province = await ProvinceModel.findOne({ id: province_id }) + const city = await CityModel.findOne({ id: city_id }) + if (!province || !city) { + return res.status(404).json({ + error: true, + message: 'استان یا شهر مورد نظر یافت نشد' + }) + } + + // به‌روزرسانی اطلاعات آدرس کاربر + user.province = province + user.city = city + user.address = address + user.lat = lat + user.lng = lng + user.show_location = show_location + + await user.save() + + return res.json({ + message: 'آدرس با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + setAddress, updateAddress +} diff --git a/public/modstagram-back/controllers/application/verify/authController.js b/public/modstagram-back/controllers/application/verify/authController.js new file mode 100644 index 0000000..e3756e6 --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/authController.js @@ -0,0 +1,108 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const { check, validationResult } = require('express-validator') +const jwt = require('jsonwebtoken') + +const saveAuthValidationRules = () => { + return [ + check('shaba').notEmpty().withMessage('شماره شبا نمی‌تواند خالی باشد') + .matches(/^(?=.{24}$)[0-9]*$/).withMessage('فرمت شماره شبا صحیح نیست'), + check('birthday').notEmpty().withMessage('تاریخ تولد نمی‌تواند خالی باشد'), + check('national_code').notEmpty().withMessage('کد ملی نمی‌تواند خالی باشد') + .isLength({ min: 10, max: 10 }).withMessage('کد ملی باید 10 رقم باشد') + ] +} + +const saveAuth = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + const { shaba, birthday, national_code } = req.body + if (!shaba || !birthday || !national_code) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + // جستجوی کاربر با شماره موبایل ارسالی + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + // بررسی تکراری بودن کد ملی + const existingUserWithNationalCode = await UserModel.findOne({ national_code }) + if (existingUserWithNationalCode && existingUserWithNationalCode._id.toString() !== user._id.toString()) { + return res.status(409).json({ + error: true, + message: 'کد ملی تکراری است' + }) + } + user.shaba = shaba + user.birthday = birthday + user.national_code = national_code + await user.save() + + return res.json({ + message: 'اطلاعات با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +const updateShaba = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(422).json({ errors: errors.array() }) + } + + const { shaba } = req.body + + if (!shaba) { + return res.status(422).json({ + error: true, + message: 'شبا ارسال نشده است' + }) + } + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + // جستجوی کاربر با استفاده از شناسه کاربر + const user = await UserModel.findById(userId) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شناسه یافت نشد' + }) + } + + // فقط شبا را به‌روزرسانی کنید + user.shaba = shaba + await user.save() + + return res.json({ + message: 'شبا با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + saveAuth, saveAuthValidationRules, updateShaba +} diff --git a/public/modstagram-back/controllers/application/verify/colorsController.js b/public/modstagram-back/controllers/application/verify/colorsController.js new file mode 100644 index 0000000..6b1f040 --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/colorsController.js @@ -0,0 +1,80 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setColors = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { eye_color, hair_color } = req.body + if (!eye_color || !hair_color) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + // جستجوی کاربر با شماره موبایل ارسالی + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + user.eye_color = eye_color + user.hair_color = hair_color + await user.save() + + return res.json({ + message: 'رنگ ها با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +const updateColors = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { eye_color, hair_color } = req.body + + // اعتبارسنجی داده‌ها + if (!eye_color || !hair_color) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی ناقص است' + }) + } + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + // یافتن کاربر با استفاده از شناسه کاربر + const user = await UserModel.findById(userId) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شناسه یافت نشد' + }) + } + + // به‌روزرسانی اطلاعات رنگ‌ها + user.eye_color = eye_color + user.hair_color = hair_color + await user.save() + + return res.json({ + message: 'رنگ‌ها با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + setColors, updateColors +} diff --git a/public/modstagram-back/controllers/application/verify/conversationController.js b/public/modstagram-back/controllers/application/verify/conversationController.js new file mode 100644 index 0000000..95bc845 --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/conversationController.js @@ -0,0 +1,74 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setConversation = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { bio, conversation_projects } = req.body + if (!bio || conversation_projects === undefined) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + // جستجوی کاربر با شماره موبایل ارسالی + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + user.bio = bio + user.conversation_projects = conversation_projects + await user.save() + + return res.json({ + message: 'روابط عمومی با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +const updateConversation = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { bio, conversation_projects } = req.body + + if (!bio || conversation_projects === undefined) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + // جستجوی کاربر با استفاده از شناسه کاربر + const user = await UserModel.findById(userId) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شناسه یافت نشد' + }) + } + user.bio = bio + user.conversation_projects = conversation_projects + await user.save() + + return res.json({ + message: 'روابط عمومی با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +module.exports = { + setConversation, updateConversation +} diff --git a/public/modstagram-back/controllers/application/verify/cooperationTypeController.js b/public/modstagram-back/controllers/application/verify/cooperationTypeController.js new file mode 100644 index 0000000..2debfbe --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/cooperationTypeController.js @@ -0,0 +1,93 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setCooperationType = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { cooperation_type, cooperation_abroad } = req.body + if (!cooperation_type || cooperation_abroad === undefined) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + if (!['all', 'verified'].includes(cooperation_type)) { + return res.status(422).json({ + error: true, + message: 'نوع همکاری نیست' + }) + } + + // جستجوی کاربر با شماره موبایل ارسالی + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + user.cooperation_type = cooperation_type + user.cooperation_abroad = cooperation_abroad + await user.save() + + return res.json({ + message: 'نوع همکاری با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +const updateCooperationType = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { cooperation_type, cooperation_abroad } = req.body + + if (!cooperation_type || cooperation_abroad === undefined) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + if (!['all', 'verified'].includes(cooperation_type)) { + return res.status(422).json({ + error: true, + message: 'نوع همکاری نامعتبر است' + }) + } + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + // جستجوی کاربر با استفاده از شناسه کاربر + const user = await UserModel.findById(userId) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شناسه یافت نشد' + }) + } + + user.cooperation_type = cooperation_type + user.cooperation_abroad = cooperation_abroad + await user.save() + + return res.json({ + message: 'نوع همکاری با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + setCooperationType, + updateCooperationType +} diff --git a/public/modstagram-back/controllers/application/verify/expertiseController.js b/public/modstagram-back/controllers/application/verify/expertiseController.js new file mode 100644 index 0000000..3c88796 --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/expertiseController.js @@ -0,0 +1,81 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setExpertise = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { expertise, sub_expertise } = req.body + if (!expertise || !sub_expertise) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + // جستجوی کاربر با شماره موبایل ارسالی + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + // آپدیت نام کاربری به صورت lowercase + user.expertise = expertise + user.sub_expertise = sub_expertise + await user.save() + + return res.json({ + message: 'تخصص با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +const updateExpertise = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { expertise, sub_expertise } = req.body + + // اعتبارسنجی داده‌ها + if (!expertise || !sub_expertise) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی ناقص است' + }) + } + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + // یافتن کاربر با استفاده از شناسه کاربر + const user = await UserModel.findById(userId) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شناسه یافت نشد' + }) + } + + // به‌روزرسانی اطلاعات تخصص و زیرتخصص + user.expertise = expertise + user.sub_expertise = sub_expertise + await user.save() + + return res.json({ + message: 'تخصص با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +module.exports = { + setExpertise, updateExpertise +} diff --git a/public/modstagram-back/controllers/application/verify/genderController.js b/public/modstagram-back/controllers/application/verify/genderController.js new file mode 100644 index 0000000..2371eca --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/genderController.js @@ -0,0 +1,46 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setGender = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { gender } = req.body + if (!gender) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ورودی اشتباه است' + }) + } + if (!['male', 'female'].includes(gender)) { + return res.status(422).json({ + error: true, + message: 'جنسیت معتبر نیست' + }) + } + // جستجوی کاربر با شماره موبایل ارسالی + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + // آپدیت نوع یوزر + user.gender = gender.toLowerCase() + await user.save() + + return res.json({ + message: 'جنسیت با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + setGender +} diff --git a/public/modstagram-back/controllers/application/verify/servicesController.js b/public/modstagram-back/controllers/application/verify/servicesController.js new file mode 100644 index 0000000..6ce2826 --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/servicesController.js @@ -0,0 +1,107 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') +const fs = require('fs-extra') +const path = require('path') + +const setServices = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(422).json({ + error: true, + message: 'شما دسترسی به این بخش ندارید' + }) + } + const { services } = req.body + if (!services) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + // مدیریت تصاویر برای خدمات + const servicesWithImages = [] + const parsedServices = JSON.parse(services) // پارس کردن رشته JSON به آرایه جاوا اسکریپت + if (parsedServices && parsedServices.length > 0) { + for (const service of parsedServices) { + const serviceImages = [] + const serviceId = service.id + if (req.files && req.files.serviceImages && req.files.serviceImages[serviceId]) { + const imageFiles = Array.isArray(req.files.serviceImages[serviceId]) ? req.files.serviceImages[serviceId] : [req.files.serviceImages[serviceId]] + const uploadDir = path.join(__dirname, '../../../../storage/services') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + for (const imageFile of imageFiles) { + const uniqueFileName = `${user.user_name}-${Date.now()}${Math.random().toString().slice(2, 11)}${path.extname(imageFile.name)}` + const filePath = path.join(uploadDir, uniqueFileName) + // await fs.promises.rename(imageFile.path, filePath) + await fs.move(imageFile.path, filePath) + const imageUrl = `/services/${uniqueFileName}` + serviceImages.push(imageUrl) + // به‌روزرسانی مسیر تصویر در آبجکت service + service.image = imageUrl + } + } else { + console.log('sss') + } + servicesWithImages.push({ ...service, images: serviceImages }) + } + } + + user.services = servicesWithImages + await user.save() + + return res.json({ + message: 'خدمات با موفقیت ثبت شد' + }) + } catch (error) { + next(error) + } +} + +const updateServices = async (req, res, next) => { + try { + const { height, weight, size } = req.body + + if (!height || !weight || !size) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + // جستجوی کاربر + const user = await UserModel.findById(userId) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربر یافت نشد' + }) + } + + user.height = height + user.weight = weight + user.size = size + await user.save() + + return res.json({ + message: 'سایز با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +module.exports = { + setServices, updateServices +} diff --git a/public/modstagram-back/controllers/application/verify/setNationalCardImageController.js b/public/modstagram-back/controllers/application/verify/setNationalCardImageController.js new file mode 100644 index 0000000..9fdf27a --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/setNationalCardImageController.js @@ -0,0 +1,55 @@ +/* eslint-disable camelcase */ +const fs = require('fs-extra') +const path = require('path') +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setNationalCardImage = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { national_card_image } = req.files + // جستجوی کاربر با شماره موبایل ارسالی + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + // بررسی آیا فایل آپلود شده است + if (!national_card_image) { + return res.status(400).json({ + error: true, + message: 'لطفاً عکس کارت ملی را انتخاب کنید' + }) + } + + // ذخیره فایل عکس پروفایل + const uploadDir = path.join(__dirname, '../../../../storage/carts') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + + const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(national_card_image.name)}` + const filePath = path.join(uploadDir, uniqueFileName) + await fs.move(national_card_image.path, filePath) + + // ذخیره مسیر فایل در دیتابیس + user.national_card_image = `/carts/${uniqueFileName}` + user.is_verified = 'pending' + await user.save() + + return res.json({ + message: 'عکس کارت ملی با موفقیت ذخیره شد', + national_card_image: user.national_card_image + }) + } catch (error) { + next(error) + } +} + +module.exports = { + setNationalCardImage +} diff --git a/public/modstagram-back/controllers/application/verify/setProfileImageController.js b/public/modstagram-back/controllers/application/verify/setProfileImageController.js new file mode 100644 index 0000000..5c1d357 --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/setProfileImageController.js @@ -0,0 +1,105 @@ +/* eslint-disable camelcase */ +const fs = require('fs-extra') +const path = require('path') +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setProfileImage = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { mobile } = req.body + const { profile_image } = req.files + if (!mobile) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + // بررسی آیا فایل آپلود شده است + if (!profile_image) { + return res.status(400).json({ + error: true, + message: 'لطفاً عکس پروفایل را انتخاب کنید' + }) + } + + // ذخیره فایل عکس پروفایل + const uploadDir = path.join(__dirname, '../../../../storage/profiles') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(profile_image.name)}` + const filePath = path.join(uploadDir, uniqueFileName) + + await fs.move(profile_image.path, filePath) + // ذخیره مسیر فایل در دیتابیس + user.profile_image = `/profiles/${uniqueFileName}` + await user.save() + + return res.json({ + message: 'عکس پروفایل با موفقیت ذخیره شد', + profile_image: user.profile_image + }) + } catch (error) { + next(error) + } +} + +const updateProfileImage = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const { profile_image } = req.files + + if (!profile_image) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const user = await UserModel.findById(userId) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + const uploadDir = path.join(__dirname, '../../../../storage/profiles') + + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + + const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(profile_image.name)}` + const filePath = path.join(uploadDir, uniqueFileName) + + await fs.move(profile_image.path, filePath) + + user.profile_image = `/profiles/${uniqueFileName}` + await user.save() + + return res.json({ + message: 'عکس پروفایل با موفقیت به‌روزرسانی شد', + profile_image: user.profile_image + }) + } catch (error) { + next(error) + } +} +module.exports = { + setProfileImage, updateProfileImage +} diff --git a/public/modstagram-back/controllers/application/verify/sizesController.js b/public/modstagram-back/controllers/application/verify/sizesController.js new file mode 100644 index 0000000..3516069 --- /dev/null +++ b/public/modstagram-back/controllers/application/verify/sizesController.js @@ -0,0 +1,78 @@ +/* eslint-disable camelcase */ +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') + +const setSizes = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { height, weight, size } = req.body + if (!height || !weight || !size) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + // جستجوی کاربر با شماره موبایل ارسالی + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این شماره موبایل یافت نشد' + }) + } + + user.height = height + user.weight = weight + user.size = size + await user.save() + + return res.json({ + message: 'سایز با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} + +const updateSizes = async (req, res, next) => { + try { + const { height, weight, size } = req.body + + if (!height || !weight || !size) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + // جستجوی کاربر + const user = await UserModel.findById(userId) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربر یافت نشد' + }) + } + + user.height = height + user.weight = weight + user.size = size + await user.save() + + return res.json({ + message: 'سایز با موفقیت به‌روزرسانی شد' + }) + } catch (error) { + next(error) + } +} +module.exports = { + setSizes, updateSizes +} diff --git a/public/modstagram-back/controllers/application/version/versionController.js b/public/modstagram-back/controllers/application/version/versionController.js new file mode 100644 index 0000000..6b557f3 --- /dev/null +++ b/public/modstagram-back/controllers/application/version/versionController.js @@ -0,0 +1,16 @@ +const VersionModel = require('../../../models/VersionModel') + +// Endpoint برای دریافت نسخه فعلی +const getVersion = async (req, res, next) => { + try { + const currentVersion = await VersionModel.findOne().sort({ _id: -1 }).exec() + if (!currentVersion) { + return res.status(200).json({ message: 'نسخه‌ای پیدا نشد' }) + } + res.json(currentVersion) + } catch (error) { + res.status(500).json({ message: 'خطای سرور', error }) + } +} + +module.exports = { getVersion } diff --git a/public/modstagram-back/controllers/application/workroom/workroomController.js b/public/modstagram-back/controllers/application/workroom/workroomController.js new file mode 100644 index 0000000..bba1d1c --- /dev/null +++ b/public/modstagram-back/controllers/application/workroom/workroomController.js @@ -0,0 +1,232 @@ +/* eslint-disable camelcase */ +const ProjectModel = require('../../../models/ProjectModel') +const RequestModel = require('../../../models/RequestModel') +const UserModel = require('../../../models/UserModel') +const jwt = require('jsonwebtoken') +const calculateRemainingTime = (milliseconds) => { + const days = Math.floor(milliseconds / (1000 * 60 * 60 * 24)) + const hours = Math.floor((milliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) + + return `${days} روز و ${hours} ساعت` +} +const getProjects = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + // eslint-disable-next-line no-unused-vars + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const user = await UserModel.findById(decodedToken.id) + const { status_filter, page = 1, limit = 10 } = req.query // افزودن پارامترهای صفحه‌بندی به درخواست + // ساخت فیلتر برای استفاده در جستجوی MongoDB + let filter = {} // افزودن شرط برای payment_status + if (user.user_type === 'user') { + if (status_filter) { + if (status_filter === 'دریافتی') { + filter = { created_for_user: userId, status: 'accepted' } + } else if (status_filter === 'ارسال شده') { + filter = { requested_users: userId, status: 'accepted' } + } else if (status_filter === 'در دست اقدام') { + filter = { selected_user: userId, status: 'ongoing' } + } else if (status_filter === 'اتمام پروژه') { + filter = { selected_user: userId, status: 'done' } + } else if (status_filter === 'کنسل شده') { + filter = { selected_user: userId, status: 'cancled' } + } else { + filter = { + $or: [ + { selected_user: userId }, + { requested_users: userId }, + { created_for_user: userId } + ] + } + } + } else { + filter = { + $or: [ + { selected_user: userId }, + { requested_users: userId }, + { created_for_user: userId } + ] + } + } + } else { + if (status_filter) { + if (status_filter === 'منتشر شده') { + filter = { creator_id: userId, status: 'accepted' } + } else if (status_filter === 'در دست اقدام') { + filter = { creator_id: userId, status: 'ongoing' } + } else if (status_filter === 'اتمام پروژه') { + filter = { creator_id: userId, status: 'done' } + } else if (status_filter === 'کنسل شده') { + filter = { creator_id: userId, status: 'cancled' } + } else if (status_filter === 'در دست بررسی') { + filter = { creator_id: userId, status: { $in: ['paid', 'rejected'] } } + } else if (status_filter === 'پرداخت نشده') { + filter = { creator_id: userId, status: 'pre_payment' } + } else { + filter = { creator_id: userId } + } + } else { + filter = { creator_id: userId } + } + } + // paid + // دریافت لیست پروژه‌ها با استفاده از فیلتر + + // استفاده از مدل پیجینیت شده برای دریافت نتایج صفحه‌بندی شده + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: { createdAt: -1 } + } + const projects = await ProjectModel.paginate(filter, options) + const projectsWithUserInfo = await Promise.all(projects?.docs.map(async project => { + const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate') + const projectWithUserInfo = { + ...project._doc, + creator, + status_filter + } + const currentTime = new Date() + const projectCreatedAt = new Date(project.createdAt) + const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt) + const remainingTime = calculateRemainingTime(timeDiff) + projectWithUserInfo.remainingTime = remainingTime + return projectWithUserInfo + })) + res.status(200).json({ + projects: projectsWithUserInfo, + totalPages: projects.totalPages, // ارسال تعداد کل صفحات + totalItems: projects.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + next(error) + } +} +const getSingleProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + const projectId = req.query.projectId + const projectRequests = await RequestModel.find({ project: projectId }) + .populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image') + .sort({ status: 1 }) + .lean() + const modifiedRequests = projectRequests.map(request => ({ + ...request, + time: request?.user?._id.toString() === userId ? request.time : null, + price: request?.user?._id.toString() === userId ? request.price : null + })) + const project = await ProjectModel.findById(projectId) + if (!project) { + return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' }) + } + // محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده + // تابع محاسبه مبلغ پرداخت شده + const getTotalPaidAmount = (installments) => { + let totalPaidAmount = 0 + installments.forEach(installment => { + totalPaidAmount += installment.amount + }) + return totalPaidAmount + } + + // تابع محاسبه مبلغ باقیمانده + const getRemainingAmount = (project) => { + const totalPaidAmount = getTotalPaidAmount(project.installments) + const remainingAmount = project.final_price - totalPaidAmount + return remainingAmount + } + + const totalPaidAmount = getTotalPaidAmount(project.installments) + const remainingAmount = getRemainingAmount(project) + // اطلاعات کاربر سازنده را نیز دریافت کنید و به آبجکت پروژه اضافه کنید + const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate') + + const projectWithUserInfo = { + ...project._doc, + creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه + } + const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score') + projectWithUserInfo.selected_user = selectedUser + // محاسبه مدت زمان باقی‌مانده برای پروژه + const currentTime = new Date() + const projectCreatedAt = new Date(project.createdAt) + const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt) + const remainingTime = calculateRemainingTime(timeDiff) + projectWithUserInfo.remainingTime = remainingTime + let projectDetails = projectWithUserInfo + if ((project.selected_user && project.selected_user.toString()) === userId || project.creator_id.toString() === userId) { + projectDetails = { + ...projectWithUserInfo, + total_paid_amount: totalPaidAmount, + remaining_amount: remainingAmount + } + } else { + projectDetails = + projectWithUserInfo + } + // } + res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests }) + } catch (error) { + next(error) + } +} + +const getProjectRequests = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + // بررسی اینکه آیا کاربر ایجاد کننده پروژه است یا خیر + const projectId = req.params.projectId + const project = await ProjectModel.findOne({ _id: projectId, creator_id: userId }) + if (!project) { + return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' }) + } + + // تابع محاسبه مبلغ پرداخت شده + const getTotalPaidAmount = (installments) => { + let totalPaidAmount = 0 + installments.forEach(installment => { + totalPaidAmount += installment.amount + }) + return totalPaidAmount + } + + // تابع محاسبه مبلغ باقیمانده + const getRemainingAmount = (project) => { + const totalPaidAmount = getTotalPaidAmount(project.installments) + const remainingAmount = project.final_price - totalPaidAmount + return remainingAmount + } + + // محاسبه مبلغ باقیمانده + const remainingAmount = getRemainingAmount(project) + + // یافتن جزییات پروژه + const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate') + const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score') + const totalPaidAmount = getTotalPaidAmount(project.installments) + + const projectRequests = await RequestModel.find({ project: projectId }).populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image').sort({ status: 1 }) + const projectinfo = await ProjectModel.findById(projectId) // جزییات درخواست‌های کاربران + projectinfo.selected_user = selectedUser + const projectDetails = { + ...projectinfo._doc, + creator, + total_paid_amount: totalPaidAmount, + remaining_amount: remainingAmount + } + res.status(200).json({ projectRequests, projectDetails }) + } catch (error) { + next(error) + } +} +module.exports = { + getProjects, getSingleProject, getProjectRequests +} diff --git a/public/modstagram-back/controllers/panel/advertising/academyCategoryController.js b/public/modstagram-back/controllers/panel/advertising/academyCategoryController.js new file mode 100644 index 0000000..9e52065 --- /dev/null +++ b/public/modstagram-back/controllers/panel/advertising/academyCategoryController.js @@ -0,0 +1,50 @@ +const AcademyCategoryModel = require('../../models/AcademyCategoryModel'); + +// دریافت همه دسته‌بندی‌های اکادمی +exports.getAll = async (req, res) => { + try { + const categories = await AcademyCategoryModel.find({}).sort({ createdAt: -1 }); + res.json({ success: true, data: categories }); + } catch (error) { + res.status(500).json({ success: false, message: error.message }); + } +}; + +// ایجاد دسته‌بندی جدید +exports.create = async (req, res) => { + try { + const { title } = req.body; + if (!title) return res.status(400).json({ success: false, message: "عنوان الزامی است" }); + + const category = await AcademyCategoryModel.create({ title }); + res.status(201).json({ success: true, message: "دسته‌بندی ایجاد شد", data: category }); + } catch (error) { + res.status(500).json({ success: false, message: error.message }); + } +}; + +// ویرایش دسته‌بندی +exports.update = async (req, res) => { + try { + const { id } = req.params; + const { title, status } = req.body; + + const category = await AcademyCategoryModel.findByIdAndUpdate(id, { title, status }, { new: true }); + if (!category) return res.status(404).json({ success: false, message: "دسته‌بندی یافت نشد" }); + + res.json({ success: true, message: "دسته‌بندی ویرایش شد", data: category }); + } catch (error) { + res.status(500).json({ success: false, message: error.message }); + } +}; + +// حذف دسته‌بندی +exports.remove = async (req, res) => { + try { + const { id } = req.params; + await AcademyCategoryModel.findByIdAndDelete(id); + res.json({ success: true, message: "دسته‌بندی حذف شد" }); + } catch (error) { + res.status(500).json({ success: false, message: error.message }); + } +}; \ No newline at end of file diff --git a/public/modstagram-back/controllers/panel/advertising/advertisingController.js b/public/modstagram-back/controllers/panel/advertising/advertisingController.js new file mode 100644 index 0000000..63831b2 --- /dev/null +++ b/public/modstagram-back/controllers/panel/advertising/advertisingController.js @@ -0,0 +1,350 @@ +/* eslint-disable eqeqeq */ +/* eslint-disable camelcase */ +const { ProvinceModel, CityModel } = require('../../../models/StateCity') +const AdvertisingModel = require('../../../models/AdvertisingModel') +// const AdvertisingLikeModel = require('../../../models/AdvertisingLikeModel') +// const AdvertisingComment = require('../../../models/AdvertisingCommentModel') +const AdvertisingProfileModel = require('../../../models/AdvertisingProfile') +const NotificationModel = require('../../../models/NotificationModel') +const AdvertisingCategoryModel = require('../../../models/AdvertisingCategoryModel') + + +const getAdvertisings = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { + page = 1, limit = 10, province, city, category, search, + startDate, + endDate, + status + } = req.query + + const filter = { + } + if (province) { + const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 }) + filter.province = provinceFind + } + if (city) { + const cityFind = await CityModel.findOne({ id: city }) + filter.city = cityFind + } + if (category) { + filter.category = category + } + if (search) { + filter.$or = [ + { title: { $regex: search, $options: 'i' } }, + { category: { $regex: search, $options: 'i' } } + ] + } + + // Date + if (startDate || endDate) { + filter.createdAt = {} + + if (startDate) { + filter.createdAt.$gte = new Date(startDate) // تاریخ شروع + } + + if (endDate) { + filter.createdAt.$lte = new Date(endDate) // تاریخ پایان + } + } + + if (status) { + filter.status = status + } + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { createdAt: -1 }, + populate: [ + { path: 'creator_id', select: 'user_name first_name last_name' } + ] + } + const advertisings = await AdvertisingModel.paginate(filter, options) + + const newAds = advertisings.docs.map(ad => { + return { + // فیلدهای مشخص‌شده از ad._doc + _id: ad._doc._id, + creator_id: ad._doc.creator_id, + category: ad._doc.category, + title: ad._doc.title, + province: ad._doc.province, + city: ad._doc.city, + status: ad._doc.status, + neighbourhood: ad._doc.neighbourhood + } + }) + res.status(200).json({ + advertisings: newAds, + totalPages: advertisings.totalPages, + totalItems: advertisings.totalDocs + }) + } catch (error) { + next(error) + } +} +const getSingleAdvertising = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const advertisingId = req.query.advertisingId + const advertising = await AdvertisingModel.findById(advertisingId) + .populate('creator_id', '_id user_name first_name last_name') + + if (!advertising) { + return res.status(404).json({ message: 'ویترین مورد نظر یافت نشد' }) + } + + const creator = await AdvertisingProfileModel.findOne({ user: advertising.creator_id._id }) + + // اضافه کردن تعداد لایک‌ها، تعداد کامنت‌ها و وضعیت لایک به تبلیغ + const advertisingData = { + ...advertising._doc + } + + res.status(200).json({ + advertising: advertisingData, + creator + }) + } catch (error) { + next(error) + } +} +const acceptAdvertising = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { advertisingId } = req.body + + // پیدا کردن تبلیغ + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + return res.status(404).json({ message: 'تبلیغ مورد نظر یافت نشد' }) + } + + // تغییر وضعیت به accepted و ذخیره زمان قبول شدن + advertising.status = 'accepted' + advertising.acceptedAt = new Date() + await advertising.save() + const notification = new NotificationModel({ + user_id: advertising?.creator_id, + project_post_id: advertising?._id, + type: 'vitrine', + title: 'تایید ویترین', + description: `ویترین شما با عنوان: ${advertising?.title} تایید و منتشر شد ` + }) + await notification.save() + + res.status(200).json({ message: 'تبلیغ اکسپت شد و پس از 15 روز منقضی خواهد شد' }) + } catch (error) { + next(error) + } +} +const rejectAdvertising = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { advertisingId, rejectReason } = req.body + + // پیدا کردن تبلیغ + const advertising = await AdvertisingModel.findById(advertisingId) + if (!advertising) { + return res.status(404).json({ message: 'تبلیغ مورد نظر یافت نشد' }) + } + + // تغییر وضعیت به rejected و ذخیره دلیل رد شدن + advertising.status = 'rejected' + advertising.reject_reason = rejectReason + await advertising.save() + const notification = new NotificationModel({ + user_id: advertising?.creator_id, + project_post_id: advertising?._id, + type: 'vitrine', + title: 'رد ویترین', + description: `ویترین شما با عنوان: ${advertising?.title} رد شد، برای دیدن علت رد، لمس کنید ` + }) + await notification.save() + res.status(200).json({ message: 'تبلیغ رد شد', advertising }) + } catch (error) { + next(error) + } +} + + +const deleteAdvertisingCategory = async (req, res, next) => { + try { + const { id } = req.params + + // چک کنه که ID معتبره + if (!id.match(/^[0-9a-fA-F]{24}$/)) { + return res.status(400).json({ + success: false, + message: 'شناسه معتبر نمی‌باشد' + }) + } + + // پیدا کنه دسته‌بندی رو + const category = await AdvertisingCategoryModel.findById(id) + if (!category) { + return res.status(404).json({ + success: false, + message: 'دسته‌بندی مورد نظر یافت نشد' + }) + } + + // حذف کنه + await category.deleteOne() + + return res.status(200).json({ + success: true, + message: 'دسته‌بندی تبلیغات با موفقیت حذف شد', + data: { id } + }) + } catch (error) { + next(error) + } +} + +const createAdvertisingCategory = async (req, res, next) => { + try { + const { title, status } = req.body + + // اعتبارسنجی ورودی‌ها + if (!title || title.trim().length < 1) { + return res.status(400).json({ + success: false, + message: 'عنوان دسته‌بندی الزامی است' + }) + } + + if (title.length > 255) { + return res.status(400).json({ + success: false, + message: 'عنوان دسته‌بندی نباید بیشتر از ۲۵۵ کاراکتر باشد' + }) + } + + // بررسی اینکه دسته‌بندی تکراری نباشد + const exists = await AdvertisingCategoryModel.findOne({ title: title.trim() }) + if (exists) { + return res.status(409).json({ + success: false, + message: 'این دسته‌بندی از قبل وجود دارد' + }) + } + + // ایجاد دسته‌بندی جدید + const newCategory = await AdvertisingCategoryModel.create({ + title: title.trim(), + status: status ?? true + }) + + return res.status(201).json({ + success: true, + message: 'دسته‌بندی تبلیغات با موفقیت ایجاد شد', + data: newCategory + }) + } catch (error) { + next(error) // میره به errorHandler مرکزی + } +} + +const getAdvertisingCategories = async (req, res, next) => { + try { + const page = Math.max(parseInt(req.query.page || '1', 10), 1); + const limit = Math.max(Math.min(parseInt(req.query.limit || '20', 10), 100), 1); + const { status, q, sort } = req.query; + + const query = {}; + if (typeof status !== 'undefined') { + // accept 'true'/'false' or boolean + if (status === 'true' || status === 'false') query.status = status === 'true'; + else if (status === '1' || status === '0') query.status = status === '1'; + } + if (q) { + query.title = { $regex: q.trim(), $options: 'i' }; + } + + const options = { + page, + limit, + sort: sort || '-createdAt', + lean: true, + }; + + // اگر mongoose-paginate-v2 نصب و فعال است: + if (typeof AdvertisingCategoryModel.paginate === 'function') { + const result = await AdvertisingCategoryModel.paginate(query, options); + return res.status(200).json({ + success: true, + totalDocs: result.totalDocs, + totalPages: result.totalPages, + page: result.page, + limit: result.limit, + docs: result.docs, + }); + } + + // fallback بدون paginate + const docs = await AdvertisingCategoryModel.find(query) + .sort(options.sort) + .skip((page - 1) * limit) + .limit(limit) + .lean(); + + const totalDocs = await AdvertisingCategoryModel.countDocuments(query); + const totalPages = Math.ceil(totalDocs / limit); + + return res.status(200).json({ + success: true, + totalDocs, + totalPages, + page, + limit, + docs, + }); + } catch (error) { + next(error); + } +}; + +/** + * GET /advertising/advertising-categories/:id + */ +const getAdvertisingCategoryById = async (req, res, next) => { + try { + const { id } = req.params; + if (!id || !id.match(/^[0-9a-fA-F]{24}$/)) { + return res.status(400).json({ success: false, message: 'شناسه معتبر نیست' }); + } + + const category = await AdvertisingCategoryModel.findById(id).lean(); + if (!category) { + return res.status(404).json({ success: false, message: 'دسته‌بندی یافت نشد' }); + } + + return res.status(200).json({ success: true, data: category }); + } catch (error) { + next(error); + } +}; + + +module.exports = { + getSingleAdvertising, + getAdvertisings, + deleteAdvertisingCategory, + createAdvertisingCategory, + getAdvertisingCategories, + getAdvertisingCategoryById, + acceptAdvertising, + rejectAdvertising +} diff --git a/public/modstagram-back/controllers/panel/comments/advertisingCommentController.js b/public/modstagram-back/controllers/panel/comments/advertisingCommentController.js new file mode 100644 index 0000000..f992c03 --- /dev/null +++ b/public/modstagram-back/controllers/panel/comments/advertisingCommentController.js @@ -0,0 +1,195 @@ +/* eslint-disable camelcase */ +const AdvertisingComment = require('../../../models/AdvertisingCommentModel') +const jMoment = require('moment-jalaali') +const mongoose = require('mongoose') +const AdvertisingModel = require('../../../models/AdvertisingModel') +const NotificationModel = require('../../../models/NotificationModel') + +// دریافت کامنت‌ها +const getAdvertisingComments = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { + page = 1, limit = 10, + startDate, + endDate, + status + } = req.query + const filter = {} + + // Date + if (startDate || endDate) { + filter.createdAt = {} + + if (startDate) { + filter.createdAt.$gte = new Date(startDate) // تاریخ شروع + } + + if (endDate) { + filter.createdAt.$lte = new Date(endDate) // تاریخ پایان + } + } + + if (status) { + filter.status = status + } + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { createdAt: -1 }, + populate: [ + { path: 'userId', select: 'user_name first_name last_name profile_image' }, + { path: 'advertisingId', select: 'title', populate: { path: 'creator_id', select: 'user_name first_name last_name' } } + // اضافه کردن اطلاعات سازنده + ] + } + + const comments = await AdvertisingComment.paginate(filter, options) + const commentList = comments.docs.map(comment => ({ + _id: comment._id, + createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'), + status: comment.status, + text: comment.text, + advertising: comment.advertisingId ? comment.advertisingId.title : null, + user: comment.userId ? { + _id: comment.userId._id, + user_name: comment.userId.user_name, + first_name: comment.userId.first_name, + last_name: comment.userId.last_name, + profile_image: comment.userId.profile_image + } : null, + creator: (comment.advertisingId && comment.advertisingId.creator_id) ? { + _id: comment.advertisingId.creator_id._id, + user_name: comment.advertisingId.creator_id.user_name, + first_name: comment.advertisingId.creator_id.first_name, + last_name: comment.advertisingId.creator_id.last_name + } : null + })); + + + res.status(200).json({ + comments: commentList, + totalPages: comments.totalPages, + totalItems: comments.totalDocs + }) + } catch (error) { + next(error) + } +} + +// دریافت جزئیات یک کامنت +const getAdvertisingCommentDetail = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const comment_id = req.query.comment_id + + if (!mongoose.Types.ObjectId.isValid(comment_id)) { + return res.status(400).json({ message: 'شناسه کامنت معتبر نیست' }) + } + + const comment = await AdvertisingComment.findById(comment_id) + .populate('userId', 'user_name first_name last_name profile_image') + .populate({ + path: 'advertisingId', + select: 'title creator_id', + populate: { + path: 'creator_id', + select: 'user_name first_name last_name' + } + }) + if (!comment) { + return res.status(404).json({ message: 'کامنت مورد نظر یافت نشد' }) + } + + const response = { + _id: comment._id, + text: comment.text, + createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'), + status: comment.status, + advertising: comment.advertisingId ? comment.advertisingId.title : null, + creator: { + _id: comment?.advertisingId?.creator_id._id, + user_name: comment?.advertisingId?.creator_id.user_name, + first_name: comment?.advertisingId?.creator_id.first_name, + last_name: comment?.advertisingId?.creator_id.last_name + }, + user: { + _id: comment.userId._id, + user_name: comment.userId.user_name, + first_name: comment.userId.first_name, + last_name: comment.userId.last_name, + profile_image: comment.userId.profile_image + } + } + + res.status(200).json({ comment: response }) + } catch (error) { + next(error) + } +} + +// تایید یک کامنت +const acceptAdvertisingComment = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { id, status, text } = req.body + + if (!id || !status) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const comment = await AdvertisingComment.findById(id) + // افزایش تعداد کامنت‌های تبلیغ + await AdvertisingModel.findByIdAndUpdate(comment?.advertisingId, { $inc: { commentsCount: 1 } }) + if (!comment) { + return res.status(404).json({ + error: true, + message: 'کامنت مورد نظر یافت نشد' + }) + } + + if (text) { + comment.text = text + } + comment.status = status + await comment.save() + + if (status === 'accepted') { + const notification = new NotificationModel({ + user_id: comment?.userId, + project_post_id: comment?.advertisingId, + type: 'vitrine-comment', + title: 'انتشار نظر', + description: 'نظر شما منتشر شد.' + }) + await notification.save() + } else { + const notification = new NotificationModel({ + user_id: comment?.userId, + project_post_id: comment?.advertisingId, + type: 'vitrine-comment', + title: 'رد نظر', + description: 'نظر شما رد شد.' + }) + await notification.save() + } + res.status(201).json({ message: 'کامنت با موفقیت تایید شد' }) + } catch (error) { + next(error) + } +} + +module.exports = { + getAdvertisingComments, + getAdvertisingCommentDetail, + acceptAdvertisingComment +} diff --git a/public/modstagram-back/controllers/panel/comments/commentController.js b/public/modstagram-back/controllers/panel/comments/commentController.js new file mode 100644 index 0000000..c0548e9 --- /dev/null +++ b/public/modstagram-back/controllers/panel/comments/commentController.js @@ -0,0 +1,172 @@ +/* eslint-disable camelcase */ +const CommentModel = require('../../../models/CommentModel') +const jMoment = require('moment-jalaali') +const { default: mongoose } = require('mongoose') + +// دریافت لیست کامنت‌ها با پیجینیشن +const getComments = async (req, res, next) => { + try { + console.log("gg6"); + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { + page = 1, limit = 10, + startDate, + endDate, + status + } = req.query + const filter = {} // فیلتر بر اساس وضعیت کامنت + + // Date + if (startDate || endDate) { + filter.createdAt = {} + + if (startDate) { + filter.createdAt.$gte = new Date(startDate) // تاریخ شروع + } + + if (endDate) { + filter.createdAt.$lte = new Date(endDate) // تاریخ پایان + } + } + console.log("gg8"); + if (status) { + filter.status = status + } + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: { createdAt: -1 }, + populate: [ + { path: 'creator', select: 'user_name first_name last_name profile_image ' }, + { path: 'user', select: 'user_name first_name last_name' }, + { path: 'project', select: 'title' } + ] + } + + const comments = await CommentModel.paginate(filter, options) + const commentList = comments.docs.map(comment => ({ + _id: comment._id, + createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'), + status: comment.status, + comment_for: comment.comment_for, + project: comment.project ? comment.project.title : null, + creator: comment.creator ? { + _id: comment.creator._id, + user_name: comment.creator.user_name, + first_name: comment.creator.first_name, + last_name: comment.creator.last_name, + profile_image: comment.creator.profile_image + } : null, + user: comment.user ? { + _id: comment.user._id, + user_name: comment.user.user_name, + first_name: comment.user.first_name, + last_name: comment.user.last_name + } : null + })); + + console.log("gg9"); + res.status(200).json({ + comments: commentList, + totalPages: comments.totalPages, + totalItems: comments.totalDocs + }) + } catch (error) { + console.log("gg"); + + next(error) + } +} + +// دریافت جزئیات یک کامنت +const getCommentDetail = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const comment_id = req.query.comment_id + + if (!mongoose.Types.ObjectId.isValid(comment_id)) { + return res.status(400).json({ message: 'شناسه کامنت معتبر نیست' }) + } + + const comment = await CommentModel.findById(comment_id) + .populate('creator', 'user_name first_name last_name profile_image ') + .populate('user', 'user_name first_name last_name') + .populate('project', 'title') + + if (!comment) { + return res.status(404).json({ message: 'کامنت مورد نظر یافت نشد' }) + } + + const response = { + _id: comment._id, + comment: comment.comment, + rating: comment.rating, + createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'), + status: comment.status, + comment_for: comment.comment_for, + project: comment.project ? comment.project.title : null, + creator: { + _id: comment.creator._id, + user_name: comment.creator.user_name, + first_name: comment.creator.first_name, + last_name: comment.creator.last_name, + profile_image: comment.creator.profile_image + }, + user: { + _id: comment.user._id, + user_name: comment.user.user_name, + first_name: comment.user.first_name, + last_name: comment.user.last_name + } + } + + res.status(200).json({ comment: response }) + } catch (error) { + next(error) + } +} + +// تایید یک کامنت +const acceptComment = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { id, status, text } = req.body + + if (!id || !status) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const comment = await CommentModel.findById(id) + + if (!comment) { + return res.status(404).json({ + error: true, + message: 'کامنت مورد نظر یافت نشد' + }) + } + if (text) { + comment.comment = text + } + comment.status = status + await comment.save() + + res.status(201).json({ message: 'کامنت با موفقیت تایید شد' }) + } catch (error) { + next(error) + } +} + +module.exports = { + getComments, + getCommentDetail, + acceptComment +} diff --git a/public/modstagram-back/controllers/panel/expertise/expertiseController.js b/public/modstagram-back/controllers/panel/expertise/expertiseController.js new file mode 100644 index 0000000..e1cf9b4 --- /dev/null +++ b/public/modstagram-back/controllers/panel/expertise/expertiseController.js @@ -0,0 +1,111 @@ +/* eslint-disable camelcase */ +const ExpertiseModel = require('../../../models/ExpertiseModel') + +const createExpertise = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { expertise } = req.body + if (!expertise + ) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + // بررسی وجود تخصص با این نام در پایگاه داده + const existingExpertise = await ExpertiseModel.findOne({ expertise }) + + if (existingExpertise) { + return res.status(400).json({ message: 'تخصص با این نام قبلاً ثبت شده است' }) + } + + // ایجاد یک نمونه جدید از مدل ExpertiseModel + const newExpertise = new ExpertiseModel({ + expertise + }) + + // ذخیره تخصص جدید در پایگاه داده + await newExpertise.save() + + res.json({ message: 'تخصص با موفقیت اضافه شد' }) + } catch (error) { + next(error) + } +} + +const createSubExpertise = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const expertiseId = req.query.id + const { name } = req.body + if (!expertiseId || !name) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + // یافتن تخصص موردنظر از طریق آیدی + const expertise = await ExpertiseModel.findById(expertiseId) + + if (!expertise) { + return res.status(404).json({ message: 'تخصص موردنظر یافت نشد' }) + } + + // اضافه کردن زیرتخصص جدید به آرایه sub_expertise تخصص موجود + expertise.sub_expertise.push({ name }) + await expertise.save() + + res.json({ message: 'زیرتخصص با موفقیت به تخصص اضافه شد' }) + } catch (error) { + next(error) + } +} +const getExpertise = async (req, res, next) => { + try { + const expertises = await ExpertiseModel.find().select('expertise sub_expertise') + res.json({ expertises }) + } catch (error) { + next(error) + } +} + +// ویرایش تخصص +const editExpertise = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { expertise } = req.body + const expertiseId = req.params.id + + if (!expertise || !expertiseId) { + return res.status(422).json({ message: 'اطلاعات ارسالی اشتباه است' }) + } + + const updatedExpertise = await ExpertiseModel.findByIdAndUpdate( + expertiseId, + { expertise }, + { new: true } + ) + + if (!updatedExpertise) { + return res.status(404).json({ message: 'تخصص یافت نشد' }) + } + + res.json({ message: 'تخصص با موفقیت ویرایش شد' }) + } catch (error) { + next(error) + } +} + +module.exports = { + createExpertise, + createSubExpertise, + getExpertise, + editExpertise + +} diff --git a/public/modstagram-back/controllers/panel/financial/financialController.js b/public/modstagram-back/controllers/panel/financial/financialController.js new file mode 100644 index 0000000..c87c796 --- /dev/null +++ b/public/modstagram-back/controllers/panel/financial/financialController.js @@ -0,0 +1,108 @@ +/* eslint-disable camelcase */ +const { default: mongoose } = require('mongoose') +const PaymentModel = require('../../../models/PaymentModel') +const jMoment = require('moment-jalaali') + +const getFinancial = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { + page = 1, limit = 10, + startDate, + endDate, + status + } = req.query + const filter = {} // افزودن شرط‌های دیگر برای فیلتر + + // Date + if (startDate || endDate) { + filter.createdAt = {} + + if (startDate) { + filter.createdAt.$gte = new Date(startDate) // تاریخ شروع + } + + if (endDate) { + filter.createdAt.$lte = new Date(endDate) // تاریخ پایان + } + } + + if (status) { + filter.status = status + } + + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: { createdAt: -1 }, + populate: [ + { + path: 'user_id', + select: '_id user_name first_name mobile last_name ' + }, + { + path: 'project_id', + select: '_id title project_type' + } + ] + } + const financial = await PaymentModel.paginate( + filter, // فیلتر + options // گزینه‌های پیجینیشن + ) + const financialList = financial?.docs.map(financia => { + const jDate = jMoment(financia.createdAt).format('jYYYY-jMM-jDD HH:mm') + return { + ...financia._doc, + createdAt: jDate + } + }) + res.json({ + financials: financialList, + totalPages: financial.totalPages, // ارسال تعداد کل صفحات + totalItems: financial.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +const getFinancialDetail = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const financial_id = req.query.financial_id + if (!mongoose.Types.ObjectId.isValid(financial_id)) { + return res.status(400).json({ message: 'شناسه تراکنش معتبر نیست' }) + } + const financial = await PaymentModel.findById(financial_id).populate([ + { + path: 'user_id', + select: '_id user_name first_name mobile last_name shaba' + }, + { + path: 'project_id', + select: '_id title project_type', + populate: { + path: 'selected_user', + select: '_id user_name first_name mobile last_name shaba' + } + } + ]) + + if (!financial) { + return res.status(404).json({ message: 'تراکنش مورد نظر یافت نشد' }) + } + const newfinancial = { + ...financial._doc, + createdAt: jMoment(financial.createdAt).format('jYYYY-jMM-jDD HH:mm') + } + return res.status(200).json({ financial: newfinancial }) + } catch (error) { + console.error('Error occurred:', error) + res.status(500).json({ error: 'Internal server error' }) + } +} +module.exports = { getFinancial, getFinancialDetail } diff --git a/public/modstagram-back/controllers/panel/login/loginController.js b/public/modstagram-back/controllers/panel/login/loginController.js new file mode 100644 index 0000000..1b38717 --- /dev/null +++ b/public/modstagram-back/controllers/panel/login/loginController.js @@ -0,0 +1,94 @@ +/* eslint-disable camelcase */ +const AdminModel = require('../../../models/AdminModel') +const bcrypt = require('bcryptjs') +const TokenService = require('../../../services/TokenService') + +const adminLogin = async (req, res, next) => { + try { + // اعتبارسنجی ورودی ها + const { user_name, password } = req.body + if (!user_name || !password) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + // یافتن کاربر با نام کاربری + const userLow = user_name.toLowerCase() + const user = await AdminModel.findOne({ user_name: userLow }) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این نام کاربری یافت نشد' + }) + } + if (!user.password) { + return res.status(422).json({ + error: true, + message: 'رمز عبور برای این کاربر تنظیم نشده است' + }) + } + const isPasswordValid = await bcrypt.compare(password, user.password) + if (!isPasswordValid) { + return res.status(422).json({ + error: true, + message: 'نام کاربری یا رمز عبور اشتباه است' + }) + } + + // اگر هم نام کاربری و هم رمز عبور درست بود، ارسال پیام موفقیت آمیز + const token = TokenService.sign({ id: user._id }) + return res.json({ + message: 'کد تایید صحیح بود', + token, + id: user._id + }) + } catch (error) { + next(error) + } +} +const changePassword = async (req, res, next) => { + try { + // اعتبارسنجی ورودی ها + const { user_name, password, new_password } = req.body + if (!user_name || !password || !new_password) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + // یافتن کاربر با نام کاربری + const userLow = user_name.toLowerCase() + const user = await AdminModel.findOne({ user_name: userLow }) + + if (!user) { + return res.status(404).json({ + error: true, + message: 'کاربری با این نام کاربری یا رمز عبور یافت نشد' + }) + } + const isPasswordValid = await bcrypt.compare(password, user.password) + if (!isPasswordValid) { + return res.status(422).json({ + error: true, + message: 'نام کاربری یا رمز عبور اشتباه است' + }) + } + + // هش کردن پسورد جدید و ذخیره در دیتابیس + const hashedPassword = await bcrypt.hash(new_password, 10) + user.password = hashedPassword + await user.save() + + return res.json({ + message: 'کلمه عبور با موفقیت ذخیره شد' + }) + } catch (error) { + next(error) + } +} + +module.exports = { + adminLogin, changePassword +} diff --git a/public/modstagram-back/controllers/panel/posts/postController.js b/public/modstagram-back/controllers/panel/posts/postController.js new file mode 100644 index 0000000..9f7ff85 --- /dev/null +++ b/public/modstagram-back/controllers/panel/posts/postController.js @@ -0,0 +1,176 @@ +/* eslint-disable camelcase */ +const NotificationModel = require('../../../models/NotificationModel') +const PostModel = require('../../../models/PostModel') +const UserModel = require('../../../models/UserModel') +const jMoment = require('moment-jalaali') +const { default: mongoose } = require('mongoose') + +const getPosts = async (req, res, next) => { + try { + const authHeader = req.header('Authorization'); + if (!authHeader || !authHeader.startsWith('Bearer ')) { + return res.status(401).json({ message: 'Access Denied: No token provided' }); + } + const token = authHeader.split(' ')[1]; + + const { + page = 1, + limit = 10, + startDate, + endDate, + status, + } = req.query; + + const filter = {}; + if (startDate || endDate) { + filter.createdAt = {}; + if (startDate) { + filter.createdAt.$gte = new Date(startDate); + } + if (endDate) { + filter.createdAt.$lte = new Date(endDate); + } + } + if (status) { + filter.status = status; + } + + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { createdAt: -1 }, + populate: { + path: 'user_id', + select: '_id user_name first_name mobile last_name national_code user_type expertise', + }, + }; + + const posts = await PostModel.paginate(filter, options); + const postList = posts.docs.map((post) => ({ + _id: post._id, + post_image: post.post_images && post.post_images.length > 0 ? post.post_images[0] : post.post_video || null, // استفاده از اولین تصویر یا ویدئو + status: post.status, + post_images: post.post_images, + post_video: post.post_video, + type: post.type, + files: post.files, + user_id: post.user_id?._id || null, + user_name: post.user_id?.user_name || '-', + user_type: post.user_id?.user_type || '-', + expertise: post.user_id?.expertise || '-', + first_name: post.user_id?.first_name || '-', + last_name: post.user_id?.last_name || '-', + mobile: post.user_id?.mobile || '-', + national_code: post.user_id?.national_code || '-', + createdAt: post.createdAt ? jMoment(post.createdAt).format('jYYYY-jMM-jDD HH:mm') : '-', + })); + + res.status(200).json({ + posts: postList, + totalPages: posts.totalPages, + totalItems: posts.totalDocs, + }); + } catch (error) { + console.error('Error in getPosts:', error); + res.status(500).json({ message: 'خطا در دریافت پست‌ها.' }); + } +}; +const getPostDetail = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const post_id = req.query.post_id + // eslint-disable-next-line no-unused-vars + + if (!mongoose.Types.ObjectId.isValid(post_id)) { + return res.status(400).json({ message: 'شناسه پست معتبر نیست' }) + } + const post = await PostModel.findById(post_id).populate('user_id', '_id user_name first_name last_name profile_image user_level') + + if (!post) { + return res.status(404).json({ message: 'پست مورد نظر یافت نشد' }) + } + const response = { + _id: post._id, + post_image: post.post_images && post.post_images.length > 0 ? post.post_images[0] : post.post_video || null, // استفاده از اولین تصویر یا ویدئو + status: post.status, + caption: post.caption, + comments: post.comments, + post_images: post.post_images, + post_video: post.post_video, + type: post.type, + files: post.files, + user_id: post.user_id?._id || null, + user_name: post.user_id?.user_name || '-', + user_type: post.user_id?.user_type || '-', + expertise: post.user_id?.expertise || '-', + first_name: post.user_id?.first_name || '-', + last_name: post.user_id?.last_name || '-', + mobile: post.user_id?.mobile || '-', + national_code: post.user_id?.national_code || '-', + createdAt: post.createdAt ? jMoment(post.createdAt).format('jYYYY-jMM-jDD HH:mm') : '-', + } + return res.status(200).json({ post: response }) + } catch (error) { + next(error) + } +} + +const acceptPost = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { id, user_id, status } = req.body + + if (!id || !user_id || !status) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const user = await UserModel.findById(user_id) + const post = await PostModel.findById(id) + + if (!post) { + return res.status(404).json({ + error: true, + message: 'پست مورد نظر یافت نشد' + }) + } + + post.status = status + await post.save() + if (status === 'accept') { + user.last_post = post + await user.save() + + const notification = new NotificationModel({ + user_id: user?._id, + project_post_id: post?._id, + type: 'accept-post', + title: 'انتشار پست', + description: 'پست شما مورد تایید قرار گرفت.' + }) + await notification.save() + } else { + const notification = new NotificationModel({ + user_id: user?._id, + project_post_id: post?._id, + type: 'reject-post', + title: 'رد پست', + description: 'پست شما مورد تایید قرار نگرفت.' + }) + await notification.save() + } + + res.status(201).json({ message: 'پست با موفقیت تایید شد' }) + } catch (error) { + next(error) + } +} + +module.exports = { + acceptPost, getPosts, getPostDetail +} diff --git a/public/modstagram-back/controllers/panel/projects/projectController.js b/public/modstagram-back/controllers/panel/projects/projectController.js new file mode 100644 index 0000000..6ae52a9 --- /dev/null +++ b/public/modstagram-back/controllers/panel/projects/projectController.js @@ -0,0 +1,256 @@ +/* eslint-disable camelcase */ +const ProjectModel = require('../../../models/ProjectModel') +const jMoment = require('moment-jalaali') +const RequestModel = require('../../../models/RequestModel') +const NotificationModel = require('../../../models/NotificationModel') + +const getProjects = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + // eslint-disable-next-line no-unused-vars + const { + page = 1, limit = 10, + startDate, + endDate, + status + } = req.query + // ساخت فیلتر برای استفاده در جستجوی MongoDB + const filter = { + } // افزودن شرط‌های دیگر برای فیلتر + // Date + if (startDate || endDate) { + filter.createdAt = {} + + if (startDate) { + filter.createdAt.$gte = new Date(startDate) // تاریخ شروع + } + + if (endDate) { + filter.createdAt.$lte = new Date(endDate) // تاریخ پایان + } + } + + if (status) { + filter.status = status + } + + // دریافت لیست پروژه‌ها با استفاده از فیلتر و گزینه‌های صفحه‌بندی + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: { createdAt: -1 }, + populate: [ + { path: 'creator_id', select: '_id user_name first_name last_name' }, + { path: 'selected_user', select: '_id user_name first_name last_name' } + ] + } + const projects = await ProjectModel.paginate(filter, options) + const projectsList = projects.docs.map(project => ({ + _id: project._id, + title: project.title, + expertise: project.expertise, + sub_expertise: project.sub_expertise, + offer_time: project.offer_time, + offer_price: project.offer_price, + final_price: project.final_price, + final_time: project.final_time, + createdAt: jMoment(project.createdAt).format('jYYYY-jMM-jDD HH:mm'), + status: project.status, + creator: project.creator_id + ? { + _id: project.creator_id._id, + user_name: project.creator_id.user_name, + first_name: project.creator_id.first_name, + last_name: project.creator_id.last_name + } + : null, + selected_user: project.selected_user + ? { + _id: project.selected_user._id, + user_name: project.selected_user.user_name, + first_name: project.selected_user.first_name, + last_name: project.selected_user.last_name + } + : null + })) + + res.status(200).json({ + projects: projectsList, + totalPages: projects.totalPages, // ارسال تعداد کل صفحات + totalItems: projects.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + next(error) + } +} +const getProjectDetails = async (req, res, next) => { + try { + const { project_id } = req.query + + // بررسی وجود projectId + if (!project_id) { + return res.status(400).send('Project ID is required') + } + + // یافتن پروژه و جمع‌آوری اطلاعات مرتبط با سازنده و کاربر انتخاب شده + const project = await ProjectModel.findById(project_id) + .populate('creator_id', '_id user_name first_name last_name mobile') + .populate('selected_user', '_id user_name first_name last_name mobile') + .lean() + + // بررسی وجود پروژه + if (!project) { + return res.status(404).send('Project not found') + } + + // دریافت لیست درخواست‌های پروژه + const projectRequests = await RequestModel.find({ project: project_id }) + .populate('user', '_id first_name last_name user_name rate profile_image') + .sort({ status: 1 }) + .lean() + + // ساختاردهی پاسخ نهایی + const projectDetails = { + _id: project._id, + title: project.title, + description: project.description, + creator: project.creator_id + ? { + _id: project.creator_id._id, + first_name: project.creator_id.first_name, + last_name: project.creator_id.last_name, + user_name: project.creator_id.user_name, + mobile: project.creator_id.mobile + } + : null, + selected_user: project.selected_user + ? { + _id: project.selected_user._id, + first_name: project.selected_user.first_name, + last_name: project.creator_id.last_name, + user_name: project.selected_user.user_name, + mobile: project.selected_user.mobile + } + : null, + province: project.province, + city: project.city, + createdAt: jMoment(project.createdAt).format('jYYYY-jMM-jDD HH:mm'), + expertise: project.expertise, + sub_expertise: project.sub_expertise, + offer_time: project.offer_time, + offer_price: project.offer_price, + final_price: project.final_price, + final_time: project.final_time, + status: project.status, + reject_reason: project.reject_reason, + requested_users: projectRequests.map(request => ({ + _id: request.user._id, + first_name: request.user.first_name, + last_name: request.user.last_name, + user_name: request.user.user_name, + profile_image: request.user.profile_image, + time: request.time, + price: request.price + })) + } + + res.status(200).json({ project: projectDetails }) + } catch (error) { + next(error) + } +} +const acceptProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { id, user_name } = req.body + + if (!id) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const project = await ProjectModel.findById(id) + + if (!project) { + return res.status(404).json({ + error: true, + message: 'پست مورد نظر یافت نشد' + }) + } + project.acceptedAt = new Date() + project.status = 'accepted' + await project.save() + const notification = new NotificationModel({ + user_id: project?.creator_id, + project_post_id: project?._id, + type: 'accept-project', + title: 'انتشار درخواست', + description: `درخواست شما با عنوان: ${project?.title} منتشر شد ` + }) + await notification.save() + if (project?.public_status === 'private' && project?.created_for_user) { + const notification = new NotificationModel({ + user_id: project?.created_for_user, + project_post_id: project?._id, + type: 'recive-project', + title: 'دعوت به همکاری', + description: `کاربر ${user_name} برای شما پروژه ایجاد کرده است ، برای نمایش جزئیات لمس کنید` + }) + await notification.save() + } + res.status(201).json({ message: 'پروژه با موفقیت تایید شد' }) + } catch (error) { + next(error) + } +} +const rejectProject = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { id, rejectReason } = req.body + + if (!id) { + return res.status(422).json({ + error: true, + message: 'اطلاعات ارسالی اشتباه است' + }) + } + + const project = await ProjectModel.findById(id) + + if (!project) { + return res.status(404).json({ + error: true, + message: 'پست مورد نظر یافت نشد' + }) + } + + project.status = 'rejected' + project.reject_reason = rejectReason + await project.save() + const notification = new NotificationModel({ + user_id: project?.creator_id, + project_post_id: project?._id, + type: 'reject-project', + title: 'رد درخواست', + description: `درخواست شما با عنوان: ${project?.title} رد شد، برای دیدن علت رد، لمس کنید ` + }) + await notification.save() + res.status(201).json({ message: 'پروژه با موفقیت رد شد' }) + } catch (error) { + next(error) + } +} +module.exports = { + getProjects, + getProjectDetails, + acceptProject, + rejectProject +} diff --git a/public/modstagram-back/controllers/panel/projects/projectTypesController.js b/public/modstagram-back/controllers/panel/projects/projectTypesController.js new file mode 100644 index 0000000..5f50f47 --- /dev/null +++ b/public/modstagram-back/controllers/panel/projects/projectTypesController.js @@ -0,0 +1,63 @@ +const TypeAndPriceModel = require('../../../models/TypeAndPriceModel') +const jwt = require('jsonwebtoken') +const UserModel = require('../../../models/UserModel') + +const getProjectTypes = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const userId = decodedToken.id + + const user = await UserModel.findById(userId) + if (!user) { + return res.status(422).json({ + error: true, + message: 'کاربر یافت نشد' + }) + } + // درخواست انواع پروژه از دیتابیس + let projectTypes = await TypeAndPriceModel.find({}, 'name price') + + // بررسی برای مواردی مانند پیدا نشدن انواع پروژه + if (!projectTypes) { + return res.status(404).json({ message: 'انواع پروژه یافت نشد.' }) + } + // اگر کاربر درخواست رایگان روزانه نداشته باشد، نوع پروژه رایگان را حذف کنید + if (user.daily_free_request <= 0) { + projectTypes = projectTypes.filter(projectType => projectType.name !== 'free') + } + // ارسال انواع پروژه به کاربر + res.status(200).json({ projectTypes }) + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error('Error in getProjectTypes:', error) + res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' }) + } +} + +const createProjectTypes = async (req, res, next) => { + try { + const { name, price } = req.body + // بررسی اعتبار ورودی‌ها + if (!name || price == null || price === undefined) { + return res.status(400).json({ message: 'لطفا نام و قیمت پروژه را وارد کنید.' }) + } + + // ایجاد نوع پروژه جدید + const newType = new TypeAndPriceModel({ name, price }) + await newType.save() + + // ارسال پیام موفقیت آمیز به کاربر + res.status(201).json({ message: 'نوع پروژه جدید با موفقیت ایجاد شد.' }) + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error('Error in createProjectTypes:', error) + res.status(500).json({ message: 'خطا در ایجاد نوع پروژه.' }) + } +} + +module.exports = { + getProjectTypes, + createProjectTypes +} diff --git a/public/modstagram-back/controllers/panel/settings/settingsController.js b/public/modstagram-back/controllers/panel/settings/settingsController.js new file mode 100644 index 0000000..b6ee8bc --- /dev/null +++ b/public/modstagram-back/controllers/panel/settings/settingsController.js @@ -0,0 +1,36 @@ +// controllers/settingController.js + +const SettingModel = require('../../../models/SettingsModel') + +// متد برای دریافت تنظیمات بر اساس key +const getSetting = async (req, res, next) => { + try { + const { key } = req.params + const setting = await SettingModel.findOne({ key }) + if (!setting) { + return res.status(404).json({ message: 'تنظیمات مورد نظر یافت نشد' }) + } + res.status(200).json(setting) + } catch (error) { + next(error) + } +} + +// متد برای به‌روزرسانی تنظیمات بر اساس key +const updateSetting = async (req, res, next) => { + try { + const { key } = req.params + const { value } = req.body + // eslint-disable-next-line no-unused-vars + const setting = await SettingModel.findOneAndUpdate( + { key }, + { value }, + { new: true, upsert: true } // اگر وجود نداشت، آن را ایجاد کن + ) + res.status(200).json({ message: 'تنظیمات با موفقیت بروز شد' }) + } catch (error) { + next(error) + } +} + +module.exports = { getSetting, updateSetting } diff --git a/public/modstagram-back/controllers/panel/shops/shopsController.js b/public/modstagram-back/controllers/panel/shops/shopsController.js new file mode 100644 index 0000000..b9bb591 --- /dev/null +++ b/public/modstagram-back/controllers/panel/shops/shopsController.js @@ -0,0 +1,161 @@ +/* eslint-disable camelcase */ +const { default: mongoose } = require('mongoose') +const jMoment = require('moment-jalaali') +const AdvertisingProfileModel = require('../../../models/AdvertisingProfile') +const AdvertisingModel = require('../../../models/AdvertisingModel') + +const getShops = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + // eslint-disable-next-line no-unused-vars + const { page = 1, limit = 10, expertise, most_price, most_requests, age, gender } = req.query + const filter = {} // افزودن شرط‌های دیگر برای فیلتر + + // if (expertise) { + // filter.expertise = expertise + // } + // if (age) { + // filter.age = age + // } + // if (gender) { + // filter.gender = gender + // } + // استفاده از مدل پیجینیت شده برای دریافت نتایج صفحه‌بندی شده + const options = { + page: parseInt(page), // تبدیل صفحه به عدد صحیح + limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح + sort: { createdAt: -1 }, + populate: [ + { path: 'user', select: '_id user_name first_name last_name' } + ] + } + const shops = await AdvertisingProfileModel.paginate(filter, options) + const newShops = shops.docs.map(user => ({ + _id: user._id, + user_name: user?.user?.user_name, + first_name: user?.user?.first_name, + last_name: user?.user?.last_name, + user_id: user?.user?._id, + profile_image: user.profile_image, + category: user.category, + vitrine_name: user.vitrine_name, + province: user.province, + city: user.city, + neighbourhood: user.neighbourhood, + createdAt: jMoment(user.createdAt).format('jYYYY-jMM-jDD HH:mm') + })) + res.status(200).json({ + shops: newShops, + totalPages: shops.totalPages, // ارسال تعداد کل صفحات + totalItems: shops.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + // در صورت بروز خطا، ارسال پیام خطا به کاربر + console.error('Error in getProjectTypes:', error) + res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' }) + } +} +const getShopDetail = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const profile_id = req.query.profile_id + // eslint-disable-next-line no-unused-vars + // دریافت جزئیات فروشگاه با استفاده از profile_id + const shop = await AdvertisingProfileModel.findById(profile_id) + .populate('user', '_id user_name first_name last_name') + .exec() + const userAds = await AdvertisingModel.find({ creator_id: shop?.user }) + // جمع‌آوری اطلاعات از تبلیغات‌ها + let allImages = [] + let allServices = [] + let allFeatures = [] + for (const ad of userAds) { + allImages = allImages.concat(ad.images) + allServices = allServices.concat(ad.services) + allFeatures = allFeatures.concat(ad.features) + } + // حذف آیتم‌های null و تکراری از allFeatures + const uniqueFeatures = [] + const featureTitles = new Set() + for (const feature of allFeatures) { + if (feature && !featureTitles.has(feature.title)) { + uniqueFeatures.push(feature) + featureTitles.add(feature.title) + } + } + if (!shop) { + return res.status(404).json({ message: 'فروشگاه مورد نظر یافت نشد' }) + } + const response = { + _id: shop?._id, + user_name: shop?.user?.user_name, + first_name: shop?.user?.first_name, + last_name: shop?.user?.last_name, + user_id: shop?.user?._id, + profile_image: shop?.profile_image, + category: shop?.category, + vitrine_name: shop?.vitrine_name, + province: shop?.province, + city: shop?.city, + neighbourhood: shop?.neighbourhood, + contactInfo: shop?.contactInfo, + address: shop?.address, + allImages: allImages?.reverse(), + allServices, + allFeatures: uniqueFeatures, + about_us: shop?.about_us + // اطلاعات اضافی که بعداً به شما می‌گویم + } + return res.status(200).json({ shop: response }) + } catch (error) { + next(error) + } +} +const updateShop = async (req, res, next) => { + try { + const shopId = req.query.shopId // دریافت شناسه کاربر از درخواست + + // چک کردن اعتبار شناسه کاربر + if (!mongoose.Types.ObjectId.isValid(shopId)) { + return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }) + } + + // فیلدهایی که می‌خواهید آپدیت شوند را از درخواست دریافت کنید + const updateFields = req.body + + // اجرای آپدیت و بازگشت مقدار آپدیت شده + const updatedUser = await AdvertisingProfileModel.findByIdAndUpdate( + shopId, + updateFields, + { new: true } + ) + + // بررسی آیا کاربر وجود دارد یا نه + if (!updatedUser) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + + // ارسال پاسخ با مقادیر آپدیت شده + res.status(200).json({ message: 'کاربر با موفقیت ویرایش شد', id: updatedUser._id }) + } catch (error) { + const errors = [] + + if (error.code === 11000) { + // Duplicate key error + for (const key in error.keyValue) { + errors.push({ message: `ارور در فیلد ${key}` }) + } + } else { + errors.push({ message: 'خطا در آپدیت کاربر' }) + } + + res.status(500).json({ errors }) + } +} + +module.exports = { + getShops, getShopDetail, updateShop +} diff --git a/public/modstagram-back/controllers/panel/tickets/ticketsController.js b/public/modstagram-back/controllers/panel/tickets/ticketsController.js new file mode 100644 index 0000000..5a71ef2 --- /dev/null +++ b/public/modstagram-back/controllers/panel/tickets/ticketsController.js @@ -0,0 +1,153 @@ +const NotificationModel = require('../../../models/NotificationModel') +const TicketMessageModel = require('../../../models/TicketMessageModel') +const TicketModel = require('../../../models/TicketModel') +const jwt = require('jsonwebtoken') +const jMoment = require('moment-jalaali') + +const getAllTickets = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { + page = 1, limit = 10, + startDate, + endDate, + status + } = req.query // افزودن پارامترهای صفحه‌بندی به درخواست + + const filter = {} // افزودن شرط‌های دیگر برای فیلتر + + // Date + if (startDate || endDate) { + filter.createdAt = {} + + if (startDate) { + filter.createdAt.$gte = new Date(startDate) // تاریخ شروع + } + + if (endDate) { + filter.createdAt.$lte = new Date(endDate) // تاریخ پایان + } + } + + if (status) { + filter.status = status + } + + const options = { + page: parseInt(page, 10) || 1, + limit: parseInt(limit, 10) || 10, + populate: [ + { path: 'user', select: '_id user_name first_name last_name mobile expertise' } + ], + sort: { updatedAt: -1 } + } + const tickets = await TicketModel.paginate(filter, options) + const ticketList = tickets?.docs.map(ticket => { + const jDate = jMoment(ticket.createdAt).format('jYYYY-jMM-jDD HH:mm') + return { + ...ticket._doc, + createdAt: jDate + } + }) + res.json({ + tickets: ticketList, + totalPages: tickets.totalPages, // ارسال تعداد کل صفحات + totalItems: tickets.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }) + } +} +const addAdminMessageToTicket = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + const adminId = decodedToken.id + + const { text, ticketId } = req.body + + const newMessage = new TicketMessageModel({ + text, + senderType: 'Admin', + senderId: adminId, + ticket: ticketId + }) + await newMessage.save() + + const ticket = await TicketModel.findById(ticketId) + if (!ticket) { + return res.status(404).json({ error: 'Ticket not found' }) + } + ticket.status = 'Answered' + ticket.new_message = true + await ticket.save() + const notification = new NotificationModel({ + user_id: ticket?.user, + project_post_id: ticket?._id, + type: 'ticket-message', + title: 'پاسخ پشتیبانی', + description: `پاسخ جدید در تیکت: ${ticket?.title}` + }) + await notification.save() + res.status(201).json(newMessage) + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }) + } +} +// senderId +const getTicketMessages = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const { ticketId } = req.query + const { page = 1, limit = 10 } = req.query + const options = { + page: parseInt(page) || 1, + limit: parseInt(limit) || 10, + populate: [ + { path: 'senderId', select: '_id user_name first_name last_name mobile expertise' } + ], + sort: { createdAt: -1 } + } + const messages = await TicketMessageModel.paginate({ ticket: ticketId }, options) + const messageList = messages?.docs.map(message => { + const jDate = jMoment(message.createdAt).format('jYYYY-jMM-jDD HH:mm') + return { + ...message._doc, + createdAt: jDate + } + }) + res.json({ + messages: messageList.reverse(), + totalPages: messages.totalPages, // ارسال تعداد کل صفحات + totalItems: messages.totalDocs // ارسال تعداد کل آیتم‌ها + }) + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }) + } +} +const closeTicket = async (req, res) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + + const { ticketId } = req.body + if (!ticketId) return res.status(400).send('Ticket ID is required') + + const ticket = await TicketModel.findById(ticketId) + if (!ticket) return res.status(404).send('Ticket not found') + + ticket.status = 'Closed' + await ticket.save() + + res.status(200).json({ message: 'Ticket has been closed successfully' }) + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }) + } +} + +module.exports = { getAllTickets, addAdminMessageToTicket, getTicketMessages, closeTicket } diff --git a/public/modstagram-back/controllers/panel/users/usersController.js b/public/modstagram-back/controllers/panel/users/usersController.js new file mode 100644 index 0000000..f0c2761 --- /dev/null +++ b/public/modstagram-back/controllers/panel/users/usersController.js @@ -0,0 +1,410 @@ +/* eslint-disable no-unused-vars */ +/* eslint-disable camelcase */ +const { default: mongoose } = require('mongoose') +const UserModel = require('../../../models/UserModel') +const jMoment = require('moment-jalaali') +const NotificationModel = require('../../../models/NotificationModel') +const { default: axios } = require('axios') + +const getUsers = async (req, res, next) => { + try { + // بررسی توکن + const token = req.header('Authorization')?.split(' ')[1]; + if (!token) return res.status(401).send('Access Denied'); + + // پارامترهای query + const { + page = 1, + limit = 20, + expertise, + most_price, + most_requests, + age, + gender, + startDate, + endDate, + status, + search + } = req.query; + + const filter = {}; // شرط‌های فیلتر + + // فیلتر تاریخ + if (startDate || endDate) { + filter.createdAt = {}; + if (startDate) filter.createdAt.$gte = new Date(startDate); + if (endDate) filter.createdAt.$lte = new Date(endDate); + } + + // فیلتر وضعیت + if (status) { + filter.is_verified = status; + } + + // فیلتر سرچ + if (search) { + const regex = new RegExp(search, "i"); // i = ignore case + filter.$or = [ + { first_name: regex }, + { last_name: regex }, + { user_name: regex }, + { mobile: regex } + ]; + } + + // فیلترهای دیگر (اختیاری) + if (expertise) filter.expertise = expertise; + if (age) filter.age = age; + if (gender) filter.gender = gender; + + // گزینه‌های صفحه‌بندی + const options = { + page: parseInt(page), + limit: parseInt(limit), + sort: { createdAt: -1 } + }; + + // گرفتن کاربران با paginate + const users = await UserModel.paginate(filter, options); + + // آماده‌سازی خروجی + const newUsers = users.docs.map(user => ({ + _id: user._id, + mobile: user.mobile, + user_name: user.user_name, + first_name: user.first_name, + last_name: user.last_name, + user_type: user.user_type, + is_verified: user.is_verified, + profile_image: user.profile_image, + expertise: user.expertise, + sub_expertise: user.sub_expertise, + gender: user.gender, + national_code: user.national_code, + province: user.province, + city: user.city, + last_online: jMoment(user.last_online).format('jYYYY-jMM-jDD HH:mm'), + createdAt: jMoment(user.createdAt).format('jYYYY-jMM-jDD HH:mm'), + block_status: user.block_status + })); + + res.status(200).json({ + users: newUsers, + totalPages: users.totalPages, + totalItems: users.totalDocs + }); + } catch (error) { + console.error('Error in getUsers:', error); + res.status(500).json({ message: 'خطا در دریافت کاربران.' }); + } +}; + + + +// const getUsers = async (req, res, next) => { +// try { +// const token = req.header('Authorization').split(' ')[1] +// if (!token) return res.status(401).send('Access Denied') + +// // eslint-disable-next-line no-unused-vars +// const { +// page = 1, +// limit = 10, +// expertise, +// most_price, +// most_requests, +// age, +// gender, +// startDate, +// endDate, +// status +// } = req.query +// const filter = {} // افزودن شرط‌های دیگر برای فیلتر + +// // Date +// if (startDate || endDate) { +// filter.createdAt = {} + +// if (startDate) { +// filter.createdAt.$gte = new Date(startDate) // تاریخ شروع +// } + +// if (endDate) { +// filter.createdAt.$lte = new Date(endDate) // تاریخ پایان +// } +// } + +// if (status) { +// filter.is_verified = status +// } + +// // if (expertise) { +// // filter.expertise = expertise +// // } +// // if (age) { +// // filter.age = age +// // } +// // if (gender) { +// // filter.gender = gender +// // } +// // استفاده از مدل پیجینیت شده برای دریافت نتایج صفحه‌بندی شده +// const options = { +// page: parseInt(page), // تبدیل صفحه به عدد صحیح +// limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح +// sort: { createdAt: -1 } +// } +// const users = await UserModel.paginate(filter, options) +// const newUsers = users.docs.map(user => ({ +// _id: user._id, +// mobile: user.mobile, +// user_name: user.user_name, +// first_name: user.first_name, +// last_name: user.last_name, +// user_type: user.user_type, +// is_verified: user.is_verified, +// profile_image: user.profile_image, +// expertise: user.expertise, +// sub_expertise: user.sub_expertise, +// gender: user.gender, +// national_code: user.national_code, +// province: user.province, +// city: user.city, +// last_online: jMoment(user.last_online).format('jYYYY-jMM-jDD HH:mm'), +// createdAt: jMoment(user.createdAt).format('jYYYY-jMM-jDD HH:mm'), +// block_status: user.block_status +// })) +// res.status(200).json({ +// users: newUsers, +// totalPages: users.totalPages, // ارسال تعداد کل صفحات +// totalItems: users.totalDocs // ارسال تعداد کل آیتم‌ها +// }) +// } catch (error) { +// // در صورت بروز خطا، ارسال پیام خطا به کاربر +// console.error('Error in getProjectTypes:', error) +// res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' }) +// } +// } +const getUserDetail = async (req, res, next) => { + try { + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const user_id = req.query.user_id + // eslint-disable-next-line no-unused-vars + + if (!mongoose.Types.ObjectId.isValid(user_id)) { + return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }) + } + const user = await UserModel.findById(user_id) + + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + + const response = { + _id: user?._id, + profile_image: user?.profile_image, + first_name: user?.first_name, + last_name: user?.last_name, + user_name: user?.user_name, + mobile: user?.mobile, + national_code: user?.national_code, + province: user?.province, + city: user?.city, + address: user?.address, + height: user?.height, + weight: user?.weight, + size: user?.size, + birthday: user?.birthday, + show_location: user?.show_location, + cooperation_abroad: user?.cooperation_abroad, + conversation_projects: user?.conversation_projects, + expertise: user?.expertise, + sub_expertise: user?.sub_expertise, + shaba: user?.shaba, + national_card_image: user?.national_card_image, + last_online: jMoment(user?.last_online).format('jYYYY-jMM-jDD HH:mm'), + createdAt: jMoment(user?.createdAt).format('jYYYY-jMM-jDD HH:mm'), + block_status: user?.block_status, + user_level: user?.user_level, + user_type: user?.user_type, + user_score: user?.user_score, + services :user?.services, + is_verified: user?.is_verified, + rate: user?.rate, + bio: user?.bio, + eye_color: user?.eye_color, + hair_color: user?.hair_color, + lat: user?.lat, + lng: user?.lng + } + return res.status(200).json({ user: response }) + } catch (error) { + next(error) + } +} +const updateUser = async (req, res, next) => { + try { + const userId = req.query.userId // دریافت شناسه کاربر از درخواست + + // چک کردن اعتبار شناسه کاربر + if (!mongoose.Types.ObjectId.isValid(userId)) { + return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }) + } + + // فیلدهایی که می‌خواهید آپدیت شوند را از درخواست دریافت کنید + const updateFields = req.body + + // اجرای آپدیت و بازگشت مقدار آپدیت شده + const updatedUser = await UserModel.findByIdAndUpdate( + userId, + updateFields, + { new: true } + ) + + // بررسی آیا کاربر وجود دارد یا نه + if (!updatedUser) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + + // ارسال پاسخ با مقادیر آپدیت شده + res.status(200).json({ message: 'کاربر با موفقیت ویرایش شد', id: updatedUser._id }) + } catch (error) { + const errors = [] + + if (error.code === 11000) { + // Duplicate key error + for (const key in error.keyValue) { + errors.push({ message: `ارور در فیلد ${key}` }) + } + } else { + errors.push({ message: 'خطا در آپدیت کاربر' }) + } + + res.status(500).json({ errors }) + } +} +const verifyUser = async (req, res, next) => { + try { + const userId = req.query.userId // دریافت شناسه کاربر از درخواست + const user = await UserModel.findById(userId) + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + user.is_verified = 'verified'; + user.is_Register = true; + await user.save(); + + + const notification = new NotificationModel({ + user_id: userId, + type: 'verify', + title: 'تایید مدارک', + description: 'مدارک ارسالی شما با موفقیت تایید شد' + }) + await notification.save() + + // Sms + + const userReciver = await UserModel.findById(userId) + + const data = JSON.stringify({ + mobile: userReciver?.mobile, + templateId: '632057', + parameters: [ + { name: 'USERS', value: userReciver?.first_name + ' ' + userReciver?.last_name } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + axios(config) + .then(function (response) { + }) + .catch(function (error) { + console.log(error) + }) + + // End Sms + + // ارسال پاسخ با مقادیر آپدیت شده + res.status(200).json({ message: 'مدارک کاربر با موفقیت تایید شد' }) + } catch (error) { + next(error) + } +} + +const updateUserStatus = async (req, res, next) => { + try { + const { userId, block_status } = req.body; + + + if (!mongoose.Types.ObjectId.isValid(userId)) { + return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' }); + } + + const user = await UserModel.findByIdAndUpdate( + userId, + { block_status }, + { new: true } + ); + + if (!user) return res.status(404).json({ message: 'کاربر یافت نشد' }); + + res.status(200).json({ message: 'وضعیت کاربر با موفقیت تغییر کرد', block_status: user.block_status }); + } catch (error) { + console.error(error); + res.status(500).json({ message: 'خطای سرور' }); + } +}; + +const rejectUser = async (req, res, next) => { + try { + const userId = req.query.userId // دریافت شناسه کاربر از درخواست + const user = await UserModel.findById(userId) + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + user.is_verified = 'rejected' + user.is_Register = false + await user.save() + const notification = new NotificationModel({ + user_id: userId, + type: 'reject-user', + title: 'رد مدارک', + description: 'مدارک ارسالی شما رد شد، برای اطلاعات بیشتر از بخش تیکت به پشتیبانی پیام دهید.' + }) + await notification.save() + + // ارسال پاسخ با مقادیر آپدیت شده + res.status(200).json({ message: 'مدارک کاربر با موفقیت رد شد' }) + } catch (error) { + next(error) + } +} +const changePass = async (req, res, next) => { + try { + const { userId, password } = req.body; + const user = await UserModel.findById(userId) + if (!user) { + return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' }) + } + user.password = password + await user.save() + + // ارسال پاسخ با مقادیر آپدیت شده + res.status(200).json({ message: 'رمز عبور با موفقیت تغییر کرد' }); + } catch (error) { + next(error) + } +} +module.exports = { + getUsers, getUserDetail, updateUser, verifyUser, rejectUser, updateUserStatus, changePass +} diff --git a/public/modstagram-back/controllers/panel/version/versionController.js b/public/modstagram-back/controllers/panel/version/versionController.js new file mode 100644 index 0000000..fca01d6 --- /dev/null +++ b/public/modstagram-back/controllers/panel/version/versionController.js @@ -0,0 +1,37 @@ +const VersionModel = require('../../../models/VersionModel') + +// Endpoint برای دریافت نسخه فعلی +const getVersion = async (req, res, next) => { + try { + const currentVersion = await VersionModel.findOne().sort({ _id: -1 }).exec() + if (!currentVersion) { + return res.status(200).json({ message: 'نسخه‌ای پیدا نشد' }) + } + res.json(currentVersion) + } catch (error) { + res.status(500).json({ message: 'خطای سرور', error }) + } +} +// متد برای ایجاد یا ویرایش نسخه +const upsertVersion = async (req, res, next) => { + try { + const { version, mandatory, releaseNotes, updateUrls } = req.body + + if (!version || !Array.isArray(updateUrls) || updateUrls.length === 0) { + return res.status(400).json({ message: 'اطلاعات ناقص است' }) + } + + // پیدا کردن نسخه‌ای که مشابه باشد و ویرایش یا ایجاد + const updatedVersion = await VersionModel.findOneAndUpdate( + { version }, // شرط برای پیدا کردن نسخه با همین شماره + { mandatory, releaseNotes, updateUrls }, // به‌روزرسانی مقادیر + { new: true, upsert: true } // ایجاد نسخه جدید اگر وجود ندارد + ) + + res.status(200).json({ message: 'نسخه به‌روزرسانی شد', version: updatedVersion }) + } catch (error) { + res.status(500).json({ message: 'خطای سرور', error }) + } +} + +module.exports = { getVersion, upsertVersion } diff --git a/public/modstagram-back/helpers/chatHelpers.js b/public/modstagram-back/helpers/chatHelpers.js new file mode 100644 index 0000000..a22af9f --- /dev/null +++ b/public/modstagram-back/helpers/chatHelpers.js @@ -0,0 +1,72 @@ +const moment = require('moment-jalaali') +const MessageModel = require('../models/MessageModel') +const UserModel = require('../models/UserModel') + +function formatTimeOnly(date) { + return moment(date).locale('fa').format('HH:mm:ss') +} + +async function enrichMessage(message) { + const doc = message._doc ? { ...message._doc } : { ...message } + let replyTo = null + + if (doc.replyToId) { + const parent = await MessageModel.findById(doc.replyToId).lean() + if (parent) { + const parentUser = + String(parent.senderId) === String(doc.senderId) + ? await UserModel.findById(doc.senderId).select('first_name last_name user_name').lean() + : await UserModel.findById(parent.senderId).select('first_name last_name user_name').lean() + replyTo = { + _id: parent._id, + content: (parent.content || 'پیام').slice(0, 200), + senderName: parentUser + ? `${parentUser.first_name || ''} ${parentUser.last_name || ''}`.trim() || parentUser.user_name + : 'کاربر' + } + } + } + + return { + ...doc, + createdAt: formatTimeOnly(doc.createdAt), + replyTo, + forwardedFrom: doc.forwardedFrom || undefined + } +} + +function emitChatEvents(io, message, senderId, receiverId) { + const payload = message + const roomA = `chat:${senderId}:${receiverId}` + const roomB = `chat:${receiverId}:${senderId}` + io.to(roomA).to(roomB).emit('newMessage', payload) + io.to(`user:${senderId}`).to(`user:${receiverId}`).emit('chatListUpdate', { + senderId, + receiverId, + message: payload + }) +} + +function parseForwardedContent(content) { + if (!content) return { body: '', forwardedFrom: null } + try { + const line = content.split('\n')[0] + const j = JSON.parse(line) + if (j.forwardedFrom) { + return { + forwardedFrom: j.forwardedFrom, + body: content.replace(/^\{.*\}\n?/, '').trim() + } + } + } catch (_) { + /* not json */ + } + return { body: content, forwardedFrom: null } +} + +module.exports = { + formatTimeOnly, + enrichMessage, + emitChatEvents, + parseForwardedContent +} diff --git a/public/modstagram-back/index.js b/public/modstagram-back/index.js new file mode 100644 index 0000000..67ae759 --- /dev/null +++ b/public/modstagram-back/index.js @@ -0,0 +1,357 @@ +const express = require('express'); +const app = express(); +const path = require('path'); +const http = require('http').createServer(app); +const cors = require('cors'); +const moment = require('moment-jalaali'); +const MessageModel = require('./models/MessageModel'); +const fs = require('fs-extra'); +const cron = require('node-cron'); +const UserModel = require('./models/UserModel'); +const blockCheck = require('./middlewares/blockCheck'); +const rateLimit = require('express-rate-limit'); +const { default: axios } = require('axios'); + +const allowedOrigins = [ + 'http://localhost:3000', + 'http://localhost:3001', // اضافه شد — مهم برای توسعه فرانت + 'http://localhost:3002', + 'http://localhost:3003', + 'http://localhost', + 'https://modstagram.com', + 'https://www.modstagram.com', + 'https://api.modstagram.com', + 'https://panel.modstagram.com', + 'https://www.panel.modstagram.com', + 'https://panel.modstagram.ir', + 'https://www.panel.modstagram.ir', + 'ionic://localhost', + 'capacitor://localhost', + // IPهای محلی (برای تست در شبکه داخلی) + /^http:\/\/192\.168\.\d{1,3}\.\d{1,3}:\d+$/, + /^http:\/\/10\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$/, +]; + +app.use(cors({ + origin: (origin, callback) => { + // در محیط توسعه، همه originها مجاز باشن + if (process.env.NODE_ENV !== 'production') { + return callback(null, true); + } + + // اگر origin وجود نداشته باشه (مثل درخواست از موبایل یا Postman) اجازه بده + if (!origin) { + return callback(null, true); + } + + // چک لیست یا RegExp + const isAllowed = allowedOrigins.some(item => { + if (typeof item === 'string') return item === origin; + if (item instanceof RegExp) return item.test(origin); + return false; + }); + + if (isAllowed) { + callback(null, true); + } else { + callback(new Error('Not allowed by CORS')); + } + }, + methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-no-toast'], + credentials: true, + optionsSuccessStatus: 200 // برای مرورگرهای قدیمی +})); + +// Socket.IO CORS +const io = require('socket.io')(http, { + cors: { + origin: (origin, callback) => { + if (process.env.NODE_ENV !== 'production') { + return callback(null, true); + } + + if (!origin) { + return callback(null, true); + } + + const isAllowed = allowedOrigins.some(item => { + if (typeof item === 'string') return item === origin; + if (item instanceof RegExp) return item.test(origin); + return false; + }); + + if (isAllowed) { + callback(null, true); + } else { + callback(new Error('Not allowed by CORS')); + } + }, + methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'], + credentials: true + } +}); + +// افزایش limit برای Base64 (1000mb کافیه) +app.use(express.json({ limit: '1000mb' })); +app.use(express.urlencoded({ limit: '1000mb', extended: true })); + +app.use('/storage', express.static(path.join(__dirname, 'storage'))); +app.use('/storage/profiles', express.static(path.join(__dirname, '../storage/profiles'))); +app.use('/storage/carts', express.static(path.join(__dirname, '../storage/carts'))); +app.use('/storage/posts', express.static(path.join(__dirname, '../storage/posts'))); +app.use('/storage/messages', express.static(path.join(__dirname, '../storage/messages'))); +app.use('/storage/tickets', express.static(path.join(__dirname, '../storage/tickets'))); +app.use('/storage/advertising', express.static(path.join(__dirname, '../storage/advertising'))); +app.use('/storage/services', express.static(path.join(__dirname, '../storage/services'))); + +require('./boot'); + +// غیرفعال کردن پارس‌کننده‌های بدنه برای روت‌های آپلود فایل +app.use((req, res, next) => { + if (req.path === '/api/v1/posts/create' && req.method === 'POST') { + console.log('DEBUG: Skipping body parsers for /api/v1/posts/create'); + return next(); + } + express.json()(req, res, next); +}); +app.use((req, res, next) => { + if (req.path === '/api/v1/posts/create' && req.method === 'POST') { + return next(); + } + express.urlencoded({ extended: true })(req, res, next); +}); + +require('./middlewares')(app); + +const limiter = rateLimit({ + windowMs: 3 * 60 * 1000, + max: 3000, + standardHeaders: true, + legacyHeaders: false, + message: 'تعداد درخواست‌های شما بیشتر از حد مجاز است، لطفاً بعداً دوباره تلاش کنید.', + handler: (req, res) => { + const retryAfter = Math.ceil((req.rateLimit.resetTime - Date.now()) / 1000); + res.set('Retry-After', retryAfter); + res.status(429).json({ + error: `شما بیش از حد مجاز درخواست ارسال کرده‌اید. لطفاً بعد از ${retryAfter} ثانیه دوباره تلاش کنید.` + }); + } +}); +app.use(limiter); +app.set('trust proxy', 'loopback'); + +require('./routes')(app); + +const { enrichMessage, emitChatEvents, parseForwardedContent } = require('./helpers/chatHelpers') + +app.get('/api/v1/chat', async (req, res) => { + try { + const { senderId, receiverId, limit, page } = req.query + const pageNumber = parseInt(page) || 1 + const limitPerPage = parseInt(limit) || 40 + + const filter = { + $or: [ + { senderId, receiverId }, + { senderId: receiverId, receiverId: senderId } + ] + } + + const totalMessagesCount = await MessageModel.countDocuments(filter) + const totalPages = Math.ceil(totalMessagesCount / limitPerPage) || 1 + const skip = (pageNumber - 1) * limitPerPage + + const messages = await MessageModel.find(filter) + .sort({ createdAt: -1 }) + .skip(skip) + .limit(limitPerPage) + + await MessageModel.updateMany( + { _id: { $in: messages.map((m) => m._id) }, receiverId: senderId }, + { $set: { readStatus: 1 } } + ) + + const enriched = await Promise.all(messages.map((m) => enrichMessage(m))) + res.json({ messages: enriched.reverse(), totalPages }) + } catch (error) { + console.error('Error fetching messages:', error) + res.status(500).json({ error: 'Server error' }) + } +}) + +app.post('/api/v1/chat', [blockCheck], async (req, res) => { + try { + const { senderId, receiverId, content, replyToId, forwardedFrom: fwdBody } = req.body + const { body, forwardedFrom: fwdParsed } = parseForwardedContent(content) + + const payload = { + senderId, + receiverId, + content: body || content, + replyToId: replyToId || undefined, + forwardedFrom: fwdBody || fwdParsed || undefined + } + + const newMessage = new MessageModel(payload) + await newMessage.save() + const formatted = await enrichMessage(newMessage) + + res.status(201).json({ data: formatted }) + emitChatEvents(io, formatted, senderId, receiverId) + } catch (error) { + console.error('Error sending message:', error) + res.status(500).json({ error: 'Server error' }) + } +}) +app.get('/api/v1/chat/read', async (req, res) => { + try { + const { senderId, receiverId } = req.query // شناسه فرستنده و گیرنده از درخواست دریافت شود + // پیدا کردن تمام پیام‌هایی که کاربر دوم مشاهده کرده است و کاربر اول آنها را ارسال کرده است + const messages = await MessageModel.find( + { senderId: receiverId, receiverId: senderId } // برای مواقعی که شناسه‌ها معکوس باشند + ) + // به روزرسانی وضعیت خوانده شده یا نشده بودن پیام‌ها به "خوانده شده" + await MessageModel.updateMany({ _id: { $in: messages.map(message => message._id) } }, { $set: { readStatus: 1 } }) + res.status(200).json({ message: 'Message read status updated successfully' }) + } catch (error) { + console.error('Error updating message read status:', error) + res.status(500).json({ error: 'Server error' }) + } +}) + +app.post("/api/v1/notification/send-sms", async (req, res) => { + const { receiverId, message } = req.body; + const user = await UserModel.findById(receiverId); + if (!user || !user.mobile) return res.status(404).json({ error: "User not found" }); + console.log("3"); + + const mobile = user.mobile + const user_name = user.user_name + const data = JSON.stringify({ + mobile, + templateId: '876533', + parameters: [ + { name: 'USER', value: user_name } + ] + }) + + const config = { + method: 'post', + url: 'https://api.sms.ir/v1/send/verify', + headers: { + 'Content-Type': 'application/json', + Accept: 'text/plain', + 'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt' + }, + data + } + + axios(config) + .then(function (response) { + console.log(response); + + }) + .catch(function (error) { + console.log(error) + }) + + res.status(200).json({ success: true }); +}); + +app.post('/api/v1/chat/file', [blockCheck], async (req, res) => { + try { + const { senderId, receiverId, content, replyToId, fileType } = req.body + const { file } = req.files + let fileUrl = null + if (file) { + const uploadDir = path.join(__dirname, '../storage/messages') + if (!fs.existsSync(uploadDir)) { + fs.mkdirSync(uploadDir, { recursive: true }) + } + const uniqueFileName = `${Date.now()}-${file.name}` + const filePath = path.join(uploadDir, uniqueFileName) + await fs.move(file.path, filePath) + fileUrl = `/messages/${uniqueFileName}` + } + + const newMessage = new MessageModel({ + senderId, + receiverId, + content: content || '', + file: fileUrl, + fileType: fileType || undefined, + replyToId: replyToId || undefined + }) + await newMessage.save() + const formatted = await enrichMessage(newMessage) + + res.status(201).json({ data: formatted }) + emitChatEvents(io, formatted, senderId, receiverId) + } catch (error) { + console.error('Error sending message:', error) + res.status(500).json({ error: 'Server error' }) + } +}) +// Errors +require('./middlewares/exception')(app) +require('./middlewares/404')(app) +io.on('connection', (socket) => { + socket.on('joinUser', ({ userId }) => { + if (userId) socket.join(`user:${userId}`) + }) + + socket.on('joinChat', ({ userId, receiverId }) => { + if (userId && receiverId) { + socket.join(`chat:${userId}:${receiverId}`) + socket.join(`chat:${receiverId}:${userId}`) + } + }) + + socket.on('typing', ({ senderId, receiverId }) => { + io.to(`chat:${receiverId}:${senderId}`).emit('userTyping', { userId: senderId }) + }) + + socket.on('stopTyping', ({ senderId, receiverId }) => { + io.to(`chat:${receiverId}:${senderId}`).emit('userStoppedTyping', { userId: senderId }) + }) + + socket.on('messageSeen', async ({ messageId, senderId, receiverId }) => { + try { + if (messageId) { + await MessageModel.findByIdAndUpdate(messageId, { readStatus: 1 }) + io.to(`chat:${receiverId}:${senderId}`).emit('messageStatusUpdate', { + messageId, + status: 'seen' + }) + } + } catch (e) { + console.error('messageSeen error', e) + } + }) +}) + +// Free Project +require('./services/AdvertisingCron') +require('./services/ProjectCron') +cron.schedule('0 0 1 * *', async () => { + try { + await UserModel.updateMany({}, { + daily_free_request: 1, + last_free_request_date: new Date(), + monthly_free_offer: 1, + last_free_offer_date: new Date() + }) + console.log('Monthly free requests reset for all users.') + } catch (error) { + console.error('Error resetting daily free requests:', error) + } +}, { + scheduled: true, + timezone: 'Asia/Tehran' +}) +module.exports = (port) => { + http.listen(port, () => { + console.log(`HTTP server is running on port ${port}`) + }) +} diff --git a/public/modstagram-back/liara.json b/public/modstagram-back/liara.json new file mode 100644 index 0000000..110cccc --- /dev/null +++ b/public/modstagram-back/liara.json @@ -0,0 +1,3 @@ +{ + "disks": [{ "name": "public", "mountTo": "/storage" }] +} diff --git a/public/modstagram-back/logs/sms-irs/13-03-2024.log b/public/modstagram-back/logs/sms-irs/13-03-2024.log new file mode 100644 index 0000000..16b1f43 --- /dev/null +++ b/public/modstagram-back/logs/sms-irs/13-03-2024.log @@ -0,0 +1,18 @@ +[Wed Mar 13 00:31:27 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3NjUHdHNE5ma0hGdHpQV040MkV0OUx0M285SkdBcGp6OFA5SGpoNHZHUzFEajkwc0ZWQWRWSlNBNFlOMWxxOC9k","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 00:31:27 2024] [VerificationCode] {"VerificationCodeId":634458365,"IsSuccessful":true,"Message":"your verification code is sent"} +[Wed Mar 13 00:34:14 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3M0WTRVeG9SeVNtN0xnMWUzQWo4WG1Oam9mNUw2SkJPV04rMGVOMUJ6Njhpb1RXMTl2LzFEdGRESXhZazBwaHBk","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 00:34:15 2024] [VerificationCode] {"VerificationCodeId":634459857,"IsSuccessful":true,"Message":"your verification code is sent"} +[Wed Mar 13 00:34:48 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3NGN0NVV3V1K01VRTg3TGY1by9PcmtlSVpWaFpBa0l4RXNCOERHMzIxMDRkL1RYbWRhOXc5ZmovT0lFV0FDamJs","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 00:34:48 2024] [VerificationCode] {"VerificationCodeId":634460165,"IsSuccessful":true,"Message":"your verification code is sent"} +[Wed Mar 13 00:34:57 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3NyNmxiRjUwVlF6UUlkSStnOWpOc0lLSyt5VHJjSjFRa0xsTkk0dFB2L3VSaE1PTDdQREY4WGlzcUFQeE01QWRP","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 00:34:57 2024] [VerificationCode] {"VerificationCodeId":634460241,"IsSuccessful":true,"Message":"your verification code is sent"} +[Wed Mar 13 00:39:39 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3N6MHErTmJEVzMydjZRcVJQaHNLb0R3MzJKcWk5bGJYNTh5UzFmSEpSSUY0b0Q4MFppdDRoeFlxWTZZSEQrL1hL","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 00:39:39 2024] [VerificationCode] {"VerificationCodeId":634462768,"IsSuccessful":true,"Message":"your verification code is sent"} +[Wed Mar 13 00:40:18 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3NLRlVYejdBcTJxMGl6dXJVSTRsQkNiOGh2M241WTZrSGI3Z0JCY3kxeFZvUzVCTnRkdmVWalFzd25KQzIzV21I","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 00:40:18 2024] [VerificationCode] {"VerificationCodeId":634463121,"IsSuccessful":true,"Message":"your verification code is sent"} +[Wed Mar 13 00:41:38 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3NOMUs3ZVN3eDU0OVBZdXR1VU1Yd3dhS2lyWmMrWkpjTGpUVVkzWDQ4ZU10VDBTWnFZc0gwYlVSZHArS1FBU2ZL","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 00:41:38 2024] [VerificationCode] {"VerificationCodeId":634463845,"IsSuccessful":true,"Message":"your verification code is sent"} +[Wed Mar 13 01:11:21 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3M4em1oSG05eU9XbVlna0U1TDRjRWdlRi8zTE10YnAzYVZia0hRTmQ3bWV4cEUyUUl4TCtPMncvWStrNi9TSjNt","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 01:11:21 2024] [VerificationCode] {"VerificationCodeId":634470192,"IsSuccessful":true,"Message":"your verification code is sent"} +[Wed Mar 13 02:55:34 2024] [Token] {"TokenKey":"OVlma3FmZmJOTjNoY1A3bmxRbE5odHBHTTNZbGpjcGxvcVVJTmZIMDFHdjkvWDNYaG55WlB0cXNpaWRmclVCeHlXNFVrd2xxZThZQktIVEdGak9Xd29QTGNhMWtpYXlWUmwwNXcvZUdxQjhmbHFyenpPNVlDVk9ZbGZsUmplQ3MwSFZidjNtY0p1T3RwQVFlbkxJdjFHZ0xUaFpqZW9CdllCR21oNFNyaXRUczFaVUVSemZ3Rzk0TW0zRG50Q3VU","IsSuccessful":true,"Message":" درخواست Token با موفقیت انجام شد"} +[Wed Mar 13 02:55:34 2024] [VerificationCode] {"VerificationCodeId":634481796,"IsSuccessful":true,"Message":"your verification code is sent"} diff --git a/public/modstagram-back/middlewares/404.js b/public/modstagram-back/middlewares/404.js new file mode 100644 index 0000000..fb30b71 --- /dev/null +++ b/public/modstagram-back/middlewares/404.js @@ -0,0 +1,9 @@ +module.exports = (app) => { + app.use((req, res, next) => { + res.status(404).send({ + code: 'Not Found', + status: 404, + message: 'requested resource could not be found!' + }) + }) +} diff --git a/public/modstagram-back/middlewares/adminAuth.js b/public/modstagram-back/middlewares/adminAuth.js new file mode 100644 index 0000000..060d854 --- /dev/null +++ b/public/modstagram-back/middlewares/adminAuth.js @@ -0,0 +1,55 @@ +const AdminModel = require('../models/AdminModel') +const jwt = require('jsonwebtoken') + +module.exports = async (req, res, next) => { + if (!('authorization' in req.headers)) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'you are not authorized!' + }) + } + + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + let decodedToken + try { + decodedToken = jwt.verify(token, process.env.APP_SECRET) + } catch (err) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'Your token is not valid!', + error: err.message + }) + } + if (!decodedToken) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'Your token is not valid!' + }) + } + try { + // پیدا کردن کاربر با استفاده از اطلاعات موجود در توکن + const admin = await AdminModel.findOne({ _id: decodedToken.id }) + if (!admin) { + return res.status(403).send({ + status: 'error', + code: 403, + message: 'Access denied!' + }) + } + + // ادامه مسیر در صورتی که کاربر ادمین باشد + req.admin = admin + next() + } catch (error) { + return res.status(500).send({ + status: 'error', + code: 500, + message: 'Internal Server Error', + error: error.message + }) + } +} diff --git a/public/modstagram-back/middlewares/auth.js b/public/modstagram-back/middlewares/auth.js new file mode 100644 index 0000000..d97a1cd --- /dev/null +++ b/public/modstagram-back/middlewares/auth.js @@ -0,0 +1,21 @@ +const TokenService = require('../services/TokenService') +module.exports = (req, res, next) => { + console.log(1); + if (!('authorization' in req.headers)) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'you are not authorized!' + }) + } + const [, tokenValue] = req.headers.authorization.split(' ') + const token = TokenService.verify(tokenValue) + if (!token) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'your token is not valid!' + }) + } + next() +} diff --git a/public/modstagram-back/middlewares/blockCheck.js b/public/modstagram-back/middlewares/blockCheck.js new file mode 100644 index 0000000..7af2097 --- /dev/null +++ b/public/modstagram-back/middlewares/blockCheck.js @@ -0,0 +1,47 @@ +const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر +const jwt = require('jsonwebtoken') + +module.exports = async (req, res, next) => { + console.log(2); + try { + if (!('authorization' in req.headers)) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'You are not authorized!' + }) + } + + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + + if (!decodedToken) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'Your token is not valid!' + }) + } + + const user = await UserModel.findById(decodedToken.id) + if (user.block_status === true) { + return res.status(403).send({ + status: 'error', + code: 403, + message: 'حساب کاربری شما مسدود شده است، برای اطلاعات بیشتر با پشتیبانی تماس بگیرید!', + type: 'block' + }) + } + + req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود. + next() + } catch (error) { + console.error('Error in blockCheck middleware:', error) + res.status(500).send({ + status: 'error', + code: 500, + message: 'Server error' + }) + } +} diff --git a/public/modstagram-back/middlewares/exception.js b/public/modstagram-back/middlewares/exception.js new file mode 100644 index 0000000..1d7ddff --- /dev/null +++ b/public/modstagram-back/middlewares/exception.js @@ -0,0 +1,11 @@ +module.exports = (app) => { + app.use((error, req, res, next) => { + const status = error.status || 500 + res.status(500).send({ + code: 'Eception', + status, + en_message: error.message, + message: 'خطایی در عملیات مورد نظر رخ داده است.' + }) + }) +} diff --git a/public/modstagram-back/middlewares/index.js b/public/modstagram-back/middlewares/index.js new file mode 100644 index 0000000..1192668 --- /dev/null +++ b/public/modstagram-back/middlewares/index.js @@ -0,0 +1,17 @@ +const bodyParser = require('body-parser') +const cors = require('cors') +const formData = require('express-form-data') +const session = require('express-session') +const lastOnline = require('./lastOnline') +module.exports = (app) => { + app.use(cors()) // develop + app.use(formData.parse()) + app.use(bodyParser.json()) + app.use(bodyParser.urlencoded({ extended: true })) + app.use(session({ + secret: 'your_secret_key', // کلید مخفی برای امنیت جلسات + resave: false, + saveUninitialized: false + })) + app.use(lastOnline) +} diff --git a/public/modstagram-back/middlewares/isHalfRegister.js b/public/modstagram-back/middlewares/isHalfRegister.js new file mode 100644 index 0000000..4285c46 --- /dev/null +++ b/public/modstagram-back/middlewares/isHalfRegister.js @@ -0,0 +1,53 @@ +const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر +const jwt = require('jsonwebtoken') + +module.exports = async (req, res, next) => { + console.log(3); + try { + console.log(31); + if (!('authorization' in req.headers)) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'You are not authorized!' + }) + } + console.log(32); + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + + if (!decodedToken) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'Your token is not valid!' + }) + } + console.log(33); + const user = await UserModel.findById(decodedToken.id) + if (!user.user_name || + !user.first_name || + !user.last_name || + !user.user_type || + !user.password) { + return res.status(403).send({ + status: 'error', + code: 403, + message: 'لطفا از بخش تنظیمات، ثبت نام خود را کامل کنید', + type: 'not_register' + }) + } + console.log(34); + req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود. + next() + } catch (error) { + console.log(35); + console.error('not_register middleware:', error) + res.status(500).send({ + status: 'error', + code: 500, + message: 'Server error' + }) + } +} diff --git a/public/modstagram-back/middlewares/isRegister.js b/public/modstagram-back/middlewares/isRegister.js new file mode 100644 index 0000000..1f97f96 --- /dev/null +++ b/public/modstagram-back/middlewares/isRegister.js @@ -0,0 +1,50 @@ +const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر +const jwt = require('jsonwebtoken') + +module.exports = async (req, res, next) => { + try { + if (!('authorization' in req.headers)) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'You are not authorized!' + }) + } + + const token = req.header('Authorization').split(' ')[1] + if (!token) return res.status(401).send('Access Denied') + const decodedToken = jwt.verify(token, process.env.APP_SECRET) + + if (!decodedToken) { + return res.status(401).send({ + status: 'error', + code: 401, + message: 'Your token is not valid!' + }) + } + + const user = await UserModel.findById(decodedToken.id) + if (!user.user_name || + !user.first_name || + !user.last_name || + !user.password) { + return res.status(403).send({ + status: 'error', + code: 403, + message: 'لطفا از بخش تنظیمات، ثبت نام خود را کامل کنید', + type: 'not_register' + }) + } + + + req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود. + next() + } catch (error) { + console.error('not_register middleware:', error) + res.status(500).send({ + status: 'error', + code: 500, + message: 'Server error' + }) + } +} diff --git a/public/modstagram-back/middlewares/lastOnline.js b/public/modstagram-back/middlewares/lastOnline.js new file mode 100644 index 0000000..716a901 --- /dev/null +++ b/public/modstagram-back/middlewares/lastOnline.js @@ -0,0 +1,21 @@ +const jwt = require('jsonwebtoken') +const UserModel = require('../models/UserModel') + +module.exports = async (req, res, next) => { + if (req.header && req.header('Authorization')) { + const token = await req.header('Authorization').split(' ')[1] + const decodedToken = await jwt.verify(token, process.env.APP_SECRET) + const user = await UserModel.findById(decodedToken.id) + if (user) { + try { + user.last_online = new Date() + await user.save() // ذخیره تغییرات در دیتابیس + } catch (error) { + // بررسی و پردازش خطاها + console.error('Error updating last online time:', error) + } + } + } + + next() +} diff --git a/public/modstagram-back/middlewares/upload.js b/public/modstagram-back/middlewares/upload.js new file mode 100644 index 0000000..2229afb --- /dev/null +++ b/public/modstagram-back/middlewares/upload.js @@ -0,0 +1,24 @@ +const multer = require('multer'); +const path = require('path'); +const fs = require('fs-extra'); + +const uploadDir = path.join(__dirname, '../storage/posts'); +fs.ensureDirSync(uploadDir); // مطمئن میشه مسیر وجود داره + +const storage = multer.diskStorage({ + destination: (req, file, cb) => cb(null, uploadDir), + filename: (req, file, cb) => { + const ext = path.extname(file.originalname); + const name = file.originalname.replace(ext, '').replace(/\s/g, '_'); + cb(null, `${Date.now()}-${name}${ext}`); + } +}); + +const fileFilter = (req, file, cb) => { + if (!file.mimetype.startsWith('image/')) return cb(new Error('فقط تصاویر مجاز است')); + cb(null, true); +}; + +const upload = multer({ storage, fileFilter, limits: { files: 10 } }); // حداکثر ۱۰ فایل + +module.exports = upload; diff --git a/public/modstagram-back/models/AcademyCategoryModel.js b/public/modstagram-back/models/AcademyCategoryModel.js new file mode 100644 index 0000000..be50bf0 --- /dev/null +++ b/public/modstagram-back/models/AcademyCategoryModel.js @@ -0,0 +1,190 @@ +const mongoose = require('mongoose'); +const mongoosePaginate = require('mongoose-paginate-v2'); +const timestamp = require('mongoose-timestamp'); + +const AcademyCategorySchema = new mongoose.Schema({ + title: { + type: String, + required: [true, 'عنوان دسته‌بندی الزامی است'], + trim: true, + minLength: [2, 'عنوان باید حداقل ۲ کاراکتر باشد'], + maxLength: [100, 'عنوان باید حداکثر ۱۰۰ کاراکتر باشد'], + unique: true, + index: true, + }, + slug: { + type: String, + required: true, + unique: true, + lowercase: true, + trim: true, + index: true, + }, + description: { + type: String, + required: false, + trim: true, + maxLength: 500, + default: null, + }, + icon: { + type: String, + required: false, + default: null, + }, + color: { + type: String, + required: false, + default: '#3B82F6', + match: /^#[0-9A-F]{6}$/i, + }, + parent: { + type: mongoose.Schema.Types.ObjectId, + ref: 'AcademyCategory', + required: false, + default: null, + index: true, + }, + level: { + type: Number, + required: true, + default: 0, + min: 0, + max: 3, + }, + order: { + type: Number, + required: true, + default: 0, + index: true, + }, + image: { + type: String, + required: false, + default: null, + }, + course_count: { + type: Number, + required: true, + default: 0, + min: 0, + }, + status: { + type: String, + enum: ['active', 'inactive', 'deleted'], + required: true, + default: 'active', + index: true, + }, + is_featured: { + type: Boolean, + required: true, + default: false, + index: true, + }, + seo_title: { + type: String, + required: false, + trim: true, + maxLength: 70, + }, + seo_description: { + type: String, + required: false, + trim: true, + maxLength: 160, + }, + created_by: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true, + }, + updated_by: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: false, + }, +}, { + toJSON: { virtuals: true }, + toObject: { virtuals: true } +}); + +// Virtual برای زیردسته‌ها +AcademyCategorySchema.virtual('children', { + ref: 'AcademyCategory', + localField: '_id', + foreignField: 'parent', + justOne: false, + options: { sort: { order: 1, title: 1 } } +}); + +// Virtual برای دوره‌های این دسته +AcademyCategorySchema.virtual('courses', { + ref: 'Course', + localField: '_id', + foreignField: 'category_id', + justOne: false, + match: { status: 'accept' } +}); + +// Middleware: قبل از save +AcademyCategorySchema.pre('save', async function(next) { + if (this.isModified('title') || this.isNew) { + // تولید slug + this.slug = this.title + .replace(/[^\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C\uFB8E\u0698a-zA-Z0-9\s]/g, '') + .trim() + .replace(/\s+/g, '-') + .toLowerCase(); + + // اگه parent داره، سطح رو محاسبه کن + if (this.parent) { + const parent = await this.constructor.findById(this.parent); + if (parent) { + this.level = parent.level + 1; + } + } else { + this.level = 0; + } + } + next(); +}); + +// استاتیک متدها +AcademyCategorySchema.statics = { + // دریافت درخت دسته‌بندی‌ها + async getTree() { + const categories = await this.find({ status: 'active', parent: null }) + .sort({ order: 1, title: 1 }) + .populate({ + path: 'children', + match: { status: 'active' }, + options: { sort: { order: 1, title: 1 } }, + populate: { + path: 'children', + match: { status: 'active' }, + options: { sort: { order: 1, title: 1 } } + } + }); + return categories; + }, + + // افزایش تعداد دوره‌ها + async incrementCourseCount(categoryId, increment = 1) { + return this.findByIdAndUpdate(categoryId, { + $inc: { course_count: increment } + }); + }, + + // دریافت دسته‌بندی با اسلاگ + async getBySlug(slug) { + return this.findOne({ slug, status: 'active' }) + .populate('children') + .populate('parent'); + } +}; + +AcademyCategorySchema.plugin(timestamp); +AcademyCategorySchema.plugin(mongoosePaginate); + +module.exports = mongoose.model('AcademyCategory', AcademyCategorySchema); \ No newline at end of file diff --git a/public/modstagram-back/models/AcademyContentModel.js b/public/modstagram-back/models/AcademyContentModel.js new file mode 100644 index 0000000..092990f --- /dev/null +++ b/public/modstagram-back/models/AcademyContentModel.js @@ -0,0 +1,71 @@ +const mongoose = require('mongoose'); +const timestamp = require('mongoose-timestamp'); +const mongoosePaginate = require('mongoose-paginate-v2'); + +const modelSchema = new mongoose.Schema({ + course_images: { + type: [String], // آرایه‌ای از مسیرهای تصاویر + required: false, + default: [], + }, + course_video: { + type: String, // مسیر ویدئو + required: false, + trim: true, + default: null, + }, + type: { + type: String, // نوع پست: 'image' یا 'video' + required: true, + enum: ['image', 'video'], + }, + files: [ + { + path: { type: String, required: false }, + type: { type: String, enum: ['image', 'video'], required: false }, + } + ], + caption: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1000, + default: null, + }, + status: { + type: String, + required: false, + trim: true, + enum: ['pending', 'accept', 'reject'], + default: 'accept', + }, + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }, + likes: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }], + comments: { + type: Object, + default: null, + }, + courseId: { + type: String, + }, + + is_free: { + type: Boolean, + }, + file_name: { + type: String, + }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model('AcademyContent', modelSchema); +module.exports = PostModel; \ No newline at end of file diff --git a/public/modstagram-back/models/AcademyLikeModel.js b/public/modstagram-back/models/AcademyLikeModel.js new file mode 100644 index 0000000..358f036 --- /dev/null +++ b/public/modstagram-back/models/AcademyLikeModel.js @@ -0,0 +1,25 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + + user_id: { + type: String, + required: true, + trim: true, + default: 0, + }, + course_id: { + type: String, + required: true, + trim: true, + default: 0, + }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("Likes", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/models/AcademyModel.js b/public/modstagram-back/models/AcademyModel.js new file mode 100644 index 0000000..9f8e758 --- /dev/null +++ b/public/modstagram-back/models/AcademyModel.js @@ -0,0 +1,55 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + academy_image: { + type: String, + required: false, + trim: true, + default: null, + }, + academy_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null, + }, + userId: { + type: String, + required: true, + }, + rate: { + type: Number, + trim: true, + default: 0 + }, + number_of_rate: { + type: Number, + trim: true, + default: 0 + }, + sheba: { + type: String, + required: false, + default: null + }, + bio: { + type: String, + required: false, + default: null + }, + tag: { + type: Object, + required: false, + default: null + }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("Academy", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/models/AcademyPaymentModel.js b/public/modstagram-back/models/AcademyPaymentModel.js new file mode 100644 index 0000000..b7c9fa7 --- /dev/null +++ b/public/modstagram-back/models/AcademyPaymentModel.js @@ -0,0 +1,24 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + price: { type: Number, required: true }, // قیمت نهایی شامل مالیات + discountAmount: { type: Number, default: 0 }, // مبلغ تخفیف + taxAmount: { type: Number, default: 0 }, // مبلغ مالیات + taxRate: { type: Number, default: 9 }, // درصد مالیات + course_name: { type: String, required: true }, + course_id: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true }, + academy_id: { type: mongoose.Schema.Types.ObjectId, ref: "Academy", required: true }, + user_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }, + payment_authority: { type: String }, + payment_ref_id: { type: String }, + status: { type: String, enum: ["pending", "success", "failed", "settled"], default: "success" }, + + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("AcademyPayment", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/models/AdminModel.js b/public/modstagram-back/models/AdminModel.js new file mode 100644 index 0000000..4bca3a2 --- /dev/null +++ b/public/modstagram-back/models/AdminModel.js @@ -0,0 +1,80 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const adminSchema = new mongoose.Schema({ + mobile: { + type: String, + required: false, + trim: true, + unique: true + }, + otp: { + type: String, + required: false, + trim: true, + minLength: 6, + maxLength: 6 + }, + user_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + password: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + first_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + last_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + user_type: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + profile_image: { + type: String, + required: false, + trim: true + }, + gender: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + last_online: { + type: Date, // ذخیره تاریخ و زمان آخرین بازدید + default: Date.now // تنظیم تاریخ به تاریخ فعلی + } +}) + +adminSchema.plugin(timestamp) +adminSchema.plugin(mongoosePaginate) +const AdminModel = mongoose.model('Admin', adminSchema) +module.exports = AdminModel diff --git a/public/modstagram-back/models/AdvertisingCategoryModel.js b/public/modstagram-back/models/AdvertisingCategoryModel.js new file mode 100644 index 0000000..855035a --- /dev/null +++ b/public/modstagram-back/models/AdvertisingCategoryModel.js @@ -0,0 +1,23 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const advertisingCategorySchema = new mongoose.Schema({ + title: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + status: { + type: Boolean, + required: false, + default: true + } +}) + +advertisingCategorySchema.plugin(timestamp) +advertisingCategorySchema.plugin(mongoosePaginate) +const AdvertisingCategoryModel = mongoose.model('AdvertisingCategory', advertisingCategorySchema) +module.exports = AdvertisingCategoryModel diff --git a/public/modstagram-back/models/AdvertisingCommentModel.js b/public/modstagram-back/models/AdvertisingCommentModel.js new file mode 100644 index 0000000..f6ea2b4 --- /dev/null +++ b/public/modstagram-back/models/AdvertisingCommentModel.js @@ -0,0 +1,32 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const advertisingCommentSchema = new mongoose.Schema({ + advertisingId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Advertising', + required: true + }, + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + text: { + type: String, + required: true, + trim: true + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], + default: 'pending' + } +}) + +advertisingCommentSchema.plugin(timestamp) +advertisingCommentSchema.plugin(mongoosePaginate) +const AdvertisingComment = mongoose.model('AdvertisingComment', advertisingCommentSchema) + +module.exports = AdvertisingComment diff --git a/public/modstagram-back/models/AdvertisingFeaturesModel.js b/public/modstagram-back/models/AdvertisingFeaturesModel.js new file mode 100644 index 0000000..4081d59 --- /dev/null +++ b/public/modstagram-back/models/AdvertisingFeaturesModel.js @@ -0,0 +1,27 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const advertisingFeaturesSchema = new mongoose.Schema({ + title: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + status: { + type: Boolean, + required: false, + default: true + }, + type: { + type: String, + default: 'boolean' + } +}) + +advertisingFeaturesSchema.plugin(timestamp) +advertisingFeaturesSchema.plugin(mongoosePaginate) +const AdvertisingFeaturesModel = mongoose.model('AdvertisingFeatures', advertisingFeaturesSchema) +module.exports = AdvertisingFeaturesModel diff --git a/public/modstagram-back/models/AdvertisingLikeModel.js b/public/modstagram-back/models/AdvertisingLikeModel.js new file mode 100644 index 0000000..f8552dd --- /dev/null +++ b/public/modstagram-back/models/AdvertisingLikeModel.js @@ -0,0 +1,20 @@ +const mongoose = require('mongoose') + +const advertisingLikeSchema = new mongoose.Schema({ + advertisingId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Advertising', + required: true + }, + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + } + +}) + +// تعریف مدل AdvertisingLikeModel +const AdvertisingLikeModel = mongoose.model('AdvertisingLike', advertisingLikeSchema) + +module.exports = AdvertisingLikeModel diff --git a/public/modstagram-back/models/AdvertisingModel.js b/public/modstagram-back/models/AdvertisingModel.js new file mode 100644 index 0000000..3046a48 --- /dev/null +++ b/public/modstagram-back/models/AdvertisingModel.js @@ -0,0 +1,230 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const advertisingSchema = new mongoose.Schema({ + title: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + category: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + description: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1024, + default: null + }, + province: { + type: Object, + default: null + }, + city: { + type: Object, + default: null + }, + neighbourhood: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + address: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + lat: { + type: String, + trim: true, + minLength: 1, + maxLength: 256, + default: null + }, + lng: { + type: String, + trim: true, + minLength: 1, + maxLength: 256, + default: null + }, + images: [{ + type: String, + required: false, + trim: true, + default: null + }], + services: [{ + title: { + type: String, + required: true, + trim: true + }, + originalPrice: { + type: String, + required: true + }, + discountPrice: { + type: String, + required: false + }, + discountPercentage: { + type: Number, + required: false + }, + status: { + type: String, + default: "UnderReview", + required: false + }, + image: { + type: String, + required: false, + trim: true + } + }], + features: [{ + title: { + type: String, + required: false, + trim: true + }, + value: { + type: Boolean, + required: true + } + }], + contactInfo: { + phone: { + type: String, + required: false, + trim: true, + default: null + }, + mobile: { + type: String, + required: false, + trim: true, + default: null + }, + telegramLink: { + type: String, + required: false, + trim: true, + default: null + }, + whatsappNumber: { + type: String, + required: false, + trim: true, + default: null + }, + instagramLink: { + type: String, + required: false, + trim: true, + default: null + }, + saveInfoForNextAds: { + type: Boolean, + required: true, + default: false + } + }, + type: { + type: String, + enum: ['free', 'normal', 'special', 'highlight'], + default: 'normal' + }, + status: { + type: String, + enum: ['pre_payment', 'paid', 'accepted', 'rejected', 'expired'], + default: 'pre_payment' + }, + payment_status: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + creator_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }, + reject_reason: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1024, + default: null + }, + mostDiscountPercentage: { + type: Number, + required: false + }, + showDiscount: { + type: Boolean, + required: false, + default: false + }, + likesCount: { + type: Number, + default: 0 + }, + commentsCount: { + type: Number, + default: 0 + }, + ratings: [{ + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + rating: { + type: Number, + required: true, + min: 1, + max: 5 + } + }], + averageRating: { + type: Number, + default: 0 + }, + ratingsCount: { + type: Number, + default: 0 + }, + viewCount: { + type: Number, + default: 0 + }, + acceptedAt: { + type: Date, + default: null + } +}) + +advertisingSchema.plugin(timestamp) +advertisingSchema.plugin(mongoosePaginate) +const AdvertisingModel = mongoose.model('Advertising', advertisingSchema) +module.exports = AdvertisingModel diff --git a/public/modstagram-back/models/AdvertisingProfile.js b/public/modstagram-back/models/AdvertisingProfile.js new file mode 100644 index 0000000..70dfc5a --- /dev/null +++ b/public/modstagram-back/models/AdvertisingProfile.js @@ -0,0 +1,113 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const advertisingProfileSchema = new mongoose.Schema({ + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + profile_image: { + type: String, + required: false, + trim: true, + default: null + }, + image_count: { + type: Number, + default: 0 + }, + like_count: { + type: Number, + default: 0 + }, + comment_count: { + type: Number, + default: 0 + }, + vitrine_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + category: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + about_us: { + type: String, + required: false, + minLength: 1, + maxLength: 1024, + default: null + }, + province: { + type: Object, + default: null + }, + city: { + type: Object, + default: null + }, + lat: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + lng: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + address: { + type: String, + required: false, + trim: true, + default: null + }, + neighbourhood: { + type: String, + required: false, + trim: true, + default: null + }, + adTotalRatings: { + type: Number, + default: 0 + }, + adRatingsCount: { + type: Number, + default: 0 + }, + adAverageRating: { + type: Number, + default: 0 + }, + contactInfo: { + phone: String, + mobile: String, + telegramLink: String, + whatsappNumber: String, + instagramLink: String, + saveInfoForNextAds: { type: Boolean, default: false } + } +}) + +advertisingProfileSchema.plugin(timestamp) +advertisingProfileSchema.plugin(mongoosePaginate) + +const AdvertisingProfileModel = mongoose.model('AdvertisingProfile', advertisingProfileSchema) + +module.exports = AdvertisingProfileModel diff --git a/public/modstagram-back/models/AdvertisingRatingModel.js b/public/modstagram-back/models/AdvertisingRatingModel.js new file mode 100644 index 0000000..ac8b79b --- /dev/null +++ b/public/modstagram-back/models/AdvertisingRatingModel.js @@ -0,0 +1,26 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const advertisingRatingSchema = new mongoose.Schema({ + advertisingId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Advertising', + required: true + }, + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + rating: { + type: Number, + required: true, + min: 1, + max: 5 + } +}) + +advertisingRatingSchema.plugin(timestamp) + +const AdvertisingRatingModel = mongoose.model('AdvertisingRating', advertisingRatingSchema) +module.exports = AdvertisingRatingModel diff --git a/public/modstagram-back/models/AdvertisingTypeModel.js b/public/modstagram-back/models/AdvertisingTypeModel.js new file mode 100644 index 0000000..5b49649 --- /dev/null +++ b/public/modstagram-back/models/AdvertisingTypeModel.js @@ -0,0 +1,25 @@ +const mongoose = require('mongoose') + +const advertisingTypeSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + }, + price: { + type: Number, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + }, + status: { + type: String, + default: 'active' + } +}) + +const AdvertisingTypeModel = mongoose.model('AdvertisingType', advertisingTypeSchema) +module.exports = AdvertisingTypeModel diff --git a/public/modstagram-back/models/CommentModel.js b/public/modstagram-back/models/CommentModel.js new file mode 100644 index 0000000..5fbabc9 --- /dev/null +++ b/public/modstagram-back/models/CommentModel.js @@ -0,0 +1,54 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const commentSchema = new mongoose.Schema({ + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + project: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Project', + required: false + }, + offer: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Offer', + required: false + }, + creator: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + rating: { + type: Number, + required: true + }, + comment: { + type: String, + trim: true + }, + post: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Post', + required: false + }, + comment_for: { + type: String, + enum: ['user', 'project', 'post'], + required: true + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], + default: 'pending' + } +}) + +commentSchema.plugin(timestamp) +commentSchema.plugin(mongoosePaginate) +const CommentModel = mongoose.model('Comment', commentSchema) +module.exports = CommentModel diff --git a/public/modstagram-back/models/CourseComentModel.js b/public/modstagram-back/models/CourseComentModel.js new file mode 100644 index 0000000..b5c7d5c --- /dev/null +++ b/public/modstagram-back/models/CourseComentModel.js @@ -0,0 +1,40 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + + user_id: { + type: String, + required: true, + trim: true, + }, + course_id: { + type: String, + required: true, + trim: true, + }, + comment: { + type: String, + required: true, + trim: true, + default: 0, + }, + rate: { + type: String, + required: true, + trim: true, + default: 0, + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], + default: 'accepted' + } + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("CourseComment", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/models/CourseModel.js b/public/modstagram-back/models/CourseModel.js new file mode 100644 index 0000000..f8a5e67 --- /dev/null +++ b/public/modstagram-back/models/CourseModel.js @@ -0,0 +1,79 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + price: { + type: String, + required: true, + }, + cuorse_name: { + type: String, + required: true, + }, + category:{ + type: String + }, + offer: { + type: String + }, + academyId:{ + type: String + }, + caption: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1000, + default: null, + }, + status: { + type: String, + required: false, + trim: true, + enum: ['pending', 'accept', 'reject'], + default: 'accept', + }, + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }, + likes: { + type: Number, + required: false, + trim: true, + default: 0, + }, + comments: { + type: Object, + default: null, + }, + type: { + type: String, + required: false, + trim: true, + enum: ['normal', 'pro', 'legend'], + default: "normal", + }, + course_time: { + type: String + }, + number_of_course_content: { + type: String + }, + teacher_number: { + type: String + }, + course_image: { + type: String + }, + teacher_name: { + type: String + }, +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("Course", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/models/CoursePaymentModel.js b/public/modstagram-back/models/CoursePaymentModel.js new file mode 100644 index 0000000..cb6de53 --- /dev/null +++ b/public/modstagram-back/models/CoursePaymentModel.js @@ -0,0 +1,22 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + price: { + type: String, + required: true, + }, + cuorse_type: { + type: String, + required: false, + trim: true, + enum: ['normal', 'pro', 'legend'], + }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("CoursePayment", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/models/ExpertiseModel.js b/public/modstagram-back/models/ExpertiseModel.js new file mode 100644 index 0000000..29b490a --- /dev/null +++ b/public/modstagram-back/models/ExpertiseModel.js @@ -0,0 +1,47 @@ +// const mongoose = require('mongoose') +// const timestamp = require('mongoose-timestamp') + +// const subExpertiseSchema = new mongoose.Schema({ +// id: { +// type: mongoose.Schema.Types.ObjectId, +// ref: 'ExpertiseModel' +// }, +// name: { +// type: String +// } +// }) + +// const expertiseSchema = new mongoose.Schema({ +// expertise: { +// type: String, +// unique: true +// }, +// sub_expertise: [subExpertiseSchema] +// }) + +// expertiseSchema.plugin(timestamp) + +// const ExpertiseModel = mongoose.model('Expertise', expertiseSchema) +// module.exports = ExpertiseModel + +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const subExpertiseSchema = new mongoose.Schema({ + name: { + type: String + } +}) + +const expertiseSchema = new mongoose.Schema({ + expertise: { + type: String, + unique: true + }, + sub_expertise: [subExpertiseSchema] +}) + +expertiseSchema.plugin(timestamp) + +const ExpertiseModel = mongoose.model('Expertise', expertiseSchema) +module.exports = ExpertiseModel diff --git a/public/modstagram-back/models/IsPaymentCourseModel.js b/public/modstagram-back/models/IsPaymentCourseModel.js new file mode 100644 index 0000000..0524f3c --- /dev/null +++ b/public/modstagram-back/models/IsPaymentCourseModel.js @@ -0,0 +1,15 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + user_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }, + course_id: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true }, + price_paid: { type: Number, required: true }, // قیمت پرداخت شده + purchased_at: { type: Date, default: Date.now }, +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("IsPaymentCourse", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/models/LikeModel.js b/public/modstagram-back/models/LikeModel.js new file mode 100644 index 0000000..1957530 --- /dev/null +++ b/public/modstagram-back/models/LikeModel.js @@ -0,0 +1,25 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const likeSchema = new mongoose.Schema({ + postId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Post', + required: true + }, + userId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + likes: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }] +}) + +// تعریف مدل LikeModel +likeSchema.plugin(timestamp) +const LikeModel = mongoose.model('Like', likeSchema) + +module.exports = LikeModel diff --git a/public/modstagram-back/models/MessageModel.js b/public/modstagram-back/models/MessageModel.js new file mode 100644 index 0000000..594f7c4 --- /dev/null +++ b/public/modstagram-back/models/MessageModel.js @@ -0,0 +1,51 @@ +const mongoose = require('mongoose') +const { Schema } = mongoose + +const messageSchema = new Schema({ + senderId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + receiverId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + content: { + type: String, + required: false, + trim: true + }, + file: { + type: String, + required: false + }, + fileType: { + type: String, + enum: ['image', 'video', 'file', 'voice', 'location'], + required: false + }, + replyToId: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Message', + required: false + }, + forwardedFrom: { + userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, + userName: String, + displayName: String + }, + createdAt: { + type: Date, + default: Date.now + }, + readStatus: { + type: Number, + default: 0 + } +}) + +const MessageModel = mongoose.model('Message', messageSchema) + +module.exports = MessageModel diff --git a/public/modstagram-back/models/NotificationModel.js b/public/modstagram-back/models/NotificationModel.js new file mode 100644 index 0000000..ff79e19 --- /dev/null +++ b/public/modstagram-back/models/NotificationModel.js @@ -0,0 +1,37 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const notificationSchema = new mongoose.Schema({ + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', // مرجع به مدل کاربر + required: true + }, + project_post_id: { + type: mongoose.Schema.Types.ObjectId, + required: false + }, + type: { + type: String, + required: true + }, + title: { + type: String, + required: true + }, + description: { + type: String, + required: true + }, + read: { + type: Boolean, + default: false // وضعیت خوانده شده یا نشده + } +}) + +notificationSchema.plugin(timestamp) +notificationSchema.plugin(mongoosePaginate) + +const NotificationModel = mongoose.model('Notification', notificationSchema) +module.exports = NotificationModel diff --git a/public/modstagram-back/models/OfferModel.js b/public/modstagram-back/models/OfferModel.js new file mode 100644 index 0000000..ec36550 --- /dev/null +++ b/public/modstagram-back/models/OfferModel.js @@ -0,0 +1,32 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') + +const offerSchema = new mongoose.Schema({ + sender: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + receiver: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], // وضعیت درخواست + default: 'pending' + }, + transaction_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Payment', + default: null + } +}) + +offerSchema.plugin(timestamp) +offerSchema.plugin(mongoosePaginate) + +const OfferModel = mongoose.model('Offer', offerSchema) +module.exports = OfferModel diff --git a/public/modstagram-back/models/OfferTypeModel.js b/public/modstagram-back/models/OfferTypeModel.js new file mode 100644 index 0000000..fa2b49c --- /dev/null +++ b/public/modstagram-back/models/OfferTypeModel.js @@ -0,0 +1,21 @@ +const mongoose = require('mongoose') + +const offerTypeModelSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + }, + price: { + type: Number, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + } +}) + +const OfferTypeModel = mongoose.model('OfferTypeModel', offerTypeModelSchema) +module.exports = OfferTypeModel diff --git a/public/modstagram-back/models/PaymentModel.js b/public/modstagram-back/models/PaymentModel.js new file mode 100644 index 0000000..c78a252 --- /dev/null +++ b/public/modstagram-back/models/PaymentModel.js @@ -0,0 +1,46 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const paymentSchema = new mongoose.Schema({ + amount: { + type: Number, + required: true + }, + status: { + type: String, + enum: ['pending', 'successful', 'failed'], + default: 'pending' + }, + authority: { + type: String, + required: false + }, + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }, + project_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Project' + }, + advertising_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Advertising' + }, + type: { + type: String, + required: true + }, + installment_step: { + type: String, + required: false, + default: null + } +}) + +paymentSchema.plugin(timestamp) +paymentSchema.plugin(mongoosePaginate) + +const PaymentModel = mongoose.model('Payment', paymentSchema) +module.exports = PaymentModel diff --git a/public/modstagram-back/models/PostModel.js b/public/modstagram-back/models/PostModel.js new file mode 100644 index 0000000..ff6d8cc --- /dev/null +++ b/public/modstagram-back/models/PostModel.js @@ -0,0 +1,60 @@ +const mongoose = require('mongoose'); +const timestamp = require('mongoose-timestamp'); +const mongoosePaginate = require('mongoose-paginate-v2'); + +const modelSchema = new mongoose.Schema({ + post_images: { + type: [String], // آرایه‌ای از مسیرهای تصاویر + required: false, + default: [], + }, + post_video: { + type: String, // مسیر ویدئو + required: false, + trim: true, + default: null, + }, + type: { + type: String, // نوع پست: 'image' یا 'video' + required: true, + enum: ['image', 'video'], + }, + files: [ + { + path: { type: String, required: true }, + type: { type: String, enum: ['image', 'video'], required: true }, + } + ], + caption: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1000, + default: null, + }, + status: { + type: String, + required: false, + trim: true, + enum: ['pending', 'accept', 'reject'], + default: 'pending', + }, + user_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }, + likes: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + }], + comments: { + type: Object, + default: null, + }, +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model('Post', modelSchema); +module.exports = PostModel; \ No newline at end of file diff --git a/public/modstagram-back/models/ProjectModel.js b/public/modstagram-back/models/ProjectModel.js new file mode 100644 index 0000000..4b4382e --- /dev/null +++ b/public/modstagram-back/models/ProjectModel.js @@ -0,0 +1,186 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') +const projectSchema = new mongoose.Schema({ + title: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + expertise: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + sub_expertise: { + type: [String], // تغییر نوع به آرایه از استرینگ + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + gender: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + age: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + conversation_projects: { + type: Boolean, + required: false, + default: null + }, + province: { + type: Object, + default: null + }, + city: { + type: Object, + default: null + }, + offer_time: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + offer_price: { + type: Number, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + description: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1024, + default: null + }, + project_type: { + type: String, + enum: ['free', 'normal', 'force', 'highlight'], + default: 'normal' + }, + payment_status: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + // فیلد برای وضعیت پروژه + status: { + type: String, + enum: ['pre_payment', 'paid', 'accepted', 'rejected', 'done', 'cancled', 'ongoing'], + default: 'pre_payment' + }, + public_status: { + type: String, + enum: ['public', 'private'], + default: 'public' + }, + created_for_user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + default: null + }, + creator_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }, + requested_users: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }], + selected_user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + default: null + }, + final_price: { + type: Number, + required: false, + default: null + }, + final_time: { + type: Number, + required: false, + default: null + }, + installments: [{ + installment_number: { + type: Number, + required: true + }, + amount: { + type: Number, + required: true + }, + due_date: { + type: Date, + required: true + } + }], + reject_reason: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 1024, + default: null + }, + ratings: [{ + creator_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + rating: { + type: Number, + required: true + }, + comment: { + type: String, + trim: true + } + }], + acceptedAt: { + type: Date, + default: null + }, + isExpired: { + type: Boolean, + default: false + } + +}) + +projectSchema.plugin(timestamp) +// اضافه کردن پیجینیشن به مدل +projectSchema.plugin(mongoosePaginate) +const ProjectModel = mongoose.model('Project', projectSchema) +module.exports = ProjectModel diff --git a/public/modstagram-back/models/RequestModel.js b/public/modstagram-back/models/RequestModel.js new file mode 100644 index 0000000..3049ec1 --- /dev/null +++ b/public/modstagram-back/models/RequestModel.js @@ -0,0 +1,33 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const requestSchema = new mongoose.Schema({ + project: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Project', + required: true + }, + user: { + type: mongoose.Schema.Types.ObjectId, + ref: 'User', + required: true + }, + time: { + type: Number, + required: true + }, + price: { + type: Number, + required: true + }, + status: { + type: String, + enum: ['pending', 'accepted', 'rejected'], + default: 'pending' + } +}) + +requestSchema.plugin(timestamp) + +const RequestModel = mongoose.model('Request', requestSchema) +module.exports = RequestModel diff --git a/public/modstagram-back/models/SettingsModel.js b/public/modstagram-back/models/SettingsModel.js new file mode 100644 index 0000000..8d41208 --- /dev/null +++ b/public/modstagram-back/models/SettingsModel.js @@ -0,0 +1,19 @@ +// models/Setting.js +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') + +const settingSchema = new mongoose.Schema({ + key: { + type: String, + required: true, + unique: true + }, + value: { + type: String, + required: true + } +}) +settingSchema.plugin(timestamp) + +const SettingModel = mongoose.model('Setting', settingSchema) +module.exports = SettingModel diff --git a/public/modstagram-back/models/StateCity.js b/public/modstagram-back/models/StateCity.js new file mode 100644 index 0000000..5f24232 --- /dev/null +++ b/public/modstagram-back/models/StateCity.js @@ -0,0 +1,19 @@ +const mongoose = require('mongoose') + +const provincesSchema = new mongoose.Schema({ + id: Number, + name: String, + slug: String +}) + +const citiesSchema = new mongoose.Schema({ + id: Number, + name: String, + slug: String, + province_id: Number +}) + +const ProvinceModel = mongoose.model('Province', provincesSchema) +const CityModel = mongoose.model('City', citiesSchema) + +module.exports = { ProvinceModel, CityModel } diff --git a/public/modstagram-back/models/TaxModel.js b/public/modstagram-back/models/TaxModel.js new file mode 100644 index 0000000..70b27e7 --- /dev/null +++ b/public/modstagram-back/models/TaxModel.js @@ -0,0 +1,15 @@ +const mongoose = require("mongoose"); +const timestamp = require("mongoose-timestamp"); +const mongoosePaginate = require("mongoose-paginate-v2"); + +const modelSchema = new mongoose.Schema({ + type: { type: String, enum: ["course", "product", "service"], required: true }, + tax: { type: Number, required: true, default: 9 }, // درصد مالیات + is_active: { type: Boolean, default: true }, + +}); + +modelSchema.plugin(timestamp); +modelSchema.plugin(mongoosePaginate); +const PostModel = mongoose.model("Tax", modelSchema); +module.exports = PostModel; diff --git a/public/modstagram-back/models/TicketMessageModel.js b/public/modstagram-back/models/TicketMessageModel.js new file mode 100644 index 0000000..b054d05 --- /dev/null +++ b/public/modstagram-back/models/TicketMessageModel.js @@ -0,0 +1,20 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const ticketMessageSchema = new mongoose.Schema({ + text: { type: String, required: false }, + file: { + type: String, // مسیر فایل در ذخیره شود + required: false // فایل اختیاری است + }, + senderType: { type: String, enum: ['User', 'Admin'], required: true }, + senderId: { type: mongoose.Schema.Types.ObjectId, refPath: 'senderType', required: true }, + ticket: { type: mongoose.Schema.Types.ObjectId, ref: 'Ticket', required: true } +}) + +ticketMessageSchema.plugin(timestamp) +// اضافه کردن پیجینیشن به مدل +ticketMessageSchema.plugin(mongoosePaginate) +const TicketMessageModel = mongoose.model('TicketMessage', ticketMessageSchema) +module.exports = TicketMessageModel diff --git a/public/modstagram-back/models/TicketModel.js b/public/modstagram-back/models/TicketModel.js new file mode 100644 index 0000000..4157fb3 --- /dev/null +++ b/public/modstagram-back/models/TicketModel.js @@ -0,0 +1,24 @@ +const mongoose = require('mongoose') +const timestamp = require('mongoose-timestamp') +const mongoosePaginate = require('mongoose-paginate-v2') + +const ticketSchema = new mongoose.Schema({ + title: { type: String, required: true }, + status: { type: String, enum: ['Pending', 'Answered', 'Customer Response', 'Closed'], default: 'Pending' }, + user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, + new_message: { + type: Boolean, + default: false // وضعیت خوانده شده یا نشده + } +}) + +ticketSchema.pre('save', function (next) { + this.updatedAt = Date.now() + next() +}) + +ticketSchema.plugin(timestamp) +// اضافه کردن پیجینیشن به مدل +ticketSchema.plugin(mongoosePaginate) +const TicketModel = mongoose.model('Ticket', ticketSchema) +module.exports = TicketModel diff --git a/public/modstagram-back/models/TypeAndPriceModel.js b/public/modstagram-back/models/TypeAndPriceModel.js new file mode 100644 index 0000000..2b059d1 --- /dev/null +++ b/public/modstagram-back/models/TypeAndPriceModel.js @@ -0,0 +1,21 @@ +const mongoose = require('mongoose') + +const typeAndPriceSchema = new mongoose.Schema({ + name: { + type: String, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + }, + price: { + type: Number, + required: true, + trim: true, + minLength: 1, + maxLength: 255 + } +}) + +const TypeAndPriceModel = mongoose.model('TypeAndPrice', typeAndPriceSchema) +module.exports = TypeAndPriceModel diff --git a/public/modstagram-back/models/UserModel.js b/public/modstagram-back/models/UserModel.js new file mode 100644 index 0000000..66b025a --- /dev/null +++ b/public/modstagram-back/models/UserModel.js @@ -0,0 +1,381 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const userSchema = new mongoose.Schema({ + mobile: { + type: String, + required: false, + trim: true, + unique: true + }, + otp: { + type: String, + required: false, + trim: true, + minLength: 6, + maxLength: 6, + default: null + }, + user_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + password: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + first_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + last_name: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + user_type: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + is_verified: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: 'none' + }, + profile_image: { + type: String, + required: false, + trim: true, + default: null + }, + national_card_image: { + type: String, + required: false, + trim: true, + default: null + }, + expertise: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + sub_expertise: { + type: [String], // تغییر نوع به آرایه از استرینگ + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + gender: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + height: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + weight: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + size: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + eye_color: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + hair_color: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + cooperation_type: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + cooperation_abroad: { + type: Boolean, + required: false, + default: null + }, + conversation_projects: { + type: Boolean, + required: false, + default: null + }, + bio: { + type: String, + required: false, + minLength: 1, + maxLength: 1024, + default: null + }, + national_code: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + birthday: { + type: Date, + required: false, + default: null + }, + is_Register: { + type: String, + + default: false + }, + shaba: { + type: String, + required: false, + trim: true, + minLength: 1, + maxLength: 255, + default: null + }, + address: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + province: { + type: Object, + default: null + }, + city: { + type: Object, + default: null + }, + lat: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + lng: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + show_location: { + type: Boolean, + required: false, + default: null + }, + rate: { + type: String, + trim: true, + maxLength: 512, + default: null + }, + referral_code: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + shop_id: { + type: mongoose.Schema.Types.ObjectId, + ref: 'Shop', + default: null + }, + last_online: { + type: Date, // ذخیره تاریخ و زمان آخرین بازدید + default: Date.now // تنظیم تاریخ به تاریخ فعلی + }, + business_license: { + type: String, + required: false, + trim: true, + default: null + }, + user_level: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + user_score: { + type: String, + trim: true, + minLength: 1, + maxLength: 512, + default: null + }, + last_post: { + type: Object, + default: null + }, + // user_ratings: [{ + // project_id: { + // type: mongoose.Schema.Types.ObjectId, + // ref: 'Project', + // required: true + // }, + // creator_id: { + // type: mongoose.Schema.Types.ObjectId, + // ref: 'User', + // required: true + // }, + // rating: { + // type: Number, + // required: true + // }, + // comment: { + // type: String, + // trim: true + // } + // }], + daily_free_request: { + type: Number, + default: 1 + }, + last_free_request_date: { + type: Date, + default: null + }, + blocked_by: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }], + blocked_users: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'User' + }], + block_status: { + type: Boolean, + required: false, + default: null + }, + advertising_profiles: [{ + type: mongoose.Schema.Types.ObjectId, + ref: 'AdvertisingProfile' + }], + services: [{ + title: { + type: String, + required: true, + trim: true + }, + originalPrice: { + type: String, + required: true + }, + discountPrice: { + type: String, + required: false + }, + discountPercentage: { + type: Number, + required: false + }, + status: { + type: String, + default: "UnderReview", + required: false + }, + image: { + type: String, + required: false, + trim: true + } + }], + monthly_free_offer: { + type: Number, + default: 1 + }, + last_free_offer_date: { + type: Date, + default: null + } + // contactInfo: { + // phone: String, + // mobile: String, + // telegramLink: String, + // whatsappNumber: String, + // instagramLink: String, + // saveInfoForNextAds: { type: Boolean, default: false } + // }, + // adTotalRatings: { + // type: Number, + // default: 0 + // }, + // adRatingsCount: { + // type: Number, + // default: 0 + // }, + // adAverageRating: { + // type: Number, + // default: 0 + // } +}) + +userSchema.plugin(timestamp) +userSchema.plugin(mongoosePaginate) +const UserModel = mongoose.model('User', userSchema) +module.exports = UserModel diff --git a/public/modstagram-back/models/VersionModel.js b/public/modstagram-back/models/VersionModel.js new file mode 100644 index 0000000..51aaf0b --- /dev/null +++ b/public/modstagram-back/models/VersionModel.js @@ -0,0 +1,12 @@ +// models/VersionModel.js +const mongoose = require('mongoose') + +const versionSchema = new mongoose.Schema({ + version: { type: String, required: true }, + mandatory: { type: Boolean, required: true }, + releaseNotes: { type: String }, + updateUrls: { type: [String], required: true } // لینک‌های آپدیت +}) + +const VersionModel = mongoose.model('Version', versionSchema) +module.exports = VersionModel diff --git a/public/modstagram-back/models/license.js b/public/modstagram-back/models/license.js new file mode 100644 index 0000000..13c59a2 --- /dev/null +++ b/public/modstagram-back/models/license.js @@ -0,0 +1,14 @@ +const mongoose = require('mongoose') +const mongoosePaginate = require('mongoose-paginate-v2') +const timestamp = require('mongoose-timestamp') +const license = new mongoose.Schema({ + + userId : String, + Confirmation : { type : Boolean, default : false}, + licenseImg : { type : String }, +}) + +license.plugin(timestamp) +license.plugin(mongoosePaginate) +const LicenseMoldel = mongoose.model('license', license) +module.exports = LicenseMoldel diff --git a/public/modstagram-back/modstagram-back@1.0.0 b/public/modstagram-back/modstagram-back@1.0.0 new file mode 100644 index 0000000..e69de29 diff --git a/public/modstagram-back/nodemon.json b/public/modstagram-back/nodemon.json new file mode 100644 index 0000000..e76d883 --- /dev/null +++ b/public/modstagram-back/nodemon.json @@ -0,0 +1,6 @@ +{ + "watch": ["*.js"], + "ext": "js", + "ignore": [], + "exec": "node server.js" +} diff --git a/public/modstagram-back/package-lock.json b/public/modstagram-back/package-lock.json new file mode 100644 index 0000000..cbd9e5c --- /dev/null +++ b/public/modstagram-back/package-lock.json @@ -0,0 +1,5576 @@ +{ + "name": "modstagram-back", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "modstagram-back", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^1.6.7", + "bcryptjs": "^2.4.3", + "body-parser": "^1.20.2", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.18.3", + "express-form-data": "^2.0.23", + "express-rate-limit": "^7.2.0", + "express-session": "^1.18.0", + "express-validator": "^7.0.1", + "helmet": "^7.1.0", + "jsonwebtoken": "^9.0.2", + "lodash": "^4.17.21", + "moment-jalaali": "^0.10.0", + "mongoose": "^8.2.1", + "mongoose-paginate-v2": "^1.8.0", + "mongoose-timestamp": "^0.6.0", + "multer": "^2.0.2", + "node-cron": "^3.0.3", + "nodemon": "^3.1.0", + "socket.io": "^4.7.5", + "socket.io-client": "^4.7.5" + }, + "devDependencies": { + "cross-env": "^7.0.3", + "eslint": "^8.57.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^16.6.2", + "eslint-plugin-promise": "^6.1.1", + "webpack": "^5.90.3", + "webpack-cli": "^5.1.4" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.5.tgz", + "integrity": "sha512-XLNOMH66KhJzUJNwT/qlMnS4WsNDWD5ASdyaSH3EtK+F4r/CFGa3jT4GNi4mfOitGvWXtdLgQJkQjxSVrio+jA==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.5", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.5.tgz", + "integrity": "sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==", + "dev": true, + "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, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "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 + }, + "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 + }, + "node_modules/@types/node": { + "version": "20.11.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", + "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "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 + }, + "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 + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/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, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "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/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.filter": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", + "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", + "integrity": "sha512-hzvSHUshSpCflDR1QMUBLHGHP1VIEBegT4pix9H/Z92Xw3ySoy6c2qh7lJWTJnRJ8JCZ9bJNCgTyYaJGcJu6xQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "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==" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "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" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bson": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.4.0.tgz", + "integrity": "sha512-6/gSSEdbkuFlSb+ufj5jUSU4+wo8xQOwm2bDSqwmxiPE17JTpsP63eAwoN8iF8Oy4gJYj+PAL3zdRCTdaw5Y1g==", + "engines": { + "node": ">=16.20.1" + } + }, + "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==" + }, + "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==" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/builtins/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "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, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001596", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz", + "integrity": "sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ==", + "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" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "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==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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 + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "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/connect-multiparty": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/connect-multiparty/-/connect-multiparty-2.2.0.tgz", + "integrity": "sha512-zKcpA7cuXGEhuw9Pz7JmVCFmp85jzGLGm/iiagXTwyEAJp4ypLPtRS/V4IGuGb9KjjrgHBs6P/gDCpZHnFzksA==", + "dependencies": { + "http-errors": "~1.7.0", + "multiparty": "~4.2.1", + "on-finished": "~2.3.0", + "qs": "~6.5.2", + "type-is": "~1.6.16" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/connect-multiparty/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/connect-multiparty/node_modules/http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/connect-multiparty/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connect-multiparty/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/connect-multiparty/node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/connect-multiparty/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/connect-multiparty/node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "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, + "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==", + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/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==", + "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==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.699", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.699.tgz", + "integrity": "sha512-I7q3BbQi6e4tJJN5CRcyvxhK0iJb34TV8eJQcgh+fR2fQ8miMgZcEInckCo1U9exDHbfz7DLDnFn8oqH/VcRKw==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-client": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz", + "integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.1.tgz", + "integrity": "sha512-3d3JRbwsCLJsYgvb6NuWEG44jjPSOMuS73L/6+7BZuoKm3W+qXnSoIYVHi8dG7Qcg4inAY4jbzkZ7MnskePeDg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz", + "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-abstract": { + "version": "1.22.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", + "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "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==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", + "dev": true + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "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==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz", + "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-config-standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", + "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" + } + ], + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", + "eslint-plugin-promise": "^6.0.0" + } + }, + "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, + "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, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/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==", + "dev": true + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "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, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/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==", + "dev": true + }, + "node_modules/eslint-plugin-es-x": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.5.0.tgz", + "integrity": "sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.6.0", + "eslint-compat-utils": "^0.1.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "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.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "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, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/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==", + "dev": true + }, + "node_modules/eslint-plugin-n": { + "version": "16.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", + "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "builtins": "^5.0.1", + "eslint-plugin-es-x": "^7.5.0", + "get-tsconfig": "^4.7.0", + "globals": "^13.24.0", + "ignore": "^5.2.4", + "is-builtin-module": "^3.2.1", + "is-core-module": "^2.12.1", + "minimatch": "^3.1.2", + "resolve": "^1.22.2", + "semver": "^7.5.3" + }, + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "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, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/express": { + "version": "4.18.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz", + "integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-form-data": { + "version": "2.0.23", + "resolved": "https://registry.npmjs.org/express-form-data/-/express-form-data-2.0.23.tgz", + "integrity": "sha512-Efm2t+xL6vEqUPs4kAyBY9xG/8LGpbSVnnFLZw6HgdxHzSRlg2/sNlA2UdMlcIKMH+LDOn7NKXUDGJK125F4rw==", + "dependencies": { + "connect-multiparty": "^2.2.0", + "fs-extra": "^9.1.0", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": ">=10.7.0" + } + }, + "node_modules/express-rate-limit": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.2.0.tgz", + "integrity": "sha512-T7nul1t4TNyfZMJ7pKRKkdeVJWa2CqB8NA1P8BwYaoDI5QSBZARv5oMS43J7b7I5P+4asjVXjb7ONuwDKucahg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "4 || 5 || ^5.0.0-beta.1" + } + }, + "node_modules/express-session": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.0.tgz", + "integrity": "sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ==", + "dependencies": { + "cookie": "0.6.0", + "cookie-signature": "1.0.7", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express-session/node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "node_modules/express-session/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express-session/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express-validator": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.0.1.tgz", + "integrity": "sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==", + "dependencies": { + "lodash": "^4.17.21", + "validator": "^13.9.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "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 + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "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, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/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 + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "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==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "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, + "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==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/helmet": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", + "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "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, + "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==", + "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==" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "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==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "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==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "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 + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jalaali-js": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.6.tgz", + "integrity": "sha512-io974va+Qyu+UfuVX3UIAgJlxLhAMx9Y8VMfh+IG00Js7hXQo1qNQuwSiSa0xxco0SVgx5HWNkaiCcV+aZ8WPw==" + }, + "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, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-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 + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/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, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "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/jsonwebtoken/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "engines": { + "node": ">=12.0.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, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "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==" + }, + "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==" + }, + "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==" + }, + "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==" + }, + "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==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "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 + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "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==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-jalaali": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/moment-jalaali/-/moment-jalaali-0.10.0.tgz", + "integrity": "sha512-XICH1+UHd3zyaE1bXWQBlhoXBqbzEyFfT0TrifNobHxLALRuTSwXn376bX8FmkYg9mZimevwwdd6EB57s5wuFA==", + "dependencies": { + "jalaali-js": "^1.1.0", + "moment": "^2.22.2", + "moment-timezone": "^0.5.21", + "rimraf": "^3.0.2" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.3.0.tgz", + "integrity": "sha512-tt0KuGjGtLUhLoU263+xvQmPHEGTw5LbcNC73EoFRYgSHwZt5tsoJC110hDyO1kjQzpgNrpdcSza9PknWN4LrA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.0", + "bson": "^6.2.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.2.1.tgz", + "integrity": "sha512-UgZZbXSJH0pdU936qj3FyVI+sBsMoGowFnL5R/RYrA50ayn6+ZYdVr8ehsRgNxRcMYwoNld5XzHIfkFRJTePEw==", + "dependencies": { + "bson": "^6.2.0", + "kareem": "2.5.1", + "mongodb": "6.3.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose-paginate-v2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mongoose-paginate-v2/-/mongoose-paginate-v2-1.8.0.tgz", + "integrity": "sha512-JiGbGxc/ytIA8UL4GaJdCLuxv5i99+XmTdP4v9YXwiJ85tdOxdrc2NQJL+0O+NRbIl+aAhaOnDbL9bJt7o3zIA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mongoose-timestamp": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mongoose-timestamp/-/mongoose-timestamp-0.6.0.tgz", + "integrity": "sha512-H0f/x2z7yvIiijP3UaE6bsSTP71WqVxn8GR8OOYKUSWmf+U1mD1K+QeEQ5BlYl6zbp/l/19F8sHXA/vUAyDnRg==", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/mongoose/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==" + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", + "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "concat-stream": "^2.0.0", + "mkdirp": "^0.5.6", + "object-assign": "^4.1.1", + "type-is": "^1.6.18", + "xtend": "^4.0.2" + }, + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/multiparty": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", + "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", + "dependencies": { + "http-errors": "~1.8.1", + "safe-buffer": "5.2.1", + "uid-safe": "2.1.5" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/multiparty/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multiparty/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/multiparty/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "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 + }, + "node_modules/node-cron": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", + "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "dependencies": { + "uuid": "8.3.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/nodemon": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", + "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", + "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "dev": true, + "dependencies": { + "array.prototype.filter": "^1.0.3", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.0.0" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "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==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "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, + "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==", + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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, + "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, + "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, + "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, + "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, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/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==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "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/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, + "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, + "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, + "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, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "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, + "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": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/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==" + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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==", + "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, + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "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==" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/socket.io": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.5.tgz", + "integrity": "sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA==", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", + "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "dependencies": { + "debug": "~4.3.4", + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-client": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", + "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", + "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-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "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.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "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, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.29.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", + "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "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==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "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, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "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" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "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, + "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/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/webpack": { + "version": "5.90.3", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz", + "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "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-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "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, + "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, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "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, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "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==" + }, + "node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "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/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/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/public/modstagram-back/package.json b/public/modstagram-back/package.json new file mode 100644 index 0000000..f0d6cf4 --- /dev/null +++ b/public/modstagram-back/package.json @@ -0,0 +1,49 @@ +{ + "name": "modstagram-back", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "node server.js", + "dev": "cross-env NODE_ENV=development nodemon index.js", + "build": "webpack", + "prod": "node dist/final.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^1.6.7", + "bcryptjs": "^2.4.3", + "body-parser": "^1.20.2", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.18.3", + "express-form-data": "^2.0.23", + "express-rate-limit": "^7.2.0", + "express-session": "^1.18.0", + "express-validator": "^7.0.1", + "helmet": "^7.1.0", + "jsonwebtoken": "^9.0.2", + "lodash": "^4.17.21", + "moment-jalaali": "^0.10.0", + "mongoose": "^8.2.1", + "mongoose-paginate-v2": "^1.8.0", + "mongoose-timestamp": "^0.6.0", + "multer": "^2.0.2", + "node-cron": "^3.0.3", + "nodemon": "^3.1.0", + "socket.io": "^4.7.5", + "socket.io-client": "^4.7.5" + }, + "devDependencies": { + "cross-env": "^7.0.3", + "eslint": "^8.57.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^16.6.2", + "eslint-plugin-promise": "^6.1.1", + "webpack": "^5.90.3", + "webpack-cli": "^5.1.4" + } +} diff --git a/public/modstagram-back/routes/application/academy/index.js b/public/modstagram-back/routes/application/academy/index.js new file mode 100644 index 0000000..a875597 --- /dev/null +++ b/public/modstagram-back/routes/application/academy/index.js @@ -0,0 +1,383 @@ +const express = require("express"); +const router = express.Router(); +const academyController = require("../../../controllers/application/academy/academyControllers"); +const multer = require("multer"); +const path = require("path"); +const fs = require("fs"); +// const academyCategoryController = require("../../../controllers/application/academy/academyCategoryController"); + +// ========================================== +// ⚙️ تنظیمات اولیه و دایرکتوری‌ها +// ========================================== + +// اطمینان از وجود دایرکتوری‌ها +const ensureDir = (dir) => { + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + console.log("DEBUG: Created directory:", dir); + } +}; + +const BASE_DIR = process.cwd(); +const courseVideoDir = path.join(BASE_DIR, "storage", "courses", "videos"); +const courseImageDir = path.join(BASE_DIR, "storage", "courses", "images"); + +console.log("DEBUG: BASE_DIR:", BASE_DIR); +console.log("DEBUG: courseVideoDir:", courseVideoDir); +console.log("DEBUG: courseImageDir:", courseImageDir); + +ensureDir(courseVideoDir); +ensureDir(courseImageDir); + +// ========================================== +// 📁 تنظیمات آپلود فایل با Multer +// ========================================== + +// تنظیمات ذخیره‌سازی فایل‌ها +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + console.log("DEBUG: Multer destination - fieldname:", file.fieldname); + // استفاده از دایرکتوری موقت برای آپلود اولیه + const tempDir = "/tmp/modstagram-uploads"; + if (!fs.existsSync(tempDir)) { + fs.mkdirSync(tempDir, { recursive: true }); + } + cb(null, tempDir); + }, + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + "-" + Math.round(Math.random() * 1e9); + const filename = uniqueSuffix + path.extname(file.originalname); + console.log("DEBUG: Generated filename:", filename); + cb(null, filename); + }, +}); + +// تنظیمات Multer با محدودیت حجم 500 مگابایت +const upload = multer({ + storage: storage, + limits: { + fileSize: 500 * 1024 * 1024, // 500 MB + }, +}); + +// ========================================== +// 🏢 مسیرهای مربوط به آکادمی +// ========================================== + +// دریافت اطلاعات آکادمی کاربر جاری +router.get("/", academyController.findAcademy); + +// یافتن آکادمی با شناسه +router.post("/findAcademyById", academyController.findAcademyById); + +// تکمیل پروفایل آکادمی +router.post("/academy/profile", academyController.academyProfile); + +// ========================================== +// 📚 مسیرهای مدیریت دوره‌ها (Courses) +// ========================================== + +// ایجاد دوره جدید +router.post("/academy/creat/course", academyController.creatCourse); + +// ویرایش دوره +router.patch("/academy/update/course", academyController.updateCourse); + +// حذف دوره (تغییر وضعیت به reject) +router.delete("/academy/delete/course", academyController.deleteCourse); + +// دریافت لیست دوره‌های آکادمی جاری +router.get("/academy/get/course", academyController.getCourse); + +// دریافت لیست همه دوره‌ها با فیلتر و صفحه‌بندی +router.get("/academy/get/curses", academyController.getCourses); + +// دریافت دوره‌های یک آکادمی خاص +router.get("/academy/get/getAcademyCourse/:Id", academyController.getAcademyCourse); + +// ========================================== +// 💳 مسیرهای پرداخت و مالی +// ========================================== + +// پرداخت برای اشتراک پرو +router.post("/academy/course/payment", academyController.proPayment); + +// کال‌بک درگاه پرداخت زرین‌پال (اشتراک پرو) +router.get("/academy/course/pro", academyController.handleCoursePaymentCallback); + +// پرداخت برای خرید دوره +router.post("/academy/course/payment-web", academyController.coursePayment); + +// کال‌بک درگاه پرداخت زرین‌پال (خرید دوره) +router.get("/academy/course/payment/verify", academyController.CoursePaymentCallback); + +// ========================================== +// 🎬 مسیرهای محتوای دوره (ویدیوها و فایل‌ها) +// ========================================== + +// دریافت محتوای دوره (ویدیوها) +router.get("/academy/course/content", academyController.getCourseContent); + +// حذف ویدیو از دوره +router.delete("/academy/course/content/video", academyController.deleteCourseVideo); + +// ========================================== +// 📹 مسیرهای آپلود ویدیو (۳ روش مختلف) +// ========================================== + +// روش 1: آپلود معمولی با Multipart (با استفاده از Multer) +router.post( + "/academy/course/creat/video", + (req, res, next) => { + console.log("===== STEP 1: Route hit ====="); + console.log("Content-Type:", req.headers["content-type"]); + next(); + }, + (req, res, next) => { + console.log("===== STEP 2: Before multer ====="); + next(); + }, + (req, res, next) => { + // اجرای manual multer با try-catch + upload.single("video")(req, res, (err) => { + if (err) { + console.log("===== MULTER ERROR ====="); + console.log("Error name:", err.name); + console.log("Error message:", err.message); + console.log("Full error:", err); + return res.status(400).json({ + success: false, + message: `خطا در آپلود: ${err.message}`, + error: err.toString(), + }); + } + console.log("===== STEP 3: Multer completed successfully ====="); + next(); + }); + }, + (req, res, next) => { + console.log("===== STEP 4: After multer ====="); + console.log("req.file:", req.file); + console.log("req.body:", req.body); + + if (!req.file) { + console.log("ERROR: No file in req.file!"); + return res.status(400).json({ + success: false, + message: "فایلی دریافت نشد", + }); + } + next(); + }, + academyController.creatCourseVideo +); + +// روش 2: آپلود با Base64 (برای فایل‌های کوچک) +router.post( + "/academy/course/creat/video-base64", + academyController.creatCourseVideoBase64 +); + +// روش 3: آپلود تکه‌تکه (Chunk Upload) - مناسب برای فایل‌های بزرگ +// دریافت هر تکه از ویدیو +router.post( + "/academy/course/creat/video-chunk", + academyController.creatCourseVideoChunk +); + +// ادغام تکه‌ها بعد از اتمام آپلود +router.post( + "/academy/course/creat/video-chunk/merge", + academyController.mergeVideoChunks +); + +// بررسی وضعیت آپلود (برای قابلیت Resume) +router.get("/academy/course/upload-status", academyController.getUploadStatus); + +// ========================================== +// ❤️ مسیرهای لایک و تعامل +// ========================================== + +// لایک کردن محتوای دوره +router.post("/academy/course/like", academyController.likeCourseContent); + +// حذف لایک (دیسلایک) +router.post("/academy/course/dislike", academyController.dontLikeCourseContent); + +// بررسی وضعیت لایک کاربر +router.post("/academy/course/is-like", academyController.isLikeCourseContent); + +// دریافت تعداد لایک‌های یک دوره +router.get( + "/academy/course/likes-count/:courseId", + academyController.getCourseLikesCount +); + +// دریافت لیست دوره‌های لایک شده توسط کاربر +router.get( + "/academy/user/liked-courses", + academyController.getUserLikedCourses +); + +// ========================================== +// 💬 مسیرهای کامنت و نظرات +// ========================================== + +// دریافت تعداد کل کامنت‌های یک دوره +router.get( + "/course/:courseId/comments/count", + academyController.getTotalCommentsCount +); + +// دریافت لیست کامنت‌های یک دوره +router.get("/course/:courseId/comments", academyController.getCourseComments); + +// ایجاد کامنت جدید +router.post("/comment/create", academyController.createComment); + +// تغییر وضعیت کامنت (تایید/رد) +router.patch( + "/comment/:commentId/status", + academyController.updateCommentStatus +); + +// حذف کامنت +router.delete("/comment/:commentId/delete", academyController.deleteComment); + +// ========================================== +// 🛒 مسیرهای دوره‌های خریداری شده +// ========================================== + +// دریافت دوره‌های خریداری شده توسط کاربر جاری +router.get( + "/course/getUserPurchasedCourses", + academyController.getUserPurchasedCourses +); + +// دریافت دوره‌های خریداری شده (با populate - روش بهینه) +router.get( + "/course/getUserPurchasedCoursesWithPopulate", + academyController.getUserPurchasedCoursesWithPopulate +); + +// دریافت همه پرداخت‌های آکادمی +router.get( + "/course/getAllAcademyPayments", + academyController.getAllAcademyPayments +); + +// بررسی خرید دوره توسط کاربر +router.get( + "/course/checkCoursePurchase/:courseId", + academyController.checkCoursePurchase +); + +// ========================================== +// 📊 مسیرهای آمار و گزارشات (STATIC) +// ========================================== + +// آمار پرداخت‌ها +router.get("/payments/stats", academyController.getPaymentStats); + +// آمار دوره‌ها +router.get("/courses/stats", academyController.getCourseStats); + +// آمار دوره‌های خریداری شده +router.get("/purchased/stats", academyController.getPurchasedStats); + +// آمار آکادمی‌ها +router.get("/academies/stats", academyController.getAcademyStats); + +// ========================================== +// ⚙️ مسیرهای تنظیمات (Settings) +// ========================================== + +// دریافت همه تنظیمات +router.get("/settings/all", academyController.getAllSettings); +router.get("/settings", academyController.getAllSettings); + +// به‌روزرسانی همه تنظیمات +router.put("/settings/all", academyController.updateAllSettings); +router.put("/settings", academyController.updateAllSettings); + +// دریافت و ویرایش قیمت دوره‌ها +router.get("/settings/course-prices", academyController.getCoursePrices); +router.put("/settings/course-price", academyController.updateCoursePrice); + +// دریافت و ویرایش مالیات +router.get("/settings/tax", academyController.getTax); +router.put("/settings/tax", academyController.updateTax); + +// ========================================== +// 🏷️ مسیرهای دسته‌بندی آکادمی (Categories) +// ========================================== + +// دریافت لیست دسته‌بندی‌ها (با فیلتر و صفحه‌بندی) +router.get('/categories', academyController.getAll); + +// دریافت درخت دسته‌بندی (ساختار سلسله‌مراتبی) +router.get('/categories/tree', academyController.getTree); + +// دریافت دسته‌بندی‌های ویژه (برای نمایش در هوم پیج) +router.get('/categories/featured', academyController.getFeatured); + +// دریافت دسته‌بندی با اسلاگ (برای سئو و لینک‌های زیبا) +router.get('/categories/slug/:slug', academyController.getBySlug); + +// دریافت یک دسته‌بندی با شناسه +router.get('/categories/:id', academyController.getOne); + +// ایجاد دسته‌بندی جدید +router.post('/categories', academyController.create); + +// ویرایش دسته‌بندی (هم PUT و هم PATCH پشتیبانی می‌شود) +router.put('/categories/:id', academyController.update); +router.patch('/categories/:id', academyController.update); + +// حذف دسته‌بندی (سافت دیلیت - فقط غیرفعال می‌شود) +router.delete('/categories/:id', academyController.remove); + +// حذف فیزیکی دسته‌بندی (به همراه query string permanent=true) +router.delete('/categories/:id/permanent', (req, res) => { + req.query.permanent = 'true'; + academyController.remove(req, res); +}); + +// تغییر وضعیت دسته‌بندی (فعال/غیرفعال) +router.patch('/categories/:id/status', academyController.toggleStatus); + +// افزایش تعداد دوره‌های دسته‌بندی (هر بار یک دوره جدید اضافه می‌شود) +router.post('/categories/:id/increment-count', academyController.incrementCourseCount); + +// ========================================== +// 👑 مسیرهای مدیریتی (پنل ادمین) +// ========================================== + +// ------ مدیریت پرداخت‌ها ------ +router.get("/payments", academyController.getAllPayments); +router.put("/payments/status", academyController.updatePaymentStatus); + +// ------ مدیریت دوره‌ها ------ +router.get("/courses", academyController.getAllCourses); +router.get("/courses/:id", academyController.getCourseById); +router.put("/courses/:id", academyController.updateCourse); +router.post("/courses", academyController.createCourse); +router.put("/academy/courses/status", academyController.updateCourseStatus); +router.delete("/courses/:courseId", academyController.admindeleteCourse); + +// ------ مدیریت دوره‌های خریداری شده ------ +router.get("/purchased", academyController.getAllPurchasedCourses); + +// ------ مدیریت آکادمی‌ها ------ +router.get("/academies", academyController.getAllAcademies); +router.get("/academies/:id", academyController.getAcademyById); +router.put("/academies/:id", academyController.updateAcademy); +router.post("/academies", academyController.createAcademy); +router.put("/academies/status", academyController.updateAcademyStatus); +router.delete("/academies/:id", academyController.deleteAcademy); + +// ========================================== +// 📤 خروجی روت‌ها +// ========================================== + +module.exports = router; \ No newline at end of file diff --git a/public/modstagram-back/routes/application/advertising/index.js b/public/modstagram-back/routes/application/advertising/index.js new file mode 100644 index 0000000..3001fa6 --- /dev/null +++ b/public/modstagram-back/routes/application/advertising/index.js @@ -0,0 +1,45 @@ +const express = require('express') +const blockCheck = require('../../../middlewares/blockCheck') +const { createAdvertisingValidationRules, createAdvertising, getAdvertisingTypes, getAdvertisingCategory, getSingleAdvertising, getAdvertisingFeatures, getAdvertisings, toggleLike, addComment, getComments, rateAdvertising, getUserAdvertisings, editAdvertising, getUserSingleAdvertising, getUserAdvertisingProfile, updateUserAdvertisingProfile, getAdvertisingsWeb, getSingleAdvertisingWeb, getUserAdvertisingProfileWeb } = require('../../../controllers/application/advertising/advertisingController') +const auth = require('../../../middlewares/auth') +const { initiateAdvertisingPayment, handleAdvertisingPaymentCallback, handleAdvertisingRepublishPaymentCallback, republishAdvertisingPayment, handleSuccessfulAdvertisingPayment, handleFailedAdvertisingPayment, handleFailedAdvertisingRepublishPayment, handleSuccessfulAdvertisingRepublishPayment } = require('../../../controllers/application/payment/paymentController') +const { initiateAdvertisingPaymentWeb, handleAdvertisingPaymentCallbackWeb, republishAdvertisingPaymentWeb, handleAdvertisingRepublishPaymentCallbackWeb } = require('../../../controllers/application/payment/paymentControllerWeb') +const router = express.Router() +router.get('/', [auth], getAdvertisings) +router.get('/web', getAdvertisingsWeb) +router.get('/profile', [auth], getUserAdvertisingProfile) +router.get('/profile-web', getUserAdvertisingProfileWeb) +router.patch('/profile', [auth], [blockCheck], updateUserAdvertisingProfile) +router.get('/user-advertising', [auth], getUserAdvertisings) +router.post('/create', [auth], [blockCheck], createAdvertisingValidationRules(), createAdvertising) +router.get('/types', [auth], getAdvertisingTypes) +router.get('/categories', getAdvertisingCategory) +router.get('/features', [auth], getAdvertisingFeatures) +router.get('/get/:advertisingId', [auth], getSingleAdvertising) +router.get('/get/web/:advertisingId', getSingleAdvertisingWeb) +router.get('/get-detail/:advertisingId', [auth], getUserSingleAdvertising) +router.post('/initiate-payment', [auth], [blockCheck], initiateAdvertisingPayment) +router.post('/initiate-payment-web', [auth], [blockCheck], initiateAdvertisingPaymentWeb) +router.post('/republish-payment', [auth], [blockCheck], republishAdvertisingPayment) +router.post('/republish-payment-web', [auth], [blockCheck], republishAdvertisingPaymentWeb) +router.get('/payment', handleAdvertisingPaymentCallback) +router.get('/payment-web', handleAdvertisingPaymentCallbackWeb) +router.get('/republish-verify-payment', handleAdvertisingRepublishPaymentCallback) +router.get('/republish-verify-payment-web', handleAdvertisingRepublishPaymentCallbackWeb) +router.post('/like', [blockCheck], [auth], toggleLike) +router.post('/comment', [blockCheck], [auth], addComment) +router.get('/comments', getComments) +router.post('/rate', [blockCheck], [auth], rateAdvertising) +router.post('/edit/:id', [blockCheck], [auth], editAdvertising) + +// Route for handling successful payment +router.post('/payment-success', handleSuccessfulAdvertisingPayment) +// Route for handling failed payment +router.post('/payment-failed', handleFailedAdvertisingPayment) +// Route for handling successful payment +router.post('/republish-payment-success', handleSuccessfulAdvertisingRepublishPayment) +// Route for handling failed payment +router.post('/republish-payment-failed', handleFailedAdvertisingRepublishPayment) + +module.exports = router +module.exports = router diff --git a/public/modstagram-back/routes/application/city/index.js b/public/modstagram-back/routes/application/city/index.js new file mode 100644 index 0000000..084c42d --- /dev/null +++ b/public/modstagram-back/routes/application/city/index.js @@ -0,0 +1,7 @@ +const express = require('express') +const router = express.Router() +const citysController = require('../../../controllers/application/citysController') + +router.get('/:id', citysController.getCities) + +module.exports = router diff --git a/public/modstagram-back/routes/application/expertise/index.js b/public/modstagram-back/routes/application/expertise/index.js new file mode 100644 index 0000000..fdf4f1d --- /dev/null +++ b/public/modstagram-back/routes/application/expertise/index.js @@ -0,0 +1,6 @@ +const express = require('express') +const { getExpertise } = require('../../../controllers/application/expertise/expertiseController') +const router = express.Router() +router.get('/', getExpertise) + +module.exports = router diff --git a/public/modstagram-back/routes/application/financial/index.js b/public/modstagram-back/routes/application/financial/index.js new file mode 100644 index 0000000..0123e94 --- /dev/null +++ b/public/modstagram-back/routes/application/financial/index.js @@ -0,0 +1,6 @@ +const express = require('express') +const { getFinancial } = require('../../../controllers/application/financial/financialController') +const router = express.Router() +router.get('/', getFinancial) + +module.exports = router diff --git a/public/modstagram-back/routes/application/login/index.js b/public/modstagram-back/routes/application/login/index.js new file mode 100644 index 0000000..6ee30c8 --- /dev/null +++ b/public/modstagram-back/routes/application/login/index.js @@ -0,0 +1,14 @@ +const express = require('express') +const router = express.Router() +const { loginValidationRules, loginUser } = require('../../../controllers/application/login/loginController') +const { verifyUser } = require('../../../controllers/application/login/verifyController') +const { changePasswordUser, changePasswordValidationRules, editChangePasswordUser } = require('../../../controllers/application/login/changePasswordController') +const { loginWithUserName } = require('../../../controllers/application/login/loginWithUserName') + +router.post('/', loginValidationRules(), loginUser) +router.post('/verify', verifyUser) +router.post('/change_password', changePasswordValidationRules(), changePasswordUser) +router.patch('/change_password', changePasswordValidationRules(), editChangePasswordUser) +router.post('/login_username', loginWithUserName) + +module.exports = router diff --git a/public/modstagram-back/routes/application/messages/index.js b/public/modstagram-back/routes/application/messages/index.js new file mode 100644 index 0000000..c74cc8b --- /dev/null +++ b/public/modstagram-back/routes/application/messages/index.js @@ -0,0 +1,6 @@ +const express = require('express') +const { getMessages, getUnreadMessages } = require('../../../controllers/application/messages/messageController') +const router = express.Router() +router.get('/', getMessages) +router.get('/unread', getUnreadMessages) +module.exports = router diff --git a/public/modstagram-back/routes/application/notification/index.js b/public/modstagram-back/routes/application/notification/index.js new file mode 100644 index 0000000..8ef0a3e --- /dev/null +++ b/public/modstagram-back/routes/application/notification/index.js @@ -0,0 +1,6 @@ +const express = require('express') +const { getNotifications, unreadNotifications } = require('../../../controllers/application/notification/notificationController') +const router = express.Router() +router.get('/', getNotifications) +router.get('/unread', unreadNotifications) +module.exports = router diff --git a/public/modstagram-back/routes/application/offers/index.js b/public/modstagram-back/routes/application/offers/index.js new file mode 100644 index 0000000..ebd57e3 --- /dev/null +++ b/public/modstagram-back/routes/application/offers/index.js @@ -0,0 +1,18 @@ +const express = require('express') +const { getUserOffers, getOfferTypes, handleSuccessfulOfferPayment, handleFailedOfferPayment, updateOfferStatus, createOfferComment } = require('../../../controllers/application/offer/offerController') +const { initiateOfferPaymentWeb, handleOfferPaymentCallback } = require('../../../controllers/application/payment/paymentControllerWeb') +const blockCheck = require('../../../middlewares/blockCheck') +const isRegister = require('../../../middlewares/isRegister') +const auth = require('./../../../middlewares/auth') + +const router = express.Router() +router.get('/', getUserOffers) +router.get('/types', [auth], getOfferTypes) +router.post('/update-status', [auth], updateOfferStatus) +router.post('/payment-success', [auth], handleSuccessfulOfferPayment) +router.post('/payment-failed', [auth], handleFailedOfferPayment) +router.post('/comment', [auth], createOfferComment) +router.post('/initiate-payment-web', [auth], [blockCheck], initiateOfferPaymentWeb) +router.get('/payment-web', handleOfferPaymentCallback) + +module.exports = router diff --git a/public/modstagram-back/routes/application/posts/index.js b/public/modstagram-back/routes/application/posts/index.js new file mode 100644 index 0000000..2c8ace0 --- /dev/null +++ b/public/modstagram-back/routes/application/posts/index.js @@ -0,0 +1,204 @@ +const express = require('express'); +const { createPostValidationRules, createPost, getUserPosts, getUserPostsWeb } = require('../../../controllers/application/posts/postController'); +const { toggleLike } = require('../../../controllers/application/posts/likeController'); +const blockCheck = require('../../../middlewares/blockCheck'); +const auth = require('../../../middlewares/auth'); +const isHalfRegister = require('../../../middlewares/isHalfRegister'); +const path = require('path'); +const fs = require('fs'); +const multer = require('multer'); + +console.log('DEBUG: Starting to load routes/posts.js'); + +const ensureDir = (dir) => { + console.log('DEBUG: Ensuring directory exists:', dir); + if (!fs.existsSync(dir)) { + console.log('DEBUG: Directory does not exist, creating:', dir); + fs.mkdirSync(dir, { recursive: true }); + } else { + console.log('DEBUG: Directory already exists:', dir); + } +}; + +const imageDir = path.join(__dirname, '../../../storage/posts/images'); +const videoDir = path.join(__dirname, '../../../storage/posts/videos'); +console.log('DEBUG: imageDir path:', imageDir); +console.log('DEBUG: videoDir path:', videoDir); +ensureDir(imageDir); +ensureDir(videoDir); + +console.log('DEBUG: Setting up multer storage'); + +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + const dir = file.mimetype.startsWith('video/') ? videoDir : imageDir; + console.log('DEBUG: multer destination for file', file.originalname, ':', dir); + cb(null, dir); + }, + filename: (req, file, cb) => { + const filename = `${Date.now()}-${file.originalname}`; + console.log('DEBUG: Generated filename for', file.originalname, ':', filename); + cb(null, filename); + }, +}); + +console.log('DEBUG: Setting up multer instance with limits and filter'); + +const upload = multer({ + storage, + limits: { + fileSize: 100 * 1024 * 1024, // حداکثر 100MB + files: 10, // حداکثر 10 فایل + fieldSize: 1024 * 1024, + fieldNameSize: 100, + }, + fileFilter: (req, file, cb) => { + console.log('DEBUG: Checking file filter for', file.originalname, 'mimetype:', file.mimetype); + if (file.mimetype.startsWith('image/') || file.mimetype.startsWith('video/')) { + console.log('DEBUG: File accepted:', file.originalname); + cb(null, true); + } else { + console.log('DEBUG: File rejected:', file.originalname); + cb(new Error('فقط تصاویر یا ویدئوها مجاز هستند'), false); + } + }, +}).array('post_files', 10); + +const multerErrorHandler = (err, req, res, next) => { + console.log('DEBUG: Request headers:', JSON.stringify(req.headers, null, 2)); + console.log('DEBUG: Request body (raw):', req.body); + console.log('DEBUG: Request files:', req.files || 'No files received'); + if (err instanceof multer.MulterError) { + console.error('DEBUG: Multer error:', err.message, err.code, err.field); + return res.status(400).json({ + error: true, + message: `خطای آپلود: ${err.message} (${err.code})`, + field: err.field, + }); + } else if (err) { + console.error('DEBUG: File filter error:', err.message); + return res.status(400).json({ + error: true, + message: err.message, + }); + } + console.log('DEBUG: Multer processing completed, files:', req.files || 'No files'); + console.log('DEBUG: Request body after multer:', req.body); + next(); +}; + +console.log('DEBUG: Setting up express router'); + +const router = express.Router(); + +// روت اصلی با multipart/form-data +router.post( + '/create', + (req, res, next) => { + console.log('DEBUG: reached auth'); + console.log('DEBUG: Raw request headers:', JSON.stringify(req.headers, null, 2)); + next(); + }, + auth, + (req, res, next) => { + console.log('DEBUG: reached blockCheck'); + next(); + }, + blockCheck, + (req, res, next) => { + console.log('DEBUG: reached isHalfRegister'); + next(); + }, + isHalfRegister, + (req, res, next) => { + console.log('DEBUG: reached multer'); + console.log('DEBUG: Content-Length:', req.headers['content-length']); + console.log('DEBUG: Content-Type:', req.headers['content-type']); + next(); + }, + upload, + multerErrorHandler, + (req, res, next) => { + console.log('DEBUG: reached validation'); + console.log('DEBUG: Parsed files:', req.files || 'No files'); + console.log('DEBUG: Parsed body:', req.body); + next(); + }, + createPostValidationRules(), + (req, res, next) => { + console.log('DEBUG: reached controller'); + next(); + }, + createPost +); + +// روت جدید برای Base64 +router.post( + '/create-base64', + (req, res, next) => { + console.log('DEBUG: reached auth for base64'); + console.log('DEBUG: Raw request headers:', JSON.stringify(req.headers, null, 2)); + next(); + }, + auth, + (req, res, next) => { + console.log('DEBUG: reached blockCheck for base64'); + next(); + }, + blockCheck, + (req, res, next) => { + console.log('DEBUG: reached isHalfRegister for base64'); + next(); + }, + isHalfRegister, + (req, res, next) => { + console.log('DEBUG: Request body (base64):', JSON.stringify(req.body, null, 2)); + next(); + }, + createPostValidationRules(), + async (req, res) => { + try { + const { files, caption } = req.body; + console.log('DEBUG: Received files (base64):', files.length); + console.log('DEBUG: Received caption:', caption); + + // تبدیل Base64 به فایل + const savedFiles = await Promise.all( + files.map(async (file, index) => { + const buffer = Buffer.from(file.data.split(',')[1], 'base64'); + const dir = file.type.startsWith('video/') ? videoDir : imageDir; + const filename = `${Date.now()}-${index}-${file.name}`; + const filePath = path.join(dir, filename); + console.log('DEBUG: Saving file:', filePath); + await fs.promises.writeFile(filePath, buffer); + return { + path: filePath, + filename, + mimetype: file.type, + }; + }) + ); + + // فراخوانی createPost با فرمت مشابه + req.files = savedFiles; + req.body = { caption }; + console.log('DEBUG: Prepared files for createPost:', savedFiles); + console.log('DEBUG: Prepared body for createPost:', req.body); + await createPost(req, res); + } catch (err) { + console.error('DEBUG: Base64 processing error:', err.message); + res.status(400).json({ + error: true, + message: `خطای پردازش فایل‌ها: ${err.message}`, + }); + } + } +); + +router.post('/like', [auth, blockCheck], toggleLike); +router.get('/user-posts', [auth], getUserPosts); +router.get('/user-posts/web', getUserPostsWeb); + +console.log('DEBUG: Finished loading routes/posts.js'); + +module.exports = router; \ No newline at end of file diff --git a/public/modstagram-back/routes/application/profile/index.js b/public/modstagram-back/routes/application/profile/index.js new file mode 100644 index 0000000..2c7bd31 --- /dev/null +++ b/public/modstagram-back/routes/application/profile/index.js @@ -0,0 +1,8 @@ +const express = require('express') +const { getProfile , getUserById} = require('../../../controllers/application/profile/profileController') +const auth = require('../../../middlewares/auth') +const router = express.Router() +router.get('/',[auth], getProfile) +router.get('/:id', getUserById) + +module.exports = router diff --git a/public/modstagram-back/routes/application/projects/index.js b/public/modstagram-back/routes/application/projects/index.js new file mode 100644 index 0000000..d432dca --- /dev/null +++ b/public/modstagram-back/routes/application/projects/index.js @@ -0,0 +1,44 @@ +const express = require('express') +const { createProject, createProjectValidationRules } = require('../../../controllers/application/projects/createProjectController') +const { getProjects, getSingleProjects, getSingleProjectsWeb, getUserProjects, getUserProjectsWeb } = require('../../../controllers/application/projects/getProjectController') +const { getProjectTypes } = require('../../../controllers/application/projects/projectTypesController') +const { initiatePayment, handlePaymentCallback, paymentRequestStepOne, paymentRequestStepTwo, paymentRequestStepAll, paymentRequestStepOneCallback, paymentRequestStepTwoCallback, paymentRequestStepAllCallback, handleSuccessfulPayment, handleFailedPayment } = require('../../../controllers/application/payment/paymentController') +const auth = require('../../../middlewares/auth') +const { requestProjectValidationRules, requestProject, acceptProject, editRequestProject } = require('../../../controllers/application/projects/requestProjectController') +const { editProject, doneProject, cancleProject, editProjectValidationRules, setRateProject, doneProjectWeb } = require('../../../controllers/application/projects/updateProjectController') +const blockCheck = require('../../../middlewares/blockCheck') +const isRegister = require('../../../middlewares/isRegister') +const { initiatePaymentWeb, handlePaymentCallbackWeb, paymentRequestAcceptWeb } = require('../../../controllers/application/payment/paymentControllerWeb') +const router = express.Router() +router.get('/', getProjects) +router.get('/user-projects', [auth], getUserProjects) +router.get('/user-projects/web', getUserProjectsWeb) +router.get('/types', [auth], getProjectTypes) +router.get('/get/:projectId', [auth], getSingleProjects) +router.get('/get/web/:projectId', getSingleProjectsWeb) +router.get('/payment', handlePaymentCallback) +router.get('/payment-web', handlePaymentCallbackWeb) +router.post('/create', [blockCheck], [auth], [isRegister], createProjectValidationRules(), createProject) +router.post('/edit', [blockCheck], [auth], [isRegister], editProjectValidationRules(), editProject) +router.post('/rate', [blockCheck], [auth], [isRegister], setRateProject) +router.post('/initiate-payment', [blockCheck], [isRegister], [auth], initiatePayment) +router.post('/initiate-payment-web', [blockCheck], [isRegister], [auth], initiatePaymentWeb) +router.post('/request', [blockCheck], [isRegister], [auth], requestProjectValidationRules(), requestProject) +router.post('/edit-request', [isRegister], [blockCheck], [auth], requestProjectValidationRules(), editRequestProject) +router.post('/payment-request-step-one', [isRegister], [blockCheck], [auth], paymentRequestStepOne) +router.post('/payment-request-step-one/web', [isRegister], [blockCheck], [auth], paymentRequestAcceptWeb) +router.post('/payment-request-step-two', [isRegister], [blockCheck], [auth], paymentRequestStepTwo) +router.post('/payment-request-all', [isRegister], [blockCheck], [auth], paymentRequestStepAll) +router.get('/payment-request-step-one-callback', paymentRequestStepOneCallback) +router.get('/payment-request-step-two-callback', paymentRequestStepTwoCallback) +router.get('/payment-request-step-all-callback', paymentRequestStepAllCallback) +router.post('/accept', [isRegister], [blockCheck], [auth], acceptProject) +router.post('/done', [isRegister], [auth], doneProject) +router.post('/done/web', [isRegister], [auth], doneProjectWeb) +router.post('/cancle', [isRegister], [blockCheck], [auth], cancleProject) + +// Route for handling successful payment +router.post('/payment-success', handleSuccessfulPayment) +// Route for handling failed payment +router.post('/payment-failed', handleFailedPayment) +module.exports = router diff --git a/public/modstagram-back/routes/application/provinces/index.js b/public/modstagram-back/routes/application/provinces/index.js new file mode 100644 index 0000000..1b346c6 --- /dev/null +++ b/public/modstagram-back/routes/application/provinces/index.js @@ -0,0 +1,7 @@ +const express = require('express') +const router = express.Router() +const provincesController = require('../../../controllers/application/provincesController') + +router.get('/', provincesController.getProvinces) + +module.exports = router diff --git a/public/modstagram-back/routes/application/register/index.js b/public/modstagram-back/routes/application/register/index.js new file mode 100644 index 0000000..9978c9d --- /dev/null +++ b/public/modstagram-back/routes/application/register/index.js @@ -0,0 +1,16 @@ +const express = require('express') +const router = express.Router() +const { registerValidationRules, registerUser } = require('../../../controllers/application/register/registerController') +const { verifyUser } = require('../../../controllers/application/register/verifyController') +const { setUserName, updateUserName } = require('../../../controllers/application/register/usernameController') +const { setUserFullName, setUserFullNameValidationRules } = require('../../../controllers/application/register/userFullNameController') +const { setUserType } = require('../../../controllers/application/register/userTypeController') + +router.post('/', registerValidationRules(), registerUser) +router.post('/verify', verifyUser) +router.post('/username', setUserName) +router.patch('/username', updateUserName) +router.post('/fullname', setUserFullNameValidationRules(), setUserFullName) +router.post('/user_type', setUserType) + +module.exports = router diff --git a/public/modstagram-back/routes/application/search-web/index.js b/public/modstagram-back/routes/application/search-web/index.js new file mode 100644 index 0000000..54f78f6 --- /dev/null +++ b/public/modstagram-back/routes/application/search-web/index.js @@ -0,0 +1,6 @@ +const express = require('express') +const { getSearch } = require('../../../controllers/application/search-web/searchController') +const router = express.Router() +router.get('/', getSearch) + +module.exports = router diff --git a/public/modstagram-back/routes/application/search/index.js b/public/modstagram-back/routes/application/search/index.js new file mode 100644 index 0000000..5db29bc --- /dev/null +++ b/public/modstagram-back/routes/application/search/index.js @@ -0,0 +1,6 @@ +const express = require('express') +const { getSearch } = require('../../../controllers/application/search/searchController') +const router = express.Router() +router.get('/', getSearch) + +module.exports = router diff --git a/public/modstagram-back/routes/application/settings/index.js b/public/modstagram-back/routes/application/settings/index.js new file mode 100644 index 0000000..bff48f0 --- /dev/null +++ b/public/modstagram-back/routes/application/settings/index.js @@ -0,0 +1,6 @@ +const express = require('express') +const { getSetting } = require('../../../controllers/application/settings/settingsController') +const router = express.Router() +router.get('/:key', getSetting) + +module.exports = router diff --git a/public/modstagram-back/routes/application/tickets/index.js b/public/modstagram-back/routes/application/tickets/index.js new file mode 100644 index 0000000..5174c7e --- /dev/null +++ b/public/modstagram-back/routes/application/tickets/index.js @@ -0,0 +1,9 @@ +const express = require('express') +const { getUserTickets, createTicket, addUserMessageToTicket, getTicketMessages } = require('../../../controllers/application/tickets/ticketsController') +const router = express.Router() +router.get('/', getUserTickets) +router.get('/messages', getTicketMessages) +router.post('/create', createTicket) +router.post('/message', addUserMessageToTicket) + +module.exports = router diff --git a/public/modstagram-back/routes/application/users/index.js b/public/modstagram-back/routes/application/users/index.js new file mode 100644 index 0000000..4442dc9 --- /dev/null +++ b/public/modstagram-back/routes/application/users/index.js @@ -0,0 +1,22 @@ +const express = require('express') +const { getUsers, getSingleUser, blockUser, unblockUser, getComments,createLicense, getAllLicenses,updateLicenseConfirmation, getLicenseByUserId, inviteEmployer, getUserContactInfo, getPostsWeb, getSingleUserWeb, createUserComment } = require('../../../controllers/application/users/getUserController') +const blockCheck = require('../../../middlewares/blockCheck') +const isRegister = require('../../../middlewares/isRegister') +const auth = require('../../../middlewares/auth') +const router = express.Router() +router.get('/', [auth], getUsers) +router.get('/web', getPostsWeb) +router.get('/get', [auth], getSingleUser) +router.get('/get/web', getSingleUserWeb) +router.post('/block', [auth], [isRegister], [blockCheck], blockUser) +router.post('/unblock', [auth], [isRegister], [blockCheck], unblockUser) +router.get('/comments', [auth], getComments) +router.post('/comments', [auth], [isRegister], [blockCheck], createUserComment) +router.get('/invite-employer', [auth], [isRegister], [blockCheck], inviteEmployer) +router.get('/contact-info', [auth], getUserContactInfo) +router.get('/License', getAllLicenses) +router.get('/License/:userId', getLicenseByUserId) +router.post('/License', createLicense) +router.put('/License/:userId', updateLicenseConfirmation) + +module.exports = router diff --git a/public/modstagram-back/routes/application/verify/index.js b/public/modstagram-back/routes/application/verify/index.js new file mode 100644 index 0000000..8e7fc8d --- /dev/null +++ b/public/modstagram-back/routes/application/verify/index.js @@ -0,0 +1,38 @@ +const express = require('express') +const { setProfileImage, updateProfileImage } = require('../../../controllers/application/verify/setProfileImageController') +const { setExpertise, updateExpertise } = require('../../../controllers/application/verify/expertiseController') +const { setGender } = require('../../../controllers/application/verify/genderController') +const { setSizes, updateSizes } = require('../../../controllers/application/verify/sizesController') +const { setColors, updateColors } = require('../../../controllers/application/verify/colorsController') +const { setCooperationType, updateCooperationType } = require('../../../controllers/application/verify/cooperationTypeController') +const { setConversation, updateConversation } = require('../../../controllers/application/verify/conversationController') +const { saveAuth, saveAuthValidationRules, updateShaba } = require('../../../controllers/application/verify/authController') +const { setAddress, updateAddress } = require('../../../controllers/application/verify/addressController') +const { setNationalCardImage } = require('../../../controllers/application/verify/setNationalCardImageController') +const blockCheck = require('../../../middlewares/blockCheck') +const auth = require('../../../middlewares/auth') +const { setServices, updateServices } = require('../../../controllers/application/verify/servicesController') +const router = express.Router() + +router.post('/profile_image', setProfileImage) +router.patch('/profile_image', [blockCheck], [auth], updateProfileImage) +router.post('/expertise', setExpertise) +router.patch('/expertise', [blockCheck], [auth], updateExpertise) +router.post('/gender', setGender) +router.post('/sizes', setSizes) +router.patch('/sizes', [blockCheck], [auth], updateSizes) +router.post('/services', setServices) +router.patch('/services', [blockCheck], [auth], updateServices) +router.post('/colors', setColors) +router.patch('/colors', [blockCheck], [auth], updateColors) +router.post('/cooperation_type', setCooperationType) +router.patch('/cooperation_type', [blockCheck], [auth], updateCooperationType) +router.post('/conversation', setConversation) +router.patch('/conversation', [blockCheck], [auth], updateConversation) +router.post('/auth', saveAuthValidationRules(), saveAuth) +router.patch('/shaba', [blockCheck], [auth], updateShaba) +router.post('/address', setAddress) +router.patch('/address', [blockCheck], [auth], updateAddress) +router.post('/national_card_image', setNationalCardImage) + +module.exports = router diff --git a/public/modstagram-back/routes/application/version/index.js b/public/modstagram-back/routes/application/version/index.js new file mode 100644 index 0000000..ab8eaec --- /dev/null +++ b/public/modstagram-back/routes/application/version/index.js @@ -0,0 +1,6 @@ +const express = require('express') +const { getVersion } = require('../../../controllers/application/version/versionController') +const router = express.Router() +router.get('/', getVersion) + +module.exports = router diff --git a/public/modstagram-back/routes/application/workroom/index.js b/public/modstagram-back/routes/application/workroom/index.js new file mode 100644 index 0000000..f7d6cba --- /dev/null +++ b/public/modstagram-back/routes/application/workroom/index.js @@ -0,0 +1,8 @@ +const express = require('express') +const { getProjects, getSingleProject, getProjectRequests } = require('../../../controllers/application/workroom/workroomController') +const router = express.Router() +router.get('/', getProjects) +router.get('/get', getSingleProject) +router.get('/get-requests/:projectId', getProjectRequests) + +module.exports = router diff --git a/public/modstagram-back/routes/index.js b/public/modstagram-back/routes/index.js new file mode 100644 index 0000000..ea419b6 --- /dev/null +++ b/public/modstagram-back/routes/index.js @@ -0,0 +1,77 @@ +const registerRouter = require('./application/register') +const loginRouter = require('./application/login') +const verifyRouter = require('./application/verify') +const provincesRouter = require('./application/provinces') +const citiesRouter = require('./application/city') +const projectsRouter = require('./application/projects') +const usersRouter = require('./application/users') +const postsRouter = require('./application/posts') +const expertiseRouter = require('./application/expertise') +const profileRouter = require('./application/profile') +const workroomRouter = require('./application/workroom') +const messagesRouter = require('./application/messages') +const searchRouter = require('./application/search') +const searchRouterWeb = require('./application/search-web') +const financialRouter = require('./application/financial') +const notificationRouter = require('./application/notification') +const ticketsRouter = require('./application/tickets') +const advertisingRouter = require('./application/advertising') +const settingsRouter = require('./application/settings') +const versionRouter = require('./application/version') +const offerRouter = require('./application/offers') +const academyRoute = require('./application/academy') + +const projectsPanelRouter = require('./panel/projects') +const postsPanelRouter = require('./panel/posts') +const expertisePanelRouter = require('./panel/expertise') +const loginPanelRouter = require('./panel/login') +const usersPanelRouter = require('./panel/users') +const ticketsPanelRouter = require('./panel/tickets') +const financialPanelRouter = require('./panel/financial') +const commentsPanelRouter = require('./panel/comments') +const advertisingPanelRouter = require('./panel/advertising') +const shopsPanelRouter = require('./panel/shops') +const settingsPanelRouter = require('./panel/settings') +const versionPanelRouter = require('./panel/version') + +const auth = require('../middlewares/auth') +const adminAuth = require('../middlewares/adminAuth') +module.exports = (app) => { + // App + app.use('/api/v1/register', registerRouter) + app.use('/api/v1/login', loginRouter) + app.use('/api/v1/verify', [auth], verifyRouter) + app.use('/api/v1/provinces', provincesRouter) + app.use('/api/v1/cities', citiesRouter) + app.use('/api/v1/projects', projectsRouter) + app.use('/api/v1/users', usersRouter) + app.use('/api/v1/posts', postsRouter) + app.use('/api/v1/expertise', expertiseRouter) + app.use('/api/v1/profile', profileRouter) + app.use('/api/v1/workroom', [auth], workroomRouter) + app.use('/api/v1/messages', [auth], messagesRouter) + app.use('/api/v1/notifications', [auth], notificationRouter) + app.use('/api/v1/search', [auth], searchRouter) + app.use('/api/v1/search-web', searchRouterWeb) + app.use('/api/v1/financial', [auth], financialRouter) + app.use('/api/v1/tickets', [auth], ticketsRouter) + app.use('/api/v1/offers', offerRouter) + app.use('/api/v1/advertising', advertisingRouter) + app.use('/api/v1/settings', settingsRouter) + app.use('/api/v1/version', versionRouter) + app.use('/api/v1/academy', academyRoute) + + // Panel + app.use('/api/v1/panel/login', loginPanelRouter) + app.use('/api/v1/panel/users', usersPanelRouter) + app.use('/api/v1/panel/projects', [adminAuth], projectsPanelRouter) + app.use('/api/v1/panel/posts', [adminAuth], postsPanelRouter) + app.use('/api/v1/panel/expertise', [adminAuth], expertisePanelRouter) + app.use('/api/v1/panel/tickets', [adminAuth], ticketsPanelRouter) + app.use('/api/v1/panel/financial', [adminAuth], financialPanelRouter) + app.use('/api/v1/panel/comments', [adminAuth], commentsPanelRouter) + app.use('/api/v1/panel/advertising', [adminAuth], advertisingPanelRouter) + app.use('/api/v1/panel/shops', [adminAuth], shopsPanelRouter) + app.use('/api/v1/panel/settings', [adminAuth], settingsPanelRouter) + app.use('/api/v1/panel/version', [adminAuth], versionPanelRouter) +} diff --git a/public/modstagram-back/routes/panel/advertising/index.js b/public/modstagram-back/routes/panel/advertising/index.js new file mode 100644 index 0000000..34a7a0b --- /dev/null +++ b/public/modstagram-back/routes/panel/advertising/index.js @@ -0,0 +1,22 @@ +const express = require('express') +const { getAdvertisings, getSingleAdvertising, acceptAdvertising, rejectAdvertising, getAdvertisingCategories, getAdvertisingCategoryById,createAdvertisingCategory , deleteAdvertisingCategory } = require('../../../controllers/panel/advertising/advertisingController') +const { getAdvertisingComments, getAdvertisingCommentDetail, acceptAdvertisingComment } = require('../../../controllers/panel/comments/advertisingCommentController') +const router = express.Router() +router.get('/', getAdvertisings) +router.get('/detail', getSingleAdvertising) +router.post('/accept', acceptAdvertising) +router.post('/reject', rejectAdvertising) + +router.get('/comments', getAdvertisingComments) +router.get('/comments/detail', getAdvertisingCommentDetail) +router.post('/comments/accept', acceptAdvertisingComment) + +router.post('/advertising-categories', createAdvertisingCategory) +router.delete('/advertising-categories/:id', deleteAdvertisingCategory) +// لیست دسته‌بندی‌ها (پشتیبانی از query params) +router.get('/advertising-categories', getAdvertisingCategories); + +// گرفتن یک دسته‌بندی با id +router.get('/advertising-categories/:id', getAdvertisingCategoryById); + +module.exports = router diff --git a/public/modstagram-back/routes/panel/comments/index.js b/public/modstagram-back/routes/panel/comments/index.js new file mode 100644 index 0000000..e64028d --- /dev/null +++ b/public/modstagram-back/routes/panel/comments/index.js @@ -0,0 +1,8 @@ +const express = require('express') +const { acceptComment, getComments, getCommentDetail } = require('../../../controllers/panel/comments/commentController') +const router = express.Router() +router.get('/', getComments) +router.get('/detail', getCommentDetail) +router.post('/accept', acceptComment) + +module.exports = router diff --git a/public/modstagram-back/routes/panel/expertise/index.js b/public/modstagram-back/routes/panel/expertise/index.js new file mode 100644 index 0000000..56e8dfe --- /dev/null +++ b/public/modstagram-back/routes/panel/expertise/index.js @@ -0,0 +1,9 @@ +const express = require('express') +const { createExpertise, createSubExpertise, getExpertise, editExpertise } = require('../../../controllers/panel/expertise/expertiseController') +const router = express.Router() +router.get('/', getExpertise) +router.post('/create', createExpertise) +router.post('/create/sub', createSubExpertise) +router.put('/update/:id', editExpertise) + +module.exports = router diff --git a/public/modstagram-back/routes/panel/financial/index.js b/public/modstagram-back/routes/panel/financial/index.js new file mode 100644 index 0000000..65f8f60 --- /dev/null +++ b/public/modstagram-back/routes/panel/financial/index.js @@ -0,0 +1,7 @@ +const express = require('express') +const { getFinancial, getFinancialDetail } = require('../../../controllers/panel/financial/financialController') +const router = express.Router() +router.get('/', getFinancial) +router.get('/detail', getFinancialDetail) + +module.exports = router diff --git a/public/modstagram-back/routes/panel/login/index.js b/public/modstagram-back/routes/panel/login/index.js new file mode 100644 index 0000000..58adb2e --- /dev/null +++ b/public/modstagram-back/routes/panel/login/index.js @@ -0,0 +1,8 @@ +const express = require('express') +const router = express.Router() +const { adminLogin, changePassword } = require('../../../controllers/panel/login/loginController') +const adminAuth = require('../../../middlewares/adminAuth') +router.post('/', adminLogin) +router.post('/change-password', [adminAuth], changePassword) + +module.exports = router diff --git a/public/modstagram-back/routes/panel/posts/index.js b/public/modstagram-back/routes/panel/posts/index.js new file mode 100644 index 0000000..5b8d4f7 --- /dev/null +++ b/public/modstagram-back/routes/panel/posts/index.js @@ -0,0 +1,8 @@ +const express = require('express') +const { acceptPost, getPosts, getPostDetail } = require('../../../controllers/panel/posts/postController') +const router = express.Router() +router.get('/', getPosts) +router.get('/detail', getPostDetail) +router.post('/accept', acceptPost) + +module.exports = router diff --git a/public/modstagram-back/routes/panel/projects/index.js b/public/modstagram-back/routes/panel/projects/index.js new file mode 100644 index 0000000..61c9f14 --- /dev/null +++ b/public/modstagram-back/routes/panel/projects/index.js @@ -0,0 +1,11 @@ +const express = require('express') +const { createProjectTypes, getProjectTypes } = require('../../../controllers/panel/projects/projectTypesController') +const { getProjects, getProjectDetails, acceptProject, rejectProject } = require('../../../controllers/panel/projects/projectController') +const router = express.Router() +router.get('/', getProjects) +router.get('/detail', getProjectDetails) +router.post('/accept', acceptProject) +router.post('/reject', rejectProject) +router.get('/types', getProjectTypes) +router.post('/types/create', createProjectTypes) +module.exports = router diff --git a/public/modstagram-back/routes/panel/settings/index.js b/public/modstagram-back/routes/panel/settings/index.js new file mode 100644 index 0000000..aebc745 --- /dev/null +++ b/public/modstagram-back/routes/panel/settings/index.js @@ -0,0 +1,7 @@ +const express = require('express') +const { getSetting, updateSetting } = require('../../../controllers/panel/settings/settingsController') +const router = express.Router() +router.get('/:key', getSetting) +router.put('/:key', updateSetting) + +module.exports = router diff --git a/public/modstagram-back/routes/panel/shops/index.js b/public/modstagram-back/routes/panel/shops/index.js new file mode 100644 index 0000000..bbeb7d6 --- /dev/null +++ b/public/modstagram-back/routes/panel/shops/index.js @@ -0,0 +1,8 @@ +const express = require('express') +const { getShops, getShopDetail, updateShop } = require('../../../controllers/panel/shops/shopsController') +const router = express.Router() +router.get('/', getShops) +router.get('/detail', getShopDetail) +router.put('/update', updateShop) + +module.exports = router diff --git a/public/modstagram-back/routes/panel/tickets/index.js b/public/modstagram-back/routes/panel/tickets/index.js new file mode 100644 index 0000000..08c12f0 --- /dev/null +++ b/public/modstagram-back/routes/panel/tickets/index.js @@ -0,0 +1,9 @@ +const express = require('express') +const { addAdminMessageToTicket, getAllTickets, getTicketMessages, closeTicket } = require('../../../controllers/panel/tickets/ticketsController') +const router = express.Router() +router.get('/', getAllTickets) +router.get('/messages', getTicketMessages) +router.post('/message', addAdminMessageToTicket) +router.post('/close', closeTicket) + +module.exports = router diff --git a/public/modstagram-back/routes/panel/users/index.js b/public/modstagram-back/routes/panel/users/index.js new file mode 100644 index 0000000..d353f39 --- /dev/null +++ b/public/modstagram-back/routes/panel/users/index.js @@ -0,0 +1,12 @@ +const express = require('express') +const { getUsers, getUserDetail,changePass, updateUser, verifyUser, rejectUser, updateUserStatus } = require('../../../controllers/panel/users/usersController') +const router = express.Router() +router.get('/', getUsers) +router.post('/change-password', changePass) +router.get('/detail', getUserDetail) +router.put('/update', updateUser) +router.post('/verify', verifyUser) +router.post('/reject', rejectUser) +router.post('/update-status', updateUserStatus); + +module.exports = router diff --git a/public/modstagram-back/routes/panel/version/index.js b/public/modstagram-back/routes/panel/version/index.js new file mode 100644 index 0000000..c726f6a --- /dev/null +++ b/public/modstagram-back/routes/panel/version/index.js @@ -0,0 +1,7 @@ +const express = require('express') +const { getVersion, upsertVersion } = require('../../../controllers/panel/version/versionController') +const router = express.Router() +router.get('/', getVersion) +router.post('/', upsertVersion) + +module.exports = router diff --git a/public/modstagram-back/sample_env b/public/modstagram-back/sample_env new file mode 100644 index 0000000..cc35c85 --- /dev/null +++ b/public/modstagram-back/sample_env @@ -0,0 +1,67 @@ + + # # App + # APP_PORT = 8000 + # APP_URL=http://localhost:8000/api/v1 + # APP_SITE=http://localhost:3001 + # APP_SECRET=c15a74aaa7dc85814cbe4d84e56e366e0c2025bad8b8b39eefa704b302fa7991 + # SMS_SECRET=eGG6ub8pDcaNWqgt + # SMS_VERIFY_KEY=2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt + # MERCHENT_CODE=c7c41e8a-918f-4741-bcd5-58f3bc51db73 + # # Mongo + # MONGO_HOST=localhost + # MONGO_DBNAME=modstagram + # MONGO_USERNAME= + # MONGO_PASSWORD= + # MONGO_PORT=27017 + + + # App + APP_PORT=3000 +APP_URL=https://app.modstagram.ir/api/v1 +APP_SITE=https://modstagram.com +APP_SITE_CallBack=https://modstagram.com/api/v1 +APP_SECRET=c15a74aaa7dc85814cbe4d84e56e366e0c2025bad8b8b39eefa704b302fa7991 +DATABASE_URL=mongodb://root:X9vLm2QrT8pS@localhost:27017/modstagram?authSource=admin +SMS_SECRET=eGG6ub8pDcaNWqgt +SMS_VERIFY_KEY=2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt +MERCHENT_CODE=c7c41e8a-918f-4741-bcd5-58f3bc51db73 +ZARINPAL_MERCHANT_ID=c7c41e8a-918f-4741-bcd5-58f3bc51db73 +MONGO_HOST=localhost +MONGO_DBNAME=modstagram +MONGO_USERNAME=root +MONGO_PASSWORD=X9vLm2QrT8pS +MONGO_PORT=27017 +NODE_ENV=production + + # # App + # APP_PORT = 8000 + # APP_URL=http://localhost:8000/api/v1 + # APP_SECRET=c15a74aaa7dc85814cbe4d84e56e366e0c2025bad8b8b39eefa704b302fa7991 + # SMS_SECRET=eGG6ub8pDcaNWqgt + # SMS_VERIFY_KEY=2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt + # MERCHENT_CODE=c7c41e8a-918f-4741-bcd5-58f3bc51db73 + # # Mongo + # MONGO_HOST=localhost + # MONGO_DBNAME=modstagram + # MONGO_USERNAME= + # MONGO_PASSWORD= + # MONGO_PORT=27017 + + + # App + # APP_PORT=3000 + # APP_URL=https://app.modstagram.ir/api/v1 + # APP_SITE=https://modstagram.com + # APP_SECRET=c15a74aaa7dc85814cbe4d84e56e366e0c2025bad8b8b39eefa704b302fa7991 + # DATABASE_URL=mongodb://root:KSDfEFklTjjO9KvOmSYlLtjw@modstagramdb:27017/my-app?authSource=admin + # SMS_SECRET=eGG6ub8pDcaNWqgt + # SMS_VERIFY_KEY=2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt + # MERCHENT_CODE=c7c41e8a-918f-4741-bcd5-58f3bc51db73 + # Mongo + # MONGO_HOST=localhost + # MONGO_DBNAME=modstagram + # MONGO_USERNAME= + # MONGO_PASSWORD= + # MONGO_PORT=27017 + # NODE_ENV=production + \ No newline at end of file diff --git a/public/modstagram-back/server.js b/public/modstagram-back/server.js new file mode 100644 index 0000000..a3abc81 --- /dev/null +++ b/public/modstagram-back/server.js @@ -0,0 +1,3 @@ +require('dotenv').config() +const bootApplication = require('./index') +bootApplication(process.env.APP_PORT) diff --git a/public/modstagram-back/services/AdvertisingCron.js b/public/modstagram-back/services/AdvertisingCron.js new file mode 100644 index 0000000..8e51b70 --- /dev/null +++ b/public/modstagram-back/services/AdvertisingCron.js @@ -0,0 +1,44 @@ +const cron = require('node-cron') +const AdvertisingModel = require('../models/AdvertisingModel') +const NotificationModel = require('../models/NotificationModel') + +// تابع برای به‌روزرسانی تبلیغات منقضی شده +const updateExpiredAdvertisings = async () => { + const now = new Date() + const oneMonthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000) + + try { + const expiredAds = await AdvertisingModel.find({ + status: 'accepted', + acceptedAt: { $lte: oneMonthAgo } + }) + + for (const ad of expiredAds) { + ad.status = 'expired' + ad.payment_status = null + await ad.save() + + // ایجاد و ذخیره نوتیفیکیشن + const notification = new NotificationModel({ + user_id: ad.creator_id, + project_post_id: ad._id, + type: 'vitrine', + title: 'انقضای ویترین', + description: `ویترین شما با عنوان: ${ad.title} منقضی شد ` + }) + await notification.save() + } + + console.log(`Updated ${expiredAds.length} expired advertisings successfully`) + } catch (error) { + console.error('Error updating expired advertisings:', error) + } +} + +// تنظیم کرون جاب برای اجرای هر ساعت +cron.schedule('0 * * * *', () => { + console.log('Running cron job to update expired advertisings') + updateExpiredAdvertisings() +}) + +module.exports = updateExpiredAdvertisings diff --git a/public/modstagram-back/services/ProjectCron.js b/public/modstagram-back/services/ProjectCron.js new file mode 100644 index 0000000..f2cfedb --- /dev/null +++ b/public/modstagram-back/services/ProjectCron.js @@ -0,0 +1,44 @@ +const cron = require('node-cron') +const ProjectModel = require('../models/ProjectModel') +const NotificationModel = require('../models/NotificationModel') + +// تابع برای به‌روزرسانی پروژه‌های منقضی شده +const updateExpiredProjects = async () => { + const now = new Date() + const oneMonthAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000) + + try { + // جستجوی پروژه‌های منقضی شده که هنوز به‌روزرسانی نشده‌اند + const expiredProjects = await ProjectModel.find({ + isExpired: false, // فقط پروژه‌هایی که هنوز منقضی نشده‌اند + acceptedAt: { $lte: oneMonthAgo } // بر اساس تاریخ انقضا + }) + + for (const project of expiredProjects) { + project.isExpired = true // تنظیم وضعیت منقضی شده + await project.save() + + // ایجاد و ذخیره نوتیفیکیشن + const notification = new NotificationModel({ + user_id: project.creator_id, + project_post_id: project._id, + type: 'project', + title: 'انقضای پروژه', + description: `پروژه شما با عنوان: ${project.title} منقضی شد.` + }) + await notification.save() + } + + console.log(`Updated ${expiredProjects.length} expired projects successfully`) + } catch (error) { + console.error('Error updating expired projects:', error) + } +} + +// تنظیم کرون جاب برای اجرای هر ساعت +cron.schedule('0 * * * *', () => { + console.log('Running cron job to update expired projects') + updateExpiredProjects() +}) + +module.exports = updateExpiredProjects diff --git a/public/modstagram-back/services/TokenService.js b/public/modstagram-back/services/TokenService.js new file mode 100644 index 0000000..49404d5 --- /dev/null +++ b/public/modstagram-back/services/TokenService.js @@ -0,0 +1,13 @@ +const jwt = require('jsonwebtoken') + +exports.sign = (data) => { + return jwt.sign(data, process.env.APP_SECRET) +} +exports.verify = (token) => { + try { + jwt.verify(token, process.env.APP_SECRET) + return true + } catch (error) { + return false + } +} diff --git a/public/modstagram-back/webpack b/public/modstagram-back/webpack new file mode 100644 index 0000000..e69de29 diff --git a/public/modstagram-back/webpack.config.js b/public/modstagram-back/webpack.config.js new file mode 100644 index 0000000..938a0f6 --- /dev/null +++ b/public/modstagram-back/webpack.config.js @@ -0,0 +1,12 @@ +const path = require('path') + +module.exports = { + mode: 'production', + entry: './server.js', + output: { + path: path.join(__dirname, 'dist'), + publicPath: '/', + filename: 'final.js' + }, + target: 'node' +} diff --git a/public/modstagram_panel/.gitignore b/public/modstagram_panel/.gitignore new file mode 100644 index 0000000..4d29575 --- /dev/null +++ b/public/modstagram_panel/.gitignore @@ -0,0 +1,23 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/public/modstagram_panel/README.md b/public/modstagram_panel/README.md new file mode 100644 index 0000000..58beeac --- /dev/null +++ b/public/modstagram_panel/README.md @@ -0,0 +1,70 @@ +# Getting Started with Create React App + +This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). + +## Available Scripts + +In the project directory, you can run: + +### `npm start` + +Runs the app in the development mode.\ +Open [http://localhost:3000](http://localhost:3000) to view it in your browser. + +The page will reload when you make changes.\ +You may also see any lint errors in the console. + +### `npm test` + +Launches the test runner in the interactive watch mode.\ +See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. + +### `npm run build` + +Builds the app for production to the `build` folder.\ +It correctly bundles React in production mode and optimizes the build for the best performance. + +The build is minified and the filenames include the hashes.\ +Your app is ready to be deployed! + +See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. + +### `npm run eject` + +**Note: this is a one-way operation. Once you `eject`, you can't go back!** + +If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. + +Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. + +You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. + +## Learn More + +You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). + +To learn React, check out the [React documentation](https://reactjs.org/). + +### Code Splitting + +This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) + +### Analyzing the Bundle Size + +This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) + +### Making a Progressive Web App + +This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) + +### Advanced Configuration + +This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) + +### Deployment + +This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) + +### `npm run build` fails to minify + +This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) diff --git a/public/modstagram_panel/package-lock.json b/public/modstagram_panel/package-lock.json new file mode 100644 index 0000000..0a77ce0 --- /dev/null +++ b/public/modstagram_panel/package-lock.json @@ -0,0 +1,19096 @@ +{ + "name": "modstagram_panel", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "modstagram_panel", + "version": "0.1.0", + "dependencies": { + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "axios": "^1.6.8", + "js-cookie": "^3.0.5", + "moment-jalaali": "^0.10.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-hot-toast": "^2.4.1", + "react-icons": "^5.5.0", + "react-modal": "^3.16.1", + "react-multi-date-picker": "^4.5.2", + "react-quill": "^2.0.0", + "react-router-dom": "^6.23.1", + "react-scripts": "5.0.1", + "web-vitals": "^2.1.4", + "yup": "^1.4.0" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "tailwindcss": "^3.4.3" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.4.tgz", + "integrity": "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==" + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@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/eslint-parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.5.tgz", + "integrity": "sha512-fcdRcWahONYo+JRnJg1/AekOacGvKx12Gu0qXJXFi2WBqQA1i7+O5PaxRB7kxE/Op94dExnCiiar6T09pvdHpA==", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@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-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.10" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", + "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", + "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", + "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-decorators": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.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==", + "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==", + "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==", + "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==", + "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-decorators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", + "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.27.1.tgz", + "integrity": "sha512-p9OkPbZ5G7UT1MofwYFigGebnrzGJacoBSQM0/6bi/PUMVE+qlWDD/OalvQKbwgQzU6dl0xAv6r4X7Jme0RYxA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "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==", + "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==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "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==", + "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==", + "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==", + "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==", + "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==", + "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==", + "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==", + "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==", + "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.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz", + "integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", + "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz", + "integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz", + "integrity": "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-flow": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz", + "integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", + "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", + "dependencies": { + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", + "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz", + "integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.27.1.tgz", + "integrity": "sha512-edoidOjl/ZxvYo4lSBOQGDSyToYVkTAwyVoa2tkuYTSmjrB1+uAedoL5iROVLXkxH+vRgA7uP4tMg2pUJpZ3Ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz", + "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", + "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", + "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", + "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", + "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.5.tgz", + "integrity": "sha512-20NUVgOrinudkIBzQ2bNxP08YpKprUkRTiRSd2/Z5GOdPImJGkoN4Z7IQe1T5AdyKI1i5L6RBmluqdSzvaq9/w==", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", + "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.5.tgz", + "integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==", + "dependencies": { + "@babel/compat-data": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.5", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.4", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/plugin-transform-exponentiation-operator": "^7.28.5", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.5", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.28.5", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.28.4", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.28.5", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.4", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.28.5.tgz", + "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.28.0", + "@babel/plugin-transform-react-jsx": "^7.27.1", + "@babel/plugin-transform-react-jsx-development": "^7.27.1", + "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz", + "integrity": "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "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==" + }, + "node_modules/@csstools/normalize.css": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz", + "integrity": "sha512-YAYeJ+Xqh7fUou1d1j9XHl44BmsuThiTr4iNrgCQ3J27IbhXsxXDGZ1cXv8Qvs99d4rBbLiSKy3+WZiet32PcQ==" + }, + "node_modules/@csstools/postcss-cascade-layers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", + "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", + "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.10" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/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==" + }, + "node_modules/@eslint/eslintrc/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==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead" + }, + "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==", + "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/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/environment/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/environment/node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "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": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/fake-timers/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/fake-timers/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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==", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/globals/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/globals/node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/reporters/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/source-map/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/test-result/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/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==" + }, + "node_modules/@jest/transform/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@jest/transform/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@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/@jest/types/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "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==", + "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==", + "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==", + "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==" + }, + "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==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/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==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.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==", + "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==", + "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==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.17.tgz", + "integrity": "sha512-tXDyE1/jzFsHXjhRZQ3hMl0IVhYe5qula43LDWIhVfjp9G/nT5OQY5AORVOrkEGAUltBJOfOWeETbmhm6kHhuQ==", + "dependencies": { + "ansi-html": "^0.0.9", + "core-js-pure": "^3.23.3", + "error-stack-parser": "^2.0.6", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.4", + "schema-utils": "^4.2.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "@types/webpack": "4.x || 5.x", + "react-refresh": ">=0.10.0 <1.0.0", + "sockjs-client": "^1.4.0", + "type-fest": ">=0.17.0 <5.0.0", + "webpack": ">=4.43.0 <6.0.0", + "webpack-dev-server": "3.x || 4.x || 5.x", + "webpack-hot-middleware": "2.x", + "webpack-plugin-serve": "0.x || 1.x" + }, + "peerDependenciesMeta": { + "@types/webpack": { + "optional": true + }, + "sockjs-client": { + "optional": true + }, + "type-fest": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + }, + "webpack-hot-middleware": { + "optional": true + }, + "webpack-plugin-serve": { + "optional": true + } + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.1.tgz", + "integrity": "sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", + "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", + "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==" + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "dependencies": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "dependencies": { + "@babel/types": "^7.12.6" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "dependencies": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz", + "integrity": "sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==", + "dependencies": { + "@adobe/css-tools": "^4.0.1", + "@babel/runtime": "^7.9.2", + "@types/testing-library__jest-dom": "^5.9.1", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.5.6", + "lodash": "^4.17.15", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=8", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/react": { + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-13.4.0.tgz", + "integrity": "sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.5.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@testing-library/react/node_modules/@testing-library/dom": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", + "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@testing-library/react/node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/@testing-library/react/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/react/node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@testing-library/user-event": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", + "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==" + }, + "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==", + "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==", + "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==", + "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==", + "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==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dependencies": { + "@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==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.12", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz", + "integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==", + "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==", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.0.tgz", + "integrity": "sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.7", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.7.tgz", + "integrity": "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "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==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.17", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", + "dependencies": { + "@types/node": "*" + } + }, + "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==" + }, + "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==", + "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==", + "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==", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/jest/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@types/jest/node_modules/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==" + }, + "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==" + }, + "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==" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/node": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.1.tgz", + "integrity": "sha512-czWPzKIAXucn9PtsttxmumiQ9N0ok9FrBwgRWrwmVLlp86BrMExzvXRLFYRJ+Ex3g6yqj+KuaxfX1JTgV2lpfg==", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", + "dependencies": { + "@types/node": "*" + } + }, + "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==" + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "peer": true + }, + "node_modules/@types/q": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", + "integrity": "sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==" + }, + "node_modules/@types/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==" + }, + "node_modules/@types/quill": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz", + "integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==", + "dependencies": { + "parchment": "^1.1.2" + } + }, + "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==" + }, + "node_modules/@types/react": { + "version": "18.3.27", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", + "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dependencies": { + "@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==" + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "5.14.9", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz", + "integrity": "sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==", + "dependencies": { + "@types/jest": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dependencies": { + "@types/node": "*" + } + }, + "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==", + "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==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dependencies": { + "@typescript-eslint/utils": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/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==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==" + }, + "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==", + "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==" + }, + "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==" + }, + "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==" + }, + "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==", + "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==" + }, + "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==", + "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==", + "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==", + "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==" + }, + "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==", + "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==", + "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==", + "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==", + "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==", + "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==" + }, + "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==" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "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==", + "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==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "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==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "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==" + }, + "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==", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "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==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz", + "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "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==", + "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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "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==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "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==", + "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-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "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==", + "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==", + "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==", + "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==", + "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.reduce": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.8.tgz", + "integrity": "sha512-DwuEqgXFBwbmZSRqt3BpQigWNUoqw9Ml2dTWdF3B2zQlQX4OeUE0zyuzX0fX0IbTvjdkZbcBTU3idgpO78qkTw==", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-array-method-boxes-properly": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "is-string": "^1.1.1" + }, + "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==", + "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==", + "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/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "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==", + "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==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz", + "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-jest/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-loader": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", + "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.4", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.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==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-named-asset-import": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", + "peerDependencies": { + "@babel/core": "^7.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "dependencies": { + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" + }, + "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==", + "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": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-react-app": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.1.0.tgz", + "integrity": "sha512-f9B1xMdnkCIqe+2dHrJsoQFRz7reChaAHE/65SdaykPklQqhme2WaC08oD3is77x9ff98/9EazAKFDZv5rFEQg==", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "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==" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.7", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.7.tgz", + "integrity": "sha512-k9xFKplee6KIio3IDbwj+uaCLpqzOwakOgmqzPezM0sFJlFKcg30vk2wOiAJtkTSfx0SSQDSe8q+mWA/fSH5Zg==", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "node_modules/bfj": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", + "integrity": "sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==", + "dependencies": { + "bluebird": "^3.7.2", + "check-types": "^11.2.3", + "hoopy": "^0.1.4", + "jsonpath": "^1.1.1", + "tryer": "^1.0.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/body-parser": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bonjour-service": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "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==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "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" + } + ], + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "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==", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "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==" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.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==", + "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==", + "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==", + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001760", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", + "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "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" + } + ] + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "engines": { + "node": ">=10" + } + }, + "node_modules/check-types": { + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", + "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==" + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "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==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/coa/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/coa/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/coa/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/coa/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/coa/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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==" + }, + "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==", + "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==" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + }, + "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==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "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==" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==" + }, + "node_modules/core-js": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz", + "integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", + "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", + "dependencies": { + "browserslist": "^4.28.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.47.0.tgz", + "integrity": "sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cosmiconfig": { + "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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-blank-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "bin": { + "css-has-pseudo": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "dependencies": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", + "bin": { + "css-prefers-color-scheme": "dist/cli.cjs" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + }, + "node_modules/cssdb": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.11.2.tgz", + "integrity": "sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + } + ] + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/csso/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "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==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "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==", + "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==", + "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/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==" + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + }, + "node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==" + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "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==", + "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-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "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==", + "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==", + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "deprecated": "Use your platform's native DOMException instead", + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "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==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "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==" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==" + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "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==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "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==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "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==", + "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==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "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-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==" + }, + "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==", + "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==", + "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==", + "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==", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "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==" + }, + "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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/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==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.0" + } + }, + "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==", + "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==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "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==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@babel/plugin-syntax-flow": "^7.14.5", + "@babel/plugin-transform-react-jsx": "^7.14.9", + "eslint": "^8.1.0" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "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-testing-library": { + "version": "5.11.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.1.tgz", + "integrity": "sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==", + "dependencies": { + "@typescript-eslint/utils": "^5.58.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0", + "npm": ">=6" + }, + "peerDependencies": { + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "dependencies": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/eslint-webpack-plugin/node_modules/jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/eslint-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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/eslint/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==" + }, + "node_modules/eslint/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "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==", + "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==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "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==", + "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/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==" + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", + "dependencies": { + "@jest/expect-utils": "30.2.0", + "@jest/get-type": "30.1.0", + "jest-matcher-utils": "30.2.0", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", + "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==" + }, + "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==", + "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==", + "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==" + }, + "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==" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] + }, + "node_modules/fastq": { + "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" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "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==", + "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==", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/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==", + "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/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "engines": { + "node": ">= 0.4.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==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "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==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "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==", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "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==" + }, + "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==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "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==", + "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==", + "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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "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==", + "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==", + "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-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "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==", + "engines": { + "node": ">=8.0.0" + } + }, + "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==", + "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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "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/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "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" + }, + "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==" + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "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==", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/goober": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", + "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "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==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "node_modules/harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" + }, + "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==", + "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==", + "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==", + "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==", + "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==", + "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==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "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==" + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.5", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.5.tgz", + "integrity": "sha512-4xynFbKNNk+WlzXeQQ+6YYsH2g7mpfPszQZUi3ovKlj+pDmngQ7vRXjrrmGROabmKwyQkcgcX5hqfOwHbFmK5g==", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "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==", + "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-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "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==", + "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==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" + }, + "node_modules/identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "dependencies": { + "harmony-reflect": "^1.4.6" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "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" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/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==", + "engines": { + "node": ">=4" + } + }, + "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==", + "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==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "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.", + "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==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "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==", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ipaddr.js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "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-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==", + "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==" + }, + "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==", + "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==", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "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-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "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==", + "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==", + "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==", + "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-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "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==", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "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-glob": { + "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" + }, + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "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==", + "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==", + "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-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "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==", + "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-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "engines": { + "node": ">=6" + } + }, + "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==", + "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==", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "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==", + "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==", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "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==", + "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==", + "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==", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/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==", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "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/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jalaali-js": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.8.tgz", + "integrity": "sha512-Jl/EwY84JwjW2wsWqeU4pNd22VNQ7EkjI36bDuLw31wH98WQW4fPjD0+mG7cdCK+Y8D6s9R3zLiQ3LaKu6bD8A==" + }, + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-changed-files/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-diff": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", + "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-diff/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/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==" + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-environment-jsdom/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-environment-jsdom/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-environment-node/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-environment-node/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node/node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-haste-map/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-haste-map/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-haste-map/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-haste-map/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-jasmine2/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-jasmine2/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-jasmine2/node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", + "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", + "dependencies": { + "@jest/get-type": "30.1.0", + "chalk": "^4.1.2", + "jest-diff": "30.2.0", + "pretty-format": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/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==" + }, + "node_modules/jest-message-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", + "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.2.0", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.2.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-message-util/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", + "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/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==" + }, + "node_modules/jest-mock": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", + "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-util": "30.2.0" + }, + "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==", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", + "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "dependencies": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "jest": "^27.0.0 || ^28.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "dependencies": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/@sinclair/typebox": { + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" + }, + "node_modules/jest-watch-typeahead/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "dependencies": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "dependencies": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/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==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-watch-typeahead/node_modules/jest-watcher/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==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watch-typeahead/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-watch-typeahead/node_modules/pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "dependencies": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-watch-typeahead/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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/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==" + }, + "node_modules/jest-watch-typeahead/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "dependencies": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.2.tgz", + "integrity": "sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg==", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/@types/yargs": { + "version": "16.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.11.tgz", + "integrity": "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g==", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, + "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==" + }, + "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==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "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==" + }, + "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==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "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==" + }, + "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==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpath": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", + "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", + "dependencies": { + "esprima": "1.2.2", + "static-eval": "2.0.2", + "underscore": "1.12.1" + } + }, + "node_modules/jsonpath/node_modules/esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "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==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/launch-editor": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", + "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" + } + }, + "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==", + "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==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "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==" + }, + "node_modules/loader-runner": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "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==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "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==" + }, + "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==" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "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==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "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==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "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==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "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==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "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==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "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==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.4.tgz", + "integrity": "sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "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==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-jalaali": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/moment-jalaali/-/moment-jalaali-0.10.4.tgz", + "integrity": "sha512-/eD0HeyvATznb5iE0G1BHjKRZAFEpJ9ZNUkcHwXhNgt1WJJVVzHD7+uDmqzZWVFLdbGme2gvIXKb3ezDYOXcZA==", + "dependencies": { + "jalaali-js": "^1.2.7", + "moment": "^2.29.4", + "moment-timezone": "^0.5.46" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.48", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", + "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "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==" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "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==" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "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==" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-forge": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", + "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", + "engines": { + "node": ">= 6.13.0" + } + }, + "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==" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==" + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.23", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", + "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==" + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "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==", + "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==", + "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==", + "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==", + "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.getownpropertydescriptors": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.9.tgz", + "integrity": "sha512-mt8YM6XwsTTovI+kdZdHSxoyF2DI59up034orlC9NfweclcWOt7CVascNNLp6U+bjFVCVCIh9PwS76tDM/rH8g==", + "dependencies": { + "array.prototype.reduce": "^1.0.8", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "gopd": "^1.2.0", + "safe-array-concat": "^1.1.3" + }, + "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==", + "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==", + "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/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "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==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "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==", + "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==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "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==", + "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==", + "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": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parchment": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz", + "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==" + }, + "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==", + "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==", + "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/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "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==", + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "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==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "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==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "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" + } + ], + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-browser-comments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "browserslist": ">=4", + "postcss": ">=8" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=7.6.0" + }, + "peerDependencies": { + "postcss": "^8.4.6" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-custom-properties": { + "version": "12.1.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", + "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.3" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-flexbugs-fixes": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", + "peerDependencies": { + "postcss": "^8.1.4" + } + }, + "node_modules/postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.9" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "dependencies": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-loader/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", + "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", + "dependencies": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-normalize": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", + "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "dependencies": { + "@csstools/normalize.css": "*", + "postcss-browser-comments": "^4", + "sanitize.css": "*" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "browserslist": ">= 4", + "postcss": ">= 8" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-opacity-percentage": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", + "funding": [ + { + "type": "kofi", + "url": "https://ko-fi.com/mrcgrtz" + }, + { + "type": "liberapay", + "url": "https://liberapay.com/mrcgrtz" + } + ], + "engines": { + "node": "^12 || ^14 || >=16" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", + "peerDependencies": { + "postcss": "^8" + } + }, + "node_modules/postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-preset-env": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", + "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", + "dependencies": { + "@csstools/postcss-cascade-layers": "^1.1.1", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.13", + "browserslist": "^4.21.4", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.1.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.10", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.2.0", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", + "peerDependencies": { + "postcss": "^8.0.3" + } + }, + "node_modules/postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/postcss-svgo/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/postcss-svgo/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/postcss-svgo/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-svgo/node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "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==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "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==" + }, + "node_modules/property-expr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", + "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==" + }, + "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==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/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==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quill": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz", + "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==", + "dependencies": { + "clone": "^2.1.1", + "deep-equal": "^1.0.1", + "eventemitter3": "^2.0.3", + "extend": "^3.0.2", + "parchment": "^1.1.4", + "quill-delta": "^3.6.2" + } + }, + "node_modules/quill-delta": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz", + "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==", + "dependencies": { + "deep-equal": "^1.0.1", + "extend": "^3.0.2", + "fast-diff": "1.1.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-app-polyfill": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", + "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", + "dependencies": { + "core-js": "^3.19.2", + "object-assign": "^4.1.1", + "promise": "^8.1.0", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.9", + "whatwg-fetch": "^3.6.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-date-object": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/react-date-object/-/react-date-object-2.1.9.tgz", + "integrity": "sha512-BHxD/quWOTo9fLKV/cfL/M31ePoj4a1JaJ/CnOf8Ndg3mrkh4x9wEMMkCfTrzduxDOgU8ZgR8uarhqI5G71sTg==" + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/chalk": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/react-dev-utils/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==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/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==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/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==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/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==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-element-popper": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-element-popper/-/react-element-popper-2.1.7.tgz", + "integrity": "sha512-tuM2OxKlW32h+6uFSK6EENHPeZ2OGgOipHfOAl+VLWEv9/j3QkSGbD+ADX3A9uJlmq24i37n28RjJmAbGTfpEg==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-error-overlay": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.1.0.tgz", + "integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==" + }, + "node_modules/react-hot-toast": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz", + "integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==", + "dependencies": { + "csstype": "^3.1.3", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-modal": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.3.tgz", + "integrity": "sha512-yCYRJB5YkeQDQlTt17WGAgFJ7jr2QYcWa1SHqZ3PluDmnKJ/7+tVU+E6uKyZ0nODaeEj+xCpK4LcSnKXLMC0Nw==", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19" + } + }, + "node_modules/react-multi-date-picker": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/react-multi-date-picker/-/react-multi-date-picker-4.5.2.tgz", + "integrity": "sha512-FgWjZB3Z6IA6XpcWiLPk85PwcRUhOiYhKK42o5k672gD/n2I6rzPfQ8bUrldOIiF/Z7FfOCdH7a6FeubzqteLg==", + "dependencies": { + "react-date-object": "^2.1.8", + "react-element-popper": "^2.1.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-quill": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz", + "integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==", + "dependencies": { + "@types/quill": "^1.3.10", + "lodash": "^4.17.4", + "quill": "^1.3.7" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18" + } + }, + "node_modules/react-refresh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "6.30.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.2.tgz", + "integrity": "sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==", + "dependencies": { + "@remix-run/router": "1.23.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.2.tgz", + "integrity": "sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==", + "dependencies": { + "@remix-run/router": "1.23.1", + "react-router": "6.30.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-scripts": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", + "dependencies": { + "@babel/core": "^7.16.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@svgr/webpack": "^5.5.0", + "babel-jest": "^27.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "bfj": "^7.0.2", + "browserslist": "^4.18.1", + "camelcase": "^6.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.5.1", + "css-minimizer-webpack-plugin": "^3.2.0", + "dotenv": "^10.0.0", + "dotenv-expand": "^5.1.0", + "eslint": "^8.3.0", + "eslint-config-react-app": "^7.0.1", + "eslint-webpack-plugin": "^3.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.0", + "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.3", + "jest-resolve": "^27.4.2", + "jest-watch-typeahead": "^1.0.0", + "mini-css-extract-plugin": "^2.4.5", + "postcss": "^8.4.4", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^6.2.1", + "postcss-normalize": "^10.0.1", + "postcss-preset-env": "^7.0.1", + "prompts": "^2.4.2", + "react-app-polyfill": "^3.0.0", + "react-dev-utils": "^12.0.1", + "react-refresh": "^0.11.0", + "resolve": "^1.20.0", + "resolve-url-loader": "^4.0.0", + "sass-loader": "^12.3.0", + "semver": "^7.3.5", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.2", + "terser-webpack-plugin": "^5.2.5", + "webpack": "^5.64.4", + "webpack-dev-server": "^4.6.0", + "webpack-manifest-plugin": "^4.0.2", + "workbox-webpack-plugin": "^6.4.1" + }, + "bin": { + "react-scripts": "bin/react-scripts.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + }, + "peerDependencies": { + "react": ">= 16", + "typescript": "^3.2.1 || ^4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/react-scripts/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "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==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "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/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regex-parser": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.1.tgz", + "integrity": "sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ==" + }, + "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==", + "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/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==" + }, + "node_modules/regjsparser": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "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==", + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dependencies": { + "is-core-module": "^2.16.1", + "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-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==", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "rework": "1.0.1", + "rework-visit": "1.0.0" + }, + "peerDependenciesMeta": { + "rework": { + "optional": true + }, + "rework-visit": { + "optional": true + } + } + }, + "node_modules/resolve-url-loader/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==" + }, + "node_modules/resolve-url-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/resolve-url-loader/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", + "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/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==", + "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-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" + } + ] + }, + "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==", + "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==", + "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/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sanitize.css": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", + "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" + }, + "node_modules/sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "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==", + "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/schema-utils/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "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/schema-utils/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==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/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==" + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz", + "integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-static/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/serve-static/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "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==", + "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==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "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==", + "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==", + "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==", + "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": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "engines": { + "node": ">= 12" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", + "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "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==", + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "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==", + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "node_modules/static-eval": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", + "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", + "dependencies": { + "escodegen": "^1.8.1" + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/static-eval/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/static-eval/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==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "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==", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" + }, + "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==", + "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/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==" + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "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==", + "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==", + "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==", + "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==", + "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/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "engines": { + "node": ">=10" + } + }, + "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==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/svgo/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/svgo/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/svgo/node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/svgo/node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "node_modules/svgo/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/svgo/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/svgo/node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/svgo/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/tailwindcss/node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "optional": true, + "peer": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "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.3.16", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", + "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "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==" + }, + "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==", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/throat": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", + "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/tiny-case": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", + "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "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==" + }, + "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==", + "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==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==" + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "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==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/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==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "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==", + "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==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "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==", + "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==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "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==", + "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==", + "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==", + "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/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.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==", + "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/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" + }, + "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==" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "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" + } + ], + "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==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.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==" + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/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==" + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/watchpack": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-vitals": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.4.tgz", + "integrity": "sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==" + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.103.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.103.0.tgz", + "integrity": "sha512-HU1JOuV1OavsZ+mfigY0j8d1TgQgbZ6M+J75zDkpEAwYeXjWSqrGJtgnPblJjd/mAyTNQ7ygw0MiKOn6etz8yw==", + "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.15.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.26.3", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.3", + "es-module-lexer": "^1.2.1", + "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.11", + "watchpack": "^2.4.4", + "webpack-sources": "^3.3.3" + }, + "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-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "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/webpack-manifest-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", + "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", + "dependencies": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "webpack": "^4.44.2 || ^5.47.0" + } + }, + "node_modules/webpack-manifest-plugin/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-manifest-plugin/node_modules/webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "dependencies": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "engines": { + "node": ">=10.13.0" + } + }, + "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==", + "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==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/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==", + "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==", + "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==", + "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==", + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-background-sync": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", + "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", + "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-build": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", + "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.6.0", + "workbox-broadcast-update": "6.6.0", + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-google-analytics": "6.6.0", + "workbox-navigation-preload": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-range-requests": "6.6.0", + "workbox-recipes": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0", + "workbox-streams": "6.6.0", + "workbox-sw": "6.6.0", + "workbox-window": "6.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "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/workbox-build/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/workbox-build/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==" + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "deprecated": "The work that was done in this beta branch won't be included in future versions", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-build/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/workbox-build/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "node_modules/workbox-build/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", + "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", + "deprecated": "workbox-background-sync@6.6.0", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-core": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", + "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==" + }, + "node_modules/workbox-expiration": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", + "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", + "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", + "deprecated": "It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained", + "dependencies": { + "workbox-background-sync": "6.6.0", + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", + "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-precaching": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", + "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", + "dependencies": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", + "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-recipes": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", + "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", + "dependencies": { + "workbox-cacheable-response": "6.6.0", + "workbox-core": "6.6.0", + "workbox-expiration": "6.6.0", + "workbox-precaching": "6.6.0", + "workbox-routing": "6.6.0", + "workbox-strategies": "6.6.0" + } + }, + "node_modules/workbox-routing": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", + "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-strategies": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", + "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", + "dependencies": { + "workbox-core": "6.6.0" + } + }, + "node_modules/workbox-streams": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", + "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", + "dependencies": { + "workbox-core": "6.6.0", + "workbox-routing": "6.6.0" + } + }, + "node_modules/workbox-sw": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", + "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==" + }, + "node_modules/workbox-webpack-plugin": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", + "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", + "dependencies": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.6.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "webpack": "^4.4.0 || ^5.9.0" + } + }, + "node_modules/workbox-webpack-plugin/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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/workbox-window": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", + "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.6.0" + } + }, + "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==", + "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==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "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==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "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==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yup": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/yup/-/yup-1.7.1.tgz", + "integrity": "sha512-GKHFX2nXul2/4Dtfxhozv701jLQHdf6J34YDh2cEkpqoo8le5Mg6/LrdseVLrFarmFygZTlfIhHx/QKfb/QWXw==", + "dependencies": { + "property-expr": "^2.0.5", + "tiny-case": "^1.0.3", + "toposort": "^2.0.2", + "type-fest": "^2.19.0" + } + }, + "node_modules/yup/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/public/modstagram_panel/package.json b/public/modstagram_panel/package.json new file mode 100644 index 0000000..2521215 --- /dev/null +++ b/public/modstagram_panel/package.json @@ -0,0 +1,53 @@ +{ + "name": "modstagram_panel", + "version": "0.1.0", + "private": true, + "dependencies": { + "@testing-library/jest-dom": "^5.17.0", + "@testing-library/react": "^13.4.0", + "@testing-library/user-event": "^13.5.0", + "axios": "^1.6.8", + "js-cookie": "^3.0.5", + "moment-jalaali": "^0.10.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-hot-toast": "^2.4.1", + "react-icons": "^5.5.0", + "react-modal": "^3.16.1", + "react-multi-date-picker": "^4.5.2", + "react-quill": "^2.0.0", + "react-router-dom": "^6.23.1", + "react-scripts": "5.0.1", + "web-vitals": "^2.1.4", + "yup": "^1.4.0" + }, + "scripts": { + "start": "BROWSER=none react-scripts start", + "build": "GENERATE_SOURCEMAP=false react-scripts build", + "build:no-cache": "GENERATE_SOURCEMAP=false INLINE_RUNTIME_CHUNK=false react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "tailwindcss": "^3.4.3" + } +} diff --git a/public/modstagram_panel/public/favicon.ico b/public/modstagram_panel/public/favicon.ico new file mode 100644 index 0000000..596b2ec Binary files /dev/null and b/public/modstagram_panel/public/favicon.ico differ diff --git a/public/modstagram_panel/public/fonts/KalamehWeb-Medium.woff b/public/modstagram_panel/public/fonts/KalamehWeb-Medium.woff new file mode 100644 index 0000000..583f1f3 Binary files /dev/null and b/public/modstagram_panel/public/fonts/KalamehWeb-Medium.woff differ diff --git a/public/modstagram_panel/public/fonts/KalamehWeb-Regular.woff b/public/modstagram_panel/public/fonts/KalamehWeb-Regular.woff new file mode 100644 index 0000000..b258ec9 Binary files /dev/null and b/public/modstagram_panel/public/fonts/KalamehWeb-Regular.woff differ diff --git a/public/modstagram_panel/public/fonts/KalamehWeb-SemiBold.woff b/public/modstagram_panel/public/fonts/KalamehWeb-SemiBold.woff new file mode 100644 index 0000000..d1f1e84 Binary files /dev/null and b/public/modstagram_panel/public/fonts/KalamehWeb-SemiBold.woff differ diff --git a/public/modstagram_panel/public/index.html b/public/modstagram_panel/public/index.html new file mode 100644 index 0000000..d58709e --- /dev/null +++ b/public/modstagram_panel/public/index.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + مدستاگرام | پنل مدیریت + + + +
+ + diff --git a/public/modstagram_panel/public/logo192.png b/public/modstagram_panel/public/logo192.png new file mode 100644 index 0000000..fc44b0a Binary files /dev/null and b/public/modstagram_panel/public/logo192.png differ diff --git a/public/modstagram_panel/public/logo512.png b/public/modstagram_panel/public/logo512.png new file mode 100644 index 0000000..a4e47a6 Binary files /dev/null and b/public/modstagram_panel/public/logo512.png differ diff --git a/public/modstagram_panel/public/manifest.json b/public/modstagram_panel/public/manifest.json new file mode 100644 index 0000000..080d6c7 --- /dev/null +++ b/public/modstagram_panel/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/public/modstagram_panel/public/robots.txt b/public/modstagram_panel/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/public/modstagram_panel/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/public/modstagram_panel/src/App.jsx b/public/modstagram_panel/src/App.jsx new file mode 100644 index 0000000..4109f71 --- /dev/null +++ b/public/modstagram_panel/src/App.jsx @@ -0,0 +1,17 @@ +import { RouterProvider } from "react-router-dom"; +import AuthProvider from "./utils/AuthProvider"; +import { Toaster } from "react-hot-toast"; +import { router } from "./routers/appRoutes"; + +function App() { + return ( +
+ + + + +
+ ); +} + +export default App; diff --git a/public/modstagram_panel/src/assets/css/index.css b/public/modstagram_panel/src/assets/css/index.css new file mode 100644 index 0000000..9ae09b3 --- /dev/null +++ b/public/modstagram_panel/src/assets/css/index.css @@ -0,0 +1,166 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@font-face { + font-family: Kalameh; + src: url("/public/fonts/KalamehWeb-Regular.woff"); +} +@font-face { + font-family: KalamehMed; + src: url("/public/fonts/KalamehWeb-Medium.woff"); +} +@font-face { + font-family: KalamehSemi; + src: url("/public/fonts/KalamehWeb-SemiBold.woff"); +} + +html { + scroll-behavior: smooth; +} + +.hide-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; +} + +.hide-scrollbar::-webkit-scrollbar { + display: none; +} +.datePickerStyle { + width: 100%; + background-color: black; +} +button, +button:focus, +textarea { + outline: none; +} + +input:focus, +button:focus, +select:focus { + outline: none; +} + +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +/* Firefox */ +input[type="number"] { + -moz-appearance: textfield; +} +* { + font-family: "kalameh" !important; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + direction: rtl; + background-color: #252525; +} +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", + monospace; +} +.dir-ltr { + direction: ltr; +} +.big-circle { + position: fixed; + top: 60vh; /* 30vh پایین‌تر از پایین صفحه */ + left: 50%; /* در وسط صفحه افقی */ + transform: translateX(-50%); /* تنظیم موقعیت در وسط صفحه افقی */ + width: 170vw; /* عرض بیشتر از عرض صفحه */ + height: 100vw; /* ارتفاع برابر با عرض بیشتر از عرض صفحه */ + border-radius: 50%; /* تبدیل به دایره */ + background-color: #fff; /* رنگ پس‌زمینه */ + z-index: 15; +} +.bg-glass { + box-shadow: 0px 4px 12px 0px #00000040; + background-color: #ffffffa2; +} +.purple-line { + width: 200px; + height: 1px; + background: linear-gradient(to right, #f9f2fb 0%, #482d4f 100%); +} +.bg-glass-absolute { + width: 101%; + height: 110%; + box-shadow: 0px 4px 12px 0px #00000040; + background-color: #e9e9e99c; + position: absolute; + bottom: -20px; + border-radius: 20px; + z-index: 99; + display: flex; + align-items: center; + justify-content: center; + left: 50%; + transform: translateX(-50%); +} +.ql-container, +.ql-editor { + min-height: 400px; + color: #fff !important; + text-align: right !important; +} +.ql-editor.ql-blank::before { + color: #fff !important; +} + +.rmdp-input { + border-color: #dee2e6 !important; + width: 130px !important; + height: 48px !important; + padding-right: 16px !important; + color: #111; +} +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1170px; + } +} +@media (min-width: 1400px) { + .container { + max-width: 1300px; + } +} +@media (min-width: 1500px) { + .container { + max-width: 1400px; + } +} +@media (min-width: 1636px) { + .container { + max-width: 1650px; + } +} diff --git a/public/modstagram_panel/src/assets/icons/AdvertisingIcon.jsx b/public/modstagram_panel/src/assets/icons/AdvertisingIcon.jsx new file mode 100644 index 0000000..5d583be --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/AdvertisingIcon.jsx @@ -0,0 +1,15 @@ +import React from "react"; + +function AdvertisingIcon(props) { + return ( + + + + + + + ); +} + +export default AdvertisingIcon; diff --git a/public/modstagram_panel/src/assets/icons/CommentsIcon.jsx b/public/modstagram_panel/src/assets/icons/CommentsIcon.jsx new file mode 100644 index 0000000..9f33f1f --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/CommentsIcon.jsx @@ -0,0 +1,18 @@ +import React from "react"; + +function CommentsIcon(props) { + return ( + + + + + + + + + + ); +} + +export default CommentsIcon; diff --git a/public/modstagram_panel/src/assets/icons/FinancialsIcon.jsx b/public/modstagram_panel/src/assets/icons/FinancialsIcon.jsx new file mode 100644 index 0000000..fa68ab3 --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/FinancialsIcon.jsx @@ -0,0 +1,18 @@ +import React from "react"; + +function FinancialsIcon(props) { + return ( + + + + + + + + + + ); +} + +export default FinancialsIcon; diff --git a/public/modstagram_panel/src/assets/icons/PostsIcon.jsx b/public/modstagram_panel/src/assets/icons/PostsIcon.jsx new file mode 100644 index 0000000..3d45171 --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/PostsIcon.jsx @@ -0,0 +1,16 @@ +import React from "react"; + +function PostsIcon(props) { + return ( + + + + + + + + ); +} + +export default PostsIcon; diff --git a/public/modstagram_panel/src/assets/icons/ProjectsIcon.jsx b/public/modstagram_panel/src/assets/icons/ProjectsIcon.jsx new file mode 100644 index 0000000..bd6e07e --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/ProjectsIcon.jsx @@ -0,0 +1,17 @@ +import React from "react"; + +function ProjectsIcon(props) { + return ( + + + + + + + + ); +} + +export default ProjectsIcon; diff --git a/public/modstagram_panel/src/assets/icons/ShopIcon.jsx b/public/modstagram_panel/src/assets/icons/ShopIcon.jsx new file mode 100644 index 0000000..4f79cec --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/ShopIcon.jsx @@ -0,0 +1,20 @@ + + + +import React from "react"; + +function ShopIcon(props) { + return ( + + + + + + + + + ); +} + +export default ShopIcon; diff --git a/public/modstagram_panel/src/assets/icons/SupportIcon.jsx b/public/modstagram_panel/src/assets/icons/SupportIcon.jsx new file mode 100644 index 0000000..330c4fc --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/SupportIcon.jsx @@ -0,0 +1,14 @@ +import React from "react"; + +function SupportIcon(props) { + return ( + + + + + ); +} + +export default SupportIcon; diff --git a/public/modstagram_panel/src/assets/icons/UsersIcon.jsx b/public/modstagram_panel/src/assets/icons/UsersIcon.jsx new file mode 100644 index 0000000..069f49b --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/UsersIcon.jsx @@ -0,0 +1,16 @@ +import React from "react"; + +function UsersIcon(props) { + return ( + + + + + + + ); +} + +export default UsersIcon; diff --git a/public/modstagram_panel/src/assets/icons/dashboardIcon.jsx b/public/modstagram_panel/src/assets/icons/dashboardIcon.jsx new file mode 100644 index 0000000..eb987b2 --- /dev/null +++ b/public/modstagram_panel/src/assets/icons/dashboardIcon.jsx @@ -0,0 +1,21 @@ +import React from "react"; + +function DashboardIcon(props) { + return ( + + + + + + + ); +} + +export default DashboardIcon; diff --git a/public/modstagram_panel/src/components/BaseUrl.js b/public/modstagram_panel/src/components/BaseUrl.js new file mode 100644 index 0000000..463a28d --- /dev/null +++ b/public/modstagram_panel/src/components/BaseUrl.js @@ -0,0 +1,7 @@ +export const BaseUrl = "https://app.modstagram.ir/api/v1/panel"; +export const AppBaseUrl = "https://app.modstagram.ir/api/v1"; +export const ImageBaseUrl = "https://app.modstagram.ir/storage"; + +// export const BaseUrl = "http://localhost:8000/api/v1/panel"; +// export const AppBaseUrl = "http://localhost:8000/api/v1"; +// export const ImageBaseUrl = "http://localhost:8000/storage"; \ No newline at end of file diff --git a/public/modstagram_panel/src/components/Filters.jsx b/public/modstagram_panel/src/components/Filters.jsx new file mode 100644 index 0000000..54bf4e8 --- /dev/null +++ b/public/modstagram_panel/src/components/Filters.jsx @@ -0,0 +1,126 @@ +import React from "react"; + +const Filters = ({ + statusOptions = [], + provinceOptions = [], + cityOptions = [], + photographyModelOptions = [], + blockStatusOptions = [], + onFilterChange = () => {}, +}) => { + const [filters, setFilters] = React.useState({ + startDate: "", + endDate: "", + status: "", + province: "", + city: "", + photographyModel: "", + blockStatus: "", + }); + + const handleFilterChange = (name, value) => { + const newFilters = { ...filters, [name]: value }; + if (name === "province") { + newFilters.city = ""; // ریست شهر هنگام تغییر استان + } + setFilters(newFilters); + onFilterChange(newFilters); + }; + + return ( +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + handleFilterChange("startDate", e.target.value)} + className="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-teal-500 dark:bg-gray-700 dark:text-white" + /> +
+
+ + handleFilterChange("endDate", e.target.value)} + className="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-600 focus:outline-none focus:ring-2 focus:ring-teal-500 dark:bg-gray-700 dark:text-white" + /> +
+
+ ); +}; + +export default Filters; \ No newline at end of file diff --git a/public/modstagram_panel/src/components/Pagination.jsx b/public/modstagram_panel/src/components/Pagination.jsx new file mode 100644 index 0000000..3a5fd68 --- /dev/null +++ b/public/modstagram_panel/src/components/Pagination.jsx @@ -0,0 +1,68 @@ +import React from "react"; + +const Pagination = ({ totalPages, currentPage, onPageChange }) => { + if (!totalPages || totalPages <= 1) return null; + + const handlePageClick = (page) => { + if (page >= 1 && page <= totalPages) onPageChange(page); + }; + + const getPageNumbers = () => { + const pages = []; + if (totalPages <= 7) { + for (let i = 1; i <= totalPages; i++) pages.push(i); + } else { + pages.push(1); + let start = Math.max(currentPage - 2, 2); + let end = Math.min(currentPage + 2, totalPages - 1); + + if (start > 2) pages.push("..."); + for (let i = start; i <= end; i++) pages.push(i); + if (end < totalPages - 1) pages.push("..."); + pages.push(totalPages); + } + return pages; + }; + + const pages = getPageNumbers(); + + return ( +
+ + + {pages.map((page, idx) => + page === "..." ? ( + ... + ) : ( + + ) + )} + + +
+ ); +}; + +export default Pagination; diff --git a/public/modstagram_panel/src/components/academy/Header.js b/public/modstagram_panel/src/components/academy/Header.js new file mode 100644 index 0000000..3a2b80d --- /dev/null +++ b/public/modstagram_panel/src/components/academy/Header.js @@ -0,0 +1,33 @@ +// src/components/Layout/Header.js +import React from "react"; +import { FaBell, FaUserCircle } from "react-icons/fa"; + +const Header = ({ toggleSidebar }) => { + return ( +
+
+ +

پنل مدیریت

+
+ +
+ + +
+ + مدیر سیستم +
+
+
+ ); +}; + +export default Header; \ No newline at end of file diff --git a/public/modstagram_panel/src/components/academy/Layout.js b/public/modstagram_panel/src/components/academy/Layout.js new file mode 100644 index 0000000..a2fb2be --- /dev/null +++ b/public/modstagram_panel/src/components/academy/Layout.js @@ -0,0 +1,27 @@ +// src/components/Layout/Layout.js +import React, { useState } from "react"; +import Sidebar from "./Sidebar"; +import Header from "./Header"; + +const Layout = ({ children }) => { + const [sidebarOpen, setSidebarOpen] = useState(window.innerWidth > 768); + + const toggleSidebar = () => { + setSidebarOpen(!sidebarOpen); + }; + + return ( +
+ + +
+ {/*
*/} +
+ {children} +
+
+
+ ); +}; + +export default Layout; \ No newline at end of file diff --git a/public/modstagram_panel/src/components/academy/Sidebar.js b/public/modstagram_panel/src/components/academy/Sidebar.js new file mode 100644 index 0000000..2d64c5a --- /dev/null +++ b/public/modstagram_panel/src/components/academy/Sidebar.js @@ -0,0 +1,50 @@ +// src/components/Layout/Sidebar.js +import React from "react"; +import { NavLink } from "react-router-dom"; +import { + FaTachometerAlt, + FaWallet, + FaBook, + FaShoppingCart, + FaUniversity, + FaCog, + FaBackspace +} from "react-icons/fa"; + +const Sidebar = () => { + const menuItems = [ + { path: "/academy", label: "داشبورد", icon: }, + { path: "/payments", label: "مدیریت پرداخت‌ها", icon: }, + { path: "/courses", label: "مدیریت دوره‌ها", icon: }, + { path: "/purchased", label: "دوره‌های خریداری شده", icon: }, + { path: "/academies", label: "مدیریت آکادمی‌ها", icon: }, + { path: "/settings", label: "تنظیمات", icon: }, + { path: "/", label: "بازگشت", icon: } + ]; + + return ( +
+
+

پنل مدیریت دوره‌ها

+
+ +
+ ); +}; + +export default Sidebar; \ No newline at end of file diff --git a/public/modstagram_panel/src/components/admin-header.jsx b/public/modstagram_panel/src/components/admin-header.jsx new file mode 100644 index 0000000..f52bffd --- /dev/null +++ b/public/modstagram_panel/src/components/admin-header.jsx @@ -0,0 +1,87 @@ +import React, { useContext, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import Loading from "./elements/loading"; +import { Link } from "react-router-dom/dist"; + +function AdminHeader() { + const navigate = useNavigate(); + const handleLogOut = () => { + localStorage.clear(); + document.getElementById("to_login").click(); + }; + function refreshPage() { + setTimeout(() => { + window.location.reload(false); + }, 1000); + } + return ( + <> + +
+
+
+
+
+ +
+

+ {/* {full_name} */} +

+
+
+
+
logOutMutation.mutate()} + className="flex bg-white cursor-pointer bg-primary hover:bg-[#cbade4] px-5 items-center h-9 group transition-colors duration-500 hover:bg-cyann rounded-[4px] font-KalamehMed font-medium" + > + <> + + + + + + + +
+
+
+
+ + ); +} + +export default AdminHeader; diff --git a/public/modstagram_panel/src/components/adminApi.js b/public/modstagram_panel/src/components/adminApi.js new file mode 100644 index 0000000..c89db8d --- /dev/null +++ b/public/modstagram_panel/src/components/adminApi.js @@ -0,0 +1,42 @@ +// src/services/adminApi.js +import api from "./api"; + +// ==================== پرداخت‌ها ==================== +export const getPayments = (params) => api.get("/academy/payments", { params }); +export const updatePaymentStatus = (data) => api.put("/academy/payments/status", data); +export const getPaymentStats = () => api.get("/academy/payments/stats"); + +// ==================== دوره‌ها ==================== +export const getCourses = (params) => api.get("/academy/courses", { params }); +export const getCourseById = (id) => api.get(`/academy/courses/${id}`); +export const createCourse = (data) => api.post("/academy/courses", data); +export const updateCourse = (id, data) => api.put(`/academy/courses/${id}`, data); +export const updateCourseStatus = (data) => api.put("/academy/academy/courses/status", data); +export const deleteCourse = (courseId) => api.delete(`/academy/courses/${courseId}`); +export const getCourseStats = () => api.get("/academy/courses/stats"); + +// ==================== دوره‌های خریداری شده ==================== +export const getPurchasedCourses = (params) => api.get("/academy/purchased", { params }); +export const getPurchasedStats = () => api.get("/academy/purchased/stats"); + +// ==================== آکادمی‌ها ==================== +export const getAcademies = (params) => api.get("/academy/academies", { params }); +export const getAcademyById = (id) => api.get(`/academy/academies/${id}`); +export const createAcademy = (data) => api.post("/academy/academies", data); +export const updateAcademy = (id, data) => api.put(`/academy/academies/${id}`, data); +export const updateAcademyStatus = (data) => api.put("/academy/academies/status", data); +export const deleteAcademy = (id) => api.delete(`/academy/academies/${id}`); +export const getAcademyStats = () => api.get("/academy/academies/stats"); + +// ==================== تنظیمات ==================== +// مسیرهای قدیمی (برای سازگاری) +export const getSettings = () => api.get("/academy/settings/all"); +export const updateSettings = (data) => api.put("/academy/settings/all", data); + +// مسیرهای جدید (جداگانه) +export const getCoursePrices = () => api.get("/academy/settings/course-prices"); +export const updateCoursePrice = (data) => api.put("/academy/settings/course-price", data); +export const getTax = () => api.get("/academy/settings/tax"); +export const updateTax = (data) => api.put("/academy/settings/tax", data); +export const getAllSettings = () => api.get("/academy/settings/all"); +export const updateAllSettings = (data) => api.put("/academy/settings/all", data); \ No newline at end of file diff --git a/public/modstagram_panel/src/components/api.js b/public/modstagram_panel/src/components/api.js new file mode 100644 index 0000000..5767435 --- /dev/null +++ b/public/modstagram_panel/src/components/api.js @@ -0,0 +1,45 @@ +// src/services/api.js - نسخه ساده و مطمئن +import axios from "axios"; +import Cookies from "js-cookie"; +import { AppBaseUrl } from "./BaseUrl"; + +const API_BASE_URL = AppBaseUrl || "http://localhost:5000/api"; + +const api = axios.create({ + baseURL: API_BASE_URL, + headers: { + "Content-Type": "application/json" + } +}); + +api.interceptors.request.use( + (config) => { + // توکن + const token = Cookies.get("token"); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + + // فقط یک تغییر ساده: اضافه کردن timestamp به URL + if (config.method === 'get') { + const separator = config.url.includes('?') ? '&' : '?'; + config.url = `${config.url}${separator}_t=${Date.now()}`; + } + + return config; + }, + (error) => Promise.reject(error) +); + +api.interceptors.response.use( + (response) => response, + (error) => { + if (error.response?.status === 401) { + Cookies.remove("token"); + window.location.href = "/login"; + } + return Promise.reject(error); + } +); + +export default api; \ No newline at end of file diff --git a/public/modstagram_panel/src/components/elements/loading.jsx b/public/modstagram_panel/src/components/elements/loading.jsx new file mode 100644 index 0000000..10963cc --- /dev/null +++ b/public/modstagram_panel/src/components/elements/loading.jsx @@ -0,0 +1,57 @@ +import React from "react"; + +function Loading(props) { + return ( + <> + + + + + + + + + + ); +} + +export default Loading; diff --git a/public/modstagram_panel/src/components/shops/ShopDet.jsx b/public/modstagram_panel/src/components/shops/ShopDet.jsx new file mode 100644 index 0000000..a5c5605 --- /dev/null +++ b/public/modstagram_panel/src/components/shops/ShopDet.jsx @@ -0,0 +1,436 @@ +import React, { useEffect, useState } from "react"; +import { AppBaseUrl, BaseUrl, ImageBaseUrl } from "../BaseUrl"; +import axios from "axios"; +import toast from "react-hot-toast"; +import Modal from "react-modal"; +const customStyles = { + content: { + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + position: "fixed", + }, +}; +const ShopDet = ({ shopData, id, getUserDetails }) => { + const [isEditing, setIsEditing] = useState(false); + const [editedData, setEditedData] = useState({}); + const [categories, setCategories] = useState([]); + const [modalIsOpen, setModalIsOpen] = useState(false); + const [modalImage, setModalImage] = useState(""); + + const openModal = (image) => { + setModalImage(image); + setModalIsOpen(true); + }; + const closeModal = () => { + setModalIsOpen(false); + }; + + const getCategories = (page = 1) => { + const config = { + url: `${AppBaseUrl}/advertising/categories`, + method: "GET", + }; + axios(config) + .then((res) => { + setCategories(res?.data?.categories); + }) + .catch((err) => { }); + }; + useEffect(() => { + getCategories(); + }, []); + const handleChange = (e) => { + const { name, value } = e.target; + setEditedData((prevData) => ({ + ...prevData, + [name]: value, + })); + }; + + console.log(editedData); + + const handleSave = async () => { + try { + const response = await axios.put( + `${BaseUrl}/shops/update?shopId=${shopData._id}`, + editedData, + { + headers: { + Authorization: `Bearer ${localStorage.getItem( + "token" + )}`, // اگر نیاز به توکن احراز هویت دارید + }, + } + ); + getUserDetails(); + setIsEditing(false); + } catch (error) { + if ( + error.response && + error.response.data && + error.response.data.errors + ) { + error.response.data.errors.forEach((err) => { + if (typeof err.message === "string") { + // نمایش پیام خطا در صورتیکه به صورت string باشد + toast.error(err.message); + } else { + // نمایش پیام خطا برای موارد دیگر + toast.error("خطای ناشناخته"); + } + }); + } else { + // نمایش پیام خطا برای سایر موارد + toast.error("خطای ناشناخته"); + } + } + }; + const contactInfoArray = shopData?.contactInfo + ? Object.keys(shopData.contactInfo).map((key) => { + let title; + switch (key) { + case "phone": + title = "شماره ثابت"; + break; + case "mobile": + title = "شماره همراه"; + break; + case "telegramLink": + title = "لینک تلگرام"; + break; + case "whatsappNumber": + title = "شماره واتساپ"; + break; + case "instagramLink": + title = "لینک اینستاگرام"; + break; + case "saveInfoForNextAds": + title = "ذخیره اطلاعات برای آگهی‌های بعدی"; + break; + default: + title = key; + } + return { title, value: shopData.contactInfo[key] }; + }) + : []; + return ( +
+
+ + {/* استفاده از ImageMagnify */} + Post + +
+
+ {/* + + + */} + تصویر پروفایل: +
+
+ +
+
+ {/* User Name */} +
+
+ نام کاربری: +
+
+ {shopData?.user_name} +
+
+ + {/* First Name */} +
+
+ نام: +
+
+ {shopData?.first_name} +
+
+ + {/* Last Name */} +
+
+ نام خانوادگی: +
+
+ {shopData?.last_name} +
+
+ + {/* Mobile */} +
+
+ دسته بندی: +
+
+ {isEditing ? ( + + ) : ( + shopData?.category + )} +
+
+ {/* National Code */} +
+
+ عنوان فروشگاه: +
+
+ {isEditing ? ( + + ) : ( + shopData?.vitrine_name + )} +
+
+ +
+
+ استان: +
+
+ {shopData?.province?.name} +
+
+
+
+ شهر: +
+
+ {shopData?.city?.name} +
+
+
+
+ محله: +
+
+ {shopData?.neighbourhood} +
+
+ {/* Address */} +
+
+ آدرس: +
+
+ {isEditing ? ( + + ) : ( + shopData?.address + )} +
+
+
+
+ لیست خدمات و کالا +
+
+
+ {shopData?.allServices && + shopData?.allServices?.map((item) => { + return ( +
+ { + openModal( + ImageBaseUrl + + item?.image + ); + }} + src={ImageBaseUrl + item?.image} + className="w-[100px] h-[100px] rounded-sm" + alt="" + /> +

+ نام : {item?.title} +

+

+ درصد تخفیف :{" "} + {item?.discountPercentage} +

+

+ قیمت اصلی :{" "} + {item?.originalPrice} +

+

+ قیمت تخفیف خورده :{" "} + {item?.discountPrice} +

+
+ ); + })} +
+
+
+
+
+ لیست امکانات +
+
+
+ {shopData?.allFeatures && + shopData?.allFeatures?.map((item) => { + return ( +
+

+ {" "} + {item?.title} :{" "} +

+

+ {item?.value == true + ? "دارد" + : "ندارد"} +

+
+ ); + })} +
+
+
+
+
+ لیست تماس +
+
+
+ {contactInfoArray.map((item, index) => ( +
+

{item.title} :

+

{item.value}

+
+ ))} +
+
+
+
+
+ تصاویر +
+
+ {shopData?.allImages && + shopData?.allImages?.map((item) => { + return ( +
+ { + openModal(ImageBaseUrl + item); + }} + src={ImageBaseUrl + item} + className="w-[100px] h-[100px] rounded-sm m-4" + alt="" + /> +
+ ); + })} +
+
+
+
+ درباره ما: +
+
+ {isEditing ? ( + + ) : ( + shopData?.about_us + )} +
+
+
+
+ تاریخ ثبت فروشگاه: +
+
+ {shopData?.createdAt} +
+
+ + {/* Save Button */} +
+ {isEditing ? ( + + ) : ( + + )} +
+
+
+ ); +}; + +export default ShopDet; diff --git a/public/modstagram_panel/src/components/sidebar.jsx b/public/modstagram_panel/src/components/sidebar.jsx new file mode 100644 index 0000000..013119e --- /dev/null +++ b/public/modstagram_panel/src/components/sidebar.jsx @@ -0,0 +1,591 @@ +import React, { useEffect, useState } from "react"; +import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; +import DashboardIcon from "../assets/icons/dashboardIcon"; +import UsersIcon from "../assets/icons/UsersIcon"; +import PostsIcon from "../assets/icons/PostsIcon"; +import ProjectsIcon from "../assets/icons/ProjectsIcon"; +import SupportIcon from "../assets/icons/SupportIcon"; +import FinancialsIcon from "../assets/icons/FinancialsIcon"; +import CommentsIcon from "../assets/icons/CommentsIcon"; +import AdvertisingIcon from "../assets/icons/AdvertisingIcon"; +import ShopIcon from "../assets/icons/ShopIcon"; +import { GrLicense } from "react-icons/gr"; + +function Tooltip({ svgIcon, title }) { + const [showTooltip, setShowTooltip] = useState(false); + + return ( +
+ setShowTooltip(true)} + onMouseLeave={() => setShowTooltip(false)} + > + {svgIcon} + +
+
+
+ {title} +
+ + + +
+
+
+ ); +} + +const Sidebar = () => { + const { pathname } = useLocation(); + const navigate = useNavigate(); + const param = useParams(); + const [items, setItems] = useState([]); + const [isCollapsed, setIsCollapsed] = useState(false); + + useEffect(() => { + setItems([ + { + menu: "داشبورد", + subshow: false, + link: "/", + submenu: [], + icon(pathnamin) { + return ( + + } + title="داشبورد" + /> + ); + }, + }, + { + menu: "کاربران", + link: "/users", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="کاربران" + /> + ); + }, + }, + { + menu: "پست ها", + link: "/posts", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="پست ها" + /> + ); + }, + }, + { + menu: "پروژه ها", + link: "/projects", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="پروژه ها" + /> + ); + }, + }, + { + menu: "تیکت ها", + link: "/tickets", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="تیکت ها" + /> + ); + }, + }, + { + menu: "مالی", + link: "/financials", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="مالی" + /> + ); + }, + }, + { + menu: "نظرات", + link: "/comments", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="نظرات" + /> + ); + }, + }, + { + menu: "ویترین", + link: "/vitrine", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="ویترین" + /> + ); + }, + }, + { + menu: "نظرات ویترین", + link: "/vitrine-comments", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="نظرات ویترین" + /> + ); + }, + }, + { + menu: "فروشگاه", + link: "/shops", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="فروشگاه" + /> + ); + }, + }, + { + menu: "اموزشگاه", + link: "/academy", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="اموزشگاه" + /> + ); + }, + }, + { + menu: "مجوز", + link: "/license", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="مجوز" + /> + ); + }, + }, + { + menu: "ورژن برنامه", + link: "/version", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + + + } + title="ورژن برنامه" + /> + ); + }, + }, + { + menu: "تخصص", + link: "/expertise", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + + + } + title="تخصص" + /> + ); + }, + }, + { + menu: "قوانین مقررات", + link: "/terms", + subshow: false, + submenu: [], + icon(pathnamin) { + return ( + + } + title="قوانین مقررات" + /> + ); + }, + }, + { + menu: "خروج", + subshow: false, + link: "#", + submenu: [], + icon(pathnamin) { + return ( + + + + + + + + } + title="خروج" + /> + ); + }, + }, + ]); + }, []); + + useEffect(() => { + let indexOfItem = 0; + for (let item of items) { + indexOfItem++; + for (let submenu of item.submenu) { + if (pathname.replace("/", "").includes(submenu?.link.replace("/", ""))) { + setItems((prev) => + prev.map((sidebarItem, i) => + i === indexOfItem - 1 + ? { ...sidebarItem, subshow: true } + : sidebarItem + ) + ); + return; + } + } + } + }, [pathname, items]); + + const navigateToMenu = (item) => { + navigate(item?.link); + setItems((prev) => + prev.map((sidebarItem) => ({ ...sidebarItem, subshow: false })) + ); + }; + + const showSubMenu = (index) => { + setItems((prev) => + prev.map((sidebarItem, i) => + i === index + ? { ...sidebarItem, subshow: !sidebarItem.subshow } + : { ...sidebarItem, subshow: false } + ) + ); + }; + + const handleLogOut = () => { + localStorage.clear(); + document.getElementById("to_login").click(); + }; + + function refreshPage() { + setTimeout(() => { + window.location.reload(false); + }, 1000); + } + + const toggleSidebar = () => { + setIsCollapsed(!isCollapsed); + }; + + return ( +
+ + +
+ {items.map((item, index) => ( +
+ {item.submenu.length === 0 ? ( + + ) : ( + + )} + {!isCollapsed && ( +
+ {item.submenu.map((submenuItem, subIndex) => { + const isActive = pathname + .replace("/", "") + .includes(submenuItem.link.replace("/", "")); + return ( + + {submenuItem.menu} + + ); + })} +
+ )} +
+ ))} +
+
+ ); +}; + +export default Sidebar; \ No newline at end of file diff --git a/public/modstagram_panel/src/components/users/UserChangePassword.jsx b/public/modstagram_panel/src/components/users/UserChangePassword.jsx new file mode 100644 index 0000000..406a4f3 --- /dev/null +++ b/public/modstagram_panel/src/components/users/UserChangePassword.jsx @@ -0,0 +1,208 @@ +import React, { useState } from 'react'; +import axios from 'axios'; +import { BaseUrl } from '../BaseUrl'; +import toast, { Toaster } from 'react-hot-toast'; +import { FiEye, FiEyeOff, FiLock, FiCheckCircle } from 'react-icons/fi'; +import { useParams } from 'react-router-dom'; + +const UserChangePassword = () => { + const { id } = useParams(); // آیدی کاربر + + const [formData, setFormData] = useState({ + newPassword: '', + confirmPassword: '', + }); + const [showPassword, setShowPassword] = useState({ + new: false, + confirm: false, + }); + const [loading, setLoading] = useState(false); + const [errors, setErrors] = useState({}); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prev) => ({ ...prev, [name]: value })); + if (errors[name]) setErrors((prev) => ({ ...prev, [name]: '' })); + }; + + const togglePasswordVisibility = (field) => { + setShowPassword((prev) => ({ ...prev, [field]: !prev[field] })); + }; + + const validatePassword = (password) => { + const errors = []; + if (password.length < 8) errors.push('حداقل 8 کاراکتر'); + if (!/[A-Z]/.test(password)) errors.push('حداقل یک حرف بزرگ'); + if (!/[a-z]/.test(password)) errors.push('حداقل یک حرف کوچک'); + if (!/[0-9]/.test(password)) errors.push('حداقل یک عدد'); + return errors; + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + const newErrors = {}; + + // اعتبارسنجی پسورد جدید + const passwordErrors = validatePassword(formData.newPassword); + if (passwordErrors.length > 0) { + newErrors.newPassword = passwordErrors.join('، '); + } + + // تطابق پسوردها + if (formData.newPassword !== formData.confirmPassword) { + newErrors.confirmPassword = 'پسوردها مطابقت ندارند'; + } + + if (Object.keys(newErrors).length > 0) { + setErrors(newErrors); + return; + } + + setLoading(true); + + try { + await axios.post( + `https://app.modstagram.ir/api/v1/panel/users/change-password`, + { + userId: id, + password: formData.newPassword, // فقط پسورد جدید + } + + ); + + // toast.success('رمز عبور کاربر با موفقیت تغییر کرد', { + // icon: , + // style: { background: '#10b981', color: 'white' }, + // }); + + // ریست فرم + setFormData({ newPassword: '', confirmPassword: '' }); + } catch (err) { + const message = err.response?.data?.message || 'خطا در تغییر رمز عبور'; + toast.error(message, { style: { background: '#ef4444', color: 'white' } }); + } finally { + setLoading(false); + } + }; + + return ( + <> + +
+
+
+
+
+ +
+

تغییر رمز عبور کاربر

+

+ آیدی کاربر: {id} +

+
+ +
+ + {/* پسورد جدید */} +
+ +
+ + +
+ {errors.newPassword && ( +

{errors.newPassword}

+ )} +
+

= 8 ? 'text-green-400' : ''}> + حداقل 8 کاراکتر +

+

+ یک حرف بزرگ +

+

+ یک حرف کوچک +

+

+ یک عدد +

+
+
+ + {/* تأیید پسورد */} +
+ +
+ + +
+ {errors.confirmPassword && ( +

{errors.confirmPassword}

+ )} +
+ + {/* دکمه ارسال */} + +
+
+
+
+ + ); +}; + +export default UserChangePassword; \ No newline at end of file diff --git a/public/modstagram_panel/src/components/users/UserComments.jsx b/public/modstagram_panel/src/components/users/UserComments.jsx new file mode 100644 index 0000000..e2e3088 --- /dev/null +++ b/public/modstagram_panel/src/components/users/UserComments.jsx @@ -0,0 +1,234 @@ +import React, { useEffect, useState } from "react"; +import AdminHeader from "../../components/admin-header"; +import Sidebar from "../../components/sidebar"; +import { useNavigate, useParams } from "react-router-dom"; +import { BaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import Loading from "../../components/elements/loading"; +import Pagination from "../../components/Pagination"; +import Filters from "../Filters"; + +const Comments = ({}) => { + // دریافت id از props + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [allComments, setAllComments] = useState([]); // تمام کامنت‌ها + const [commentList, setCommentList] = useState([]); // کامنت‌های فیلتر شده + const [totalPages, setTotalPages] = useState(0); + const [currentPage, setCurrentPage] = useState(1); + const [filters, setFilters] = useState({ + startDate: "", + endDate: "", + status: "", + }); + + + const token = document.cookie + .split("; ") + .find((row) => row.startsWith("token=")) + ?.split("=")[1]; + + const param = useParams(); + const id = param?.id; + + const getCommentList = (page = 1) => { + setLoading(true); + + const { startDate, endDate, status } = filters; + const config = { + url: `${BaseUrl}/comments?limit=20&page=${page}${ + startDate ? "&startDate=" + startDate : "" + }${endDate ? "&endDate=" + endDate : ""}&status=${status}`, + + method: "GET", + headers: { + Authorization: `Bearer ${token}`, // اضافه کردن توکن به هدر + }, + }; + axios(config) + .then((res) => { + // setAllComments(res?.data?.comments); + setTotalPages(res?.data?.totalPages); + + // بررسی اینکه کامنت‌ها وجود دارند + const comments = res?.data?.comments || []; + + console.log(comments); + + // فیلتر فقط زمانی انجام میشه که creator وجود داشته باشه + const userComments = comments.filter( + (c) => c?.creator?._id === id + ); + + setCommentList(userComments); + setLoading(false); + + }) + .catch((err) => { + setLoading(false); + }); + }; + useEffect(() => { + getCommentList(currentPage); + }, [currentPage, filters]); + + return ( + <> +
+
+
+ {/* Filters */} + + +
+
+
+

+ عنوان پروژه +

+
+
+

+ نام کاربری سازنده +

+
+
+

+ نام و نام خانوادگی سازنده +

+
+
+

+ نام کاربری یوزر +

+
+
+

+ نام و نام خانوادگی یوزر +

+
+
+

+ تاریخ ثبت کامنت +

+
+
+

وضعیت

+
+
+

+
+
+
+ {loading ? ( +
+ +
+ ) : ( +
+ {Array.isArray(commentList) && commentList.length > 0 ? ( + commentList.map((comment, index) => { + return ( +
+
+

+ {comment?.project || "-"} +

+
+
+

+ {comment?.creator?.user_name || "-"} +

+
+
+

+ {comment?.creator?.first_name || ""}{" "} + {comment?.creator?.last_name || ""} +

+
+
+

+ {comment?.user?.user_name || "-"} +

+
+
+

+ {comment?.user?.first_name || ""}{" "} + {comment?.user?.last_name || ""} +

+
+
+

+ {comment?.createdAt || "-"} +

+
+
+
+

+ {comment?.status === "pending" + ? "در انتظار تایید" + : comment?.status === "accepted" + ? "تایید شده" + : comment?.status === "rejected" + ? "رد شده" + : "-"} +

+
+
+
+ +
+
+ ); + }) + ) : ( +

+ هیچ کامنتی یافت نشد. +

+ )} +
+ )} + setCurrentPage(page)} + /> +
+
+
+ + ); +}; + +export default Comments; diff --git a/public/modstagram_panel/src/components/users/UserDet.jsx b/public/modstagram_panel/src/components/users/UserDet.jsx new file mode 100644 index 0000000..4f92fac --- /dev/null +++ b/public/modstagram_panel/src/components/users/UserDet.jsx @@ -0,0 +1,607 @@ +import React, { useState } from "react"; +import { BaseUrl, ImageBaseUrl } from "../BaseUrl"; +import axios from "axios"; +import Modal from "react-modal"; +import toast from "react-hot-toast"; +import Sidebar from "../sidebar"; + +const customStyles = { + content: { + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + position: "fixed", + }, +}; + +const UserDet = ({ userData, id, getUserDet }) => { + const [isEditing, setIsEditing] = useState(false); + const [editedData, setEditedData] = useState({}); + const [modalIsOpen, setModalIsOpen] = useState(false); + const [modalImage, setModalImage] = useState(""); + + const openModal = (image) => { + setModalImage(image); + setModalIsOpen(true); + }; + + const closeModal = () => { + setModalIsOpen(false); + }; + + const handleChange = (e) => { + const { name, value } = e.target; + setEditedData((prevData) => ({ + ...prevData, + [name]: value, + })); + }; + + const handleSave = async () => { + try { + const response = await axios.put( + `${BaseUrl}/users/update?userId=${userData._id}`, + editedData, + { + headers: { + Authorization: `Bearer ${localStorage.getItem("token")}`, + }, + } + ); + setIsEditing(false); + toast.success("اطلاعات با موفقیت ذخیره شد"); + getUserDet(); + } catch (error) { + if (error.response && error.response.data && error.response.data.errors) { + error.response.data.errors.forEach((err) => { + toast.error( + typeof err.message === "string" ? err.message : "خطای ناشناخته" + ); + }); + } else { + toast.error("خطای ناشناخته"); + } + } + }; + + const acceptVerify = () => { + axios + .post(`${BaseUrl}/users/verify?userId=${id}`, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }) + .then(async (response) => { + toast.success(response?.data?.message); + getUserDet(); + }) + .catch((error) => { + toast.error(error?.response?.data?.message || "خطای ناشناخته"); + }); + }; + + const rejectVerify = () => { + axios + .post(`${BaseUrl}/users/reject?userId=${id}`, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }) + .then(async (response) => { + toast.success(response?.data?.message); + getUserDet(); + }) + .catch((error) => { + toast.error(error?.response?.data?.message || "خطای ناشناخته"); + }); + }; + + const acceptService = async (serviceId) => { + try { + // به‌روزرسانی آرایه services با تغییر status سرویس موردنظر به "true" + const updatedServices = userData.services.map((service) => + service._id === serviceId ? { ...service, status: "true" } : service + ); + + const response = await axios.put( + `${BaseUrl}/users/update?userId=${userData._id}`, + { services: updatedServices }, + { + headers: { + Authorization: `Bearer ${localStorage.getItem("token")}`, + Accept: "application/json", + "Content-Type": "application/json", + }, + } + ); + toast.success(response?.data?.message || "سرویس با موفقیت تأیید شد"); + getUserDet(); + } catch (error) { + toast.error(error?.response?.data?.message || "خطای ناشناخته"); + } + }; + + const rejectService = async (serviceId) => { + // فقط پیام رد نمایش داده می‌شود و status تغییر نمی‌کند + toast.success("سرویس رد شد"); + }; + + return ( +
+
+ + Post + + + {/* Profile Image */} +
+
+ تصویر پروفایل: +
+
+ openModal(ImageBaseUrl + userData?.profile_image)} + src={ImageBaseUrl + userData?.profile_image} + className="w-[200px] h-[200px] rounded-md" + alt="" + /> +
+
+ + {/* User Name */} +
+
+ نام کاربری: +
+
+ {isEditing ? ( + + ) : ( + userData?.user_name + )} +
+
+ + {/* First Name */} +
+
+ نام: +
+
+ {isEditing ? ( + + ) : ( + userData?.first_name + )} +
+
+ + {/* Last Name */} +
+
+ نام خانوادگی: +
+
+ {isEditing ? ( + + ) : ( + userData?.last_name + )} +
+
+ + {/* Mobile */} +
+
+ موبایل: +
+
+ {isEditing ? ( + + ) : ( + userData?.mobile + )} +
+
+ + {/* National Code */} +
+
+ کد ملی: +
+
+ {isEditing ? ( + + ) : ( + userData?.national_code + )} +
+
+ + {/* Province */} +
+
+ استان: +
+
+ {userData?.province?.name} +
+
+ + {/* City */} +
+
+ شهر: +
+
+ {userData?.city?.name} +
+
+ + {/* Address */} +
+
+ آدرس: +
+
+ {isEditing ? ( + + ) : ( + userData?.address + )} +
+
+ + {/* Height */} +
+
+ قد: +
+
+ {isEditing ? ( + + ) : ( + userData?.height + )} +
+
+ + {/* Weight */} +
+
+ وزن: +
+
+ {isEditing ? ( + + ) : ( + userData?.weight + )} +
+
+ + {/* Size */} +
+
+ سایز: +
+
+ {isEditing ? ( + + ) : ( + userData?.size + )} +
+
+ + {/* Bio */} +
+
+ بیو: +
+
+ {isEditing ? ( + + ) : ( + userData?.bio + )} +
+
+ + {/* Birthday */} +
+
+ تاریخ تولد: +
+
+ {userData?.birthday} +
+
+ + {/* Cooperation Abroad */} +
+
+ خارج از محدوده سکونت به من پیشنهاد بده: +
+
+ {userData?.cooperation_abroad == true ? "بله" : "خیر"} +
+
+ + {/* Conversation Projects */} +
+
+ پروژه با روابط عمومی بالا: +
+
+ {userData?.conversation_projects == true ? "بله" : "خیر"} +
+
+ + {/* Expertise */} +
+ {/* عنوان */} +
+ تخصص: +
+ + {/* تخصص + زیرتخصص‌ها */} +
+ {userData?.expertise} : + + {userData?.sub_expertise?.map((item, index) => ( + + {item} + {index !== userData?.sub_expertise?.length - 1 ? " _ " : ""} + + ))} +
+
+ + {/* Shaba */} +
+
+ شماره شبا: +
+
+ {isEditing ? ( + + ) : ( + userData?.shaba + )} +
+
+ + {/* National Card Image */} +
+
+ تصویر کارت ملی: +
+
+ + openModal(ImageBaseUrl + userData?.national_card_image) + } + src={ImageBaseUrl + userData?.national_card_image} + className="w-[200px] h-[200px] rounded-md" + alt="" + /> +
+
+ + {/* Last Online */} +
+
+ آخرین زمان ورود: +
+
+ {userData?.last_online} +
+
+ + {/* Created At */} +
+
+ تاریخ ثبت نام: +
+
+ {userData?.createdAt} +
+
+ + {/* Verification Status */} +
+
+ وضعیت مدارک: +
+
+

+ {userData?.is_verified === "verified" + ? "تایید شده" + : userData?.is_verified === "pending" + ? "در انتظار تایید" + : ""} +

+ + +
+
+ + {/* Services Section */} +
+
+ خدمات: +
+
+ {userData?.services?.length > 0 ? ( + userData.services.map((service) => ( +
+ {service.title} openModal(ImageBaseUrl + service.image)} + /> +
+

عنوان: {service.title}

+

قیمت اصلی: {service.originalPrice} تومان

+

قیمت با تخفیف: {service.discountPrice} تومان

+

درصد تخفیف: {service.discountPercentage}%

+

+ وضعیت:{" "} + {service.status === "true" + ? "تأیید شده" + : service.status === "UnderReview" + ? "در انتظار بررسی" + : "رد شده"} +

+
+
+ +
+
+ )) + ) : ( +

هیچ سرویسی یافت نشد

+ )} +
+
+ + {/* User Rate */} +
+
+ امتیاز کاربر: +
+
+ {userData?.rate} +
+
+ + {/* User Level */} +
+
+ سطح کاربر: +
+
+ {userData?.user_level} +
+
+ + {/* Save Button */} +
+ {isEditing ? ( + + ) : ( + + )} +
+
+
+ ); +}; + +export default UserDet; diff --git a/public/modstagram_panel/src/components/users/UserFinancial.jsx b/public/modstagram_panel/src/components/users/UserFinancial.jsx new file mode 100644 index 0000000..59471a3 --- /dev/null +++ b/public/modstagram_panel/src/components/users/UserFinancial.jsx @@ -0,0 +1,9 @@ +import React from 'react' + +const UserFinancial = () => { + return ( +
UserFinancial
+ ) +} + +export default UserFinancial \ No newline at end of file diff --git a/public/modstagram_panel/src/components/users/UserMessages.jsx b/public/modstagram_panel/src/components/users/UserMessages.jsx new file mode 100644 index 0000000..e03c8e5 --- /dev/null +++ b/public/modstagram_panel/src/components/users/UserMessages.jsx @@ -0,0 +1,9 @@ +import React from 'react' + +const UserMessages = () => { + return ( +
UserMessages
+ ) +} + +export default UserMessages \ No newline at end of file diff --git a/public/modstagram_panel/src/components/users/UserPosts.jsx b/public/modstagram_panel/src/components/users/UserPosts.jsx new file mode 100644 index 0000000..0a8fe3e --- /dev/null +++ b/public/modstagram_panel/src/components/users/UserPosts.jsx @@ -0,0 +1,217 @@ +import React, { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { BaseUrl, ImageBaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import Loading from "../../components/elements/loading"; +import Pagination from "../../components/Pagination"; + +const UserPosts = ({ id }) => { + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [allPosts, setAllPosts] = useState([]); // تمام پست‌ها + const [postsList, setPostsList] = useState([]); // پست‌های صفحه جاری + const [totalPages, setTotalPages] = useState(0); + const [currentPage, setCurrentPage] = useState(1); + const [filters, setFilters] = useState({ + startDate: "", + endDate: "", + status: "", + }); + + const itemsPerPage = 10; // تعداد آیتم در هر صفحه + + // دریافت همه پست‌ها از API (بدون user_id) + const fetchAllPosts = () => { + setLoading(true); + const { startDate, endDate, status } = filters; + + let url = `${BaseUrl}/posts?limit=1000`; // گرفتن تعداد زیاد برای فیلتر فرانت + if (startDate) url += `&startDate=${startDate}`; + if (endDate) url += `&endDate=${endDate}`; + if (status) url += `&status=${status}`; + + axios + .get(url) + .then((res) => { + const posts = res?.data?.posts || []; + setAllPosts(posts); + setLoading(false); + }) + .catch(() => setLoading(false)); + }; + + // فیلتر و صفحه‌بندی روی فرانت + const paginatePosts = () => { + const filteredPosts = allPosts.filter((post) => post.user_id === id); + const startIndex = (currentPage - 1) * itemsPerPage; + const paginatedPosts = filteredPosts.slice( + startIndex, + startIndex + itemsPerPage + ); + setPostsList(paginatedPosts); + setTotalPages(Math.ceil(filteredPosts.length / itemsPerPage)); + }; + + useEffect(() => { + fetchAllPosts(); + }, [filters]); + + useEffect(() => { + paginatePosts(); + }, [allPosts, currentPage, id]); + + return ( + <> +
+
+
+ {/* Table Header */} +
+
+
+

تصویر

+
+
+

نام کاربری

+
+
+

نوع کاربری

+
+
+

نام و نام خانوادگی

+
+
+

موبایل

+
+
+

کد ملی

+
+
+

تاریخ ثبت پست

+
+
+

وضعیت

+
+
+

جزئیات

+
+
+
+ + {loading ? ( +
+ +
+ ) : ( +
+ {postsList?.map((post, index) => ( +
+
+
+ {post?.files?.length > 0 ? ( + post.files[0].type === "image" ? ( + Post + ) : ( +
+
+

{post?.user_name}

+
+
+ {" "} +

+ {post?.user_type === "employer" + ? "کارفرما" + : post?.user_type === "user" + ? post?.expertise || "-" + : "-"} +

+
+
+

+ {post?.first_name} {post?.last_name} +

+
+
+

{post?.mobile}

+
+
+

{post?.national_code}

+
+
+

{post?.createdAt}

+
+
+

+ {post?.status === "accept" + ? "منتشر شده" + : post?.status === "pending" + ? "در انتظار تایید" + : "رد شده"} +

+
+
+ +
+
+
+ ))} +
+ )} + + post.user_id === id).length} + totalPages={totalPages} + currentPage={currentPage} + onPageChange={(page) => setCurrentPage(page)} + /> +
+
+
+ + ); +}; + +export default UserPosts; diff --git a/public/modstagram_panel/src/components/users/UserWorkroom.jsx b/public/modstagram_panel/src/components/users/UserWorkroom.jsx new file mode 100644 index 0000000..1d6e7bb --- /dev/null +++ b/public/modstagram_panel/src/components/users/UserWorkroom.jsx @@ -0,0 +1,200 @@ +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; +import { AppBaseUrl } from '../BaseUrl'; +import { useParams } from 'react-router-dom'; +import moment from 'moment-jalaali'; +import { FiUser, FiCalendar, FiClock, FiCheckCircle, FiXCircle, FiAlertCircle } from 'react-icons/fi'; + +const UserWorkroom = () => { + const [projects, setProjects] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const param = useParams(); + const id = param?.id; + + useEffect(() => { + const fetchProjects = async () => { + try { + const response = await axios.get(`${AppBaseUrl}/offers`, { + params: { status_filter: "دریافت", id }, + }); + + const offersFromSender = response.data.offerbyidsender?.docs || []; + const offersFromReceiver = response.data.offerbyid?.docs || []; + + const mergedOffers = [...offersFromSender, ...offersFromReceiver]; + const sortedOffers = mergedOffers.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); + + setProjects(sortedOffers); + } catch (err) { + setError('خطا در بارگذاری درخواست‌ها'); + } finally { + setLoading(false); + } + }; + + fetchProjects(); + }, [id]); + + const formatJalaliDate = (date) => { + if (!date) return 'نامشخص'; + return moment(date).format('jYYYY/jMM/jDD - HH:mm'); + }; + + const StatusTag = ({ status }) => { + const config = { + accepted: { text: 'تایید شده', color: 'bg-green-900/30 text-green-300 border border-green-800', icon: }, + rejected: { text: 'رد شده', color: 'bg-red-900/30 text-red-300 border border-red-800', icon: }, + pending: { text: 'در انتظار', color: 'bg-yellow-900/30 text-yellow-300 border border-yellow-800', icon: }, + }; + + const { text, color, icon } = config[status] || { text: status, color: 'bg-gray-800 text-gray-400 border border-gray-700', icon: null }; + + return ( + + {icon} + {text} + + ); + }; + + if (loading) { + return ( +
+
+
+ ); + } + + if (error) { + return ( +
+

{error}

+
+ ); + } + + if (projects.length === 0) { + return ( +
+ +

هیچ درخواستی یافت نشد.

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

+ + لیست درخواست‌ها +

+

مجموع: {projects.length} درخواست

+
+ + {/* موبایل: کارت‌ها */} +
+ {projects.map((project) => ( +
+
+
+
+

درخواست‌کننده

+

+ {project.sender + ? `${project.sender.first_name} ${project.sender.last_name}` + : 'نامشخص'} +

+

@{project.sender?.user_name}

+
+ +
+ +
+

درخواست‌شونده

+

+ {project.receiver + ? `${project.receiver.first_name} ${project.receiver.last_name}` + : 'نامشخص'} +

+

@{project.receiver?.user_name}

+
+ +
+ + {formatJalaliDate(project.createdAt)} +
+ {project.updatedAt && ( +
+ + آخرین تغییر: {formatJalaliDate(project.updatedAt)} +
+ )} +
+
+ ))} +
+ + {/* دسکتاپ: جدول */} +
+ + + + + + + + + + + + {projects.map((project) => ( + + + + + + + + ))} + +
درخواست‌کنندهدرخواست‌شوندهوضعیتتاریخ ثبتآخرین تغییر
+
+

+ {project.sender + ? `${project.sender.first_name} ${project.sender.last_name}` + : 'نامشخص'} +

+

@{project.sender?.user_name}

+
+
+
+

+ {project.receiver + ? `${project.receiver.first_name} ${project.receiver.last_name}` + : 'نامشخص'} +

+

@{project.receiver?.user_name}

+
+
+ + + {formatJalaliDate(project.createdAt)} + + {project.updatedAt ? formatJalaliDate(project.updatedAt) : '—'} +
+
+
+
+ ); +}; + +export default UserWorkroom; \ No newline at end of file diff --git a/public/modstagram_panel/src/index.js b/public/modstagram_panel/src/index.js new file mode 100644 index 0000000..b6adba9 --- /dev/null +++ b/public/modstagram_panel/src/index.js @@ -0,0 +1,73 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './assets/css/index.css'; +import App from './App'; +import toast from 'react-hot-toast'; +import axios from 'axios'; +import { BaseUrl } from './components/BaseUrl'; + +const root = ReactDOM.createRoot(document.getElementById('root')); + +const handleUnauthorized = () => { + localStorage.removeItem("userData"); + localStorage.removeItem("token"); + localStorage.removeItem("login"); + window.location = "/login"; +}; + +const getToken = () => { + const token = localStorage.getItem("token"); + return token == null ? "" : token; +}; +axios.interceptors.request.use( + (config) => { + if (!config.url.endsWith('/panel/login')) { + config.headers["Authorization"] = `Bearer ${getToken()}`; + } + return config; + }, + (error) => { + return Promise.reject(error); + } +); + +axios.interceptors.response.use( + (response) => { + if (response.data.message && response.data.message != "") + toast.success(response.data.message); + return response; + }, + (error) => { + if (error.response.status == 422) { + if (error.response.data.errors) { + Object.keys(error.response.data.errors).map((err) => + error.response.data.errors[err].map((item) => toast.error(item)) + ); + } + + } else if (error.response.status == 401) { + handleUnauthorized(); + } else if ( + error.response.status == 429 || + error.response.status == 500 || + error.response.status == 503 + ) { + toast.error("خطایی رخ داده"); + } else if (error.response.status == 403) { + // window.location.reload(); + toast.error( + "متاسفانه دسترسی شما به بخش هایی از این صفحه محدود شده است" + ); + } else { + toast.error(error.response.data.message); + } + + return Promise.reject(error); + } +); +root.render( + + + +); + diff --git a/public/modstagram_panel/src/pages/Dashboard.jsx b/public/modstagram_panel/src/pages/Dashboard.jsx new file mode 100644 index 0000000..8418a96 --- /dev/null +++ b/public/modstagram_panel/src/pages/Dashboard.jsx @@ -0,0 +1,50 @@ +import React, { useState } from "react"; +import { Link } from "react-router-dom"; +import AdminHeader from "../components/admin-header"; +import Sidebar from "../components/sidebar"; + +const items = [ + { id: 1, label: "کاربران جدید", href: "/users?status=pending" }, + { id: 2, label: "پست‌های جدید", href: "/posts?status=pending" }, + { id: 3, label: "بیلبورد جدید", href: "/vitrine?status=pending" }, + { id: 4, label: "نظرات جدید", href: "/comments?status=pending" }, + { id: 5, label: "تیکت جدید", href: "/tickets?status=pending" }, + { id: 6, label: "نظرات بیلبورد جدید", href: "/vitrine-comments?status=pending" }, +]; + +const Dashboard = () => { + const [active, setActive] = useState(null); + + return ( + <> + +
+
+
+ +
+
+ {items.map((item) => ( + setActive(item.id)} + className={`cursor-pointer rounded-xl border p-6 shadow-md transition block + ${ + active === item.id + ? "bg-cyan-600 text-white font-bold shadow-lg scale-105" + : "bg-[#232a31] hover:bg-[#2a3036] text-gray-200" + }`} + > + {item.label} + + ))} +
+
+
+
+ + ); +}; + +export default Dashboard; diff --git a/public/modstagram_panel/src/pages/Login.jsx b/public/modstagram_panel/src/pages/Login.jsx new file mode 100644 index 0000000..78bf9d2 --- /dev/null +++ b/public/modstagram_panel/src/pages/Login.jsx @@ -0,0 +1,116 @@ +import React, { useEffect, useState } from "react"; +import { Link, useNavigate } from "react-router-dom"; +import * as Yup from "yup"; +import Loading from "../components/elements/loading"; +import { useAuth } from "../utils/AuthProvider"; +import axios from "axios"; +import { BaseUrl } from "../components/BaseUrl"; +import toast, { useToaster } from "react-hot-toast"; + +const Login = () => { + const navigate = useNavigate(); + const [loading, setloading] = useState(false); + const token = useAuth(); + const [userName, setUserName] = useState("") + const [password, setPassword] = useState("") + useEffect(() => { + if (token !== null) { + navigate("/", { replace: true }); + } + }, []); + const loginHandler = () => { + const data = { + user_name: userName, + password, + }; + axios + .post(`${BaseUrl}/login`, data, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }) + .then(async (response) => { + try { + localStorage.setItem("token", response?.data?.token); + document.getElementById("to_dashboard").click(); + } catch (error) { + toast.error("اطلاعات وارد شده صحیح نمیباشد"); + } + }) + .catch(function (error) { + toast.error(error?.response?.data?.message); + }); + } + function refreshPage() { + setTimeout(() => { + window.location.reload(false); + }, 1000); + } + return ( +
+ +
+
+
+
+ ورود +
+
+
+ + setUserName(e.target.value)} + /> +
+
+ + setPassword(e.target.value)} + /> +
+
+ +
+
+
+
+
+
+ ); +}; + +export default Login; diff --git a/public/modstagram_panel/src/pages/academies/academies.jsx b/public/modstagram_panel/src/pages/academies/academies.jsx new file mode 100644 index 0000000..5a818c5 --- /dev/null +++ b/public/modstagram_panel/src/pages/academies/academies.jsx @@ -0,0 +1,412 @@ +// src/pages/Academies.js +import React, { useState, useEffect, useCallback } from "react"; +import toast from "react-hot-toast"; +import { + getAcademies, + updateAcademyStatus, + deleteAcademy, + getAcademyStats +} from "../../components/adminApi"; // اصلاح مسیر +import Layout from "../../components/academy/Layout"; +import { FaSearch, FaEdit, FaTrash, FaEye, FaStar, FaUniversity, FaTimes } from "react-icons/fa"; +import { ImageBaseUrl } from "../../components/BaseUrl"; + +// در صورت نیاز به BASE_URL +const IMAGE_BASE_URL = ImageBaseUrl|| ""; + +const Academies = () => { + const [academies, setAcademies] = useState([]); + const [stats, setStats] = useState(null); + const [loading, setLoading] = useState(true); + const [page, setPage] = useState(1); + const [totalPages, setTotalPages] = useState(1); + const [search, setSearch] = useState(""); + const [searchInput, setSearchInput] = useState(""); + const [showModal, setShowModal] = useState(false); + const [selectedAcademy, setSelectedAcademy] = useState(null); + + const fetchAcademies = useCallback(async () => { + setLoading(true); + try { + const response = await getAcademies({ page, limit: 12, search }); + console.log("Academies response:", response.data); + + if (response.data.success) { + const responseData = response.data.data; + setAcademies(responseData?.academies || []); + setStats(responseData?.stats || null); + setTotalPages(responseData?.pagination?.totalPages || 1); + } else { + toast.error(response.data.message || "خطا در دریافت آکادمی‌ها"); + } + } catch (error) { + console.error("Error fetching academies:", error); + toast.error("خطا در دریافت آکادمی‌ها"); + } finally { + setLoading(false); + } + }, [page, search]); + + const fetchStats = async () => { + try { + const response = await getAcademyStats(); + console.log("Stats response:", response.data); + + if (response.data.success) { + setStats(response.data.data); + } + } catch (error) { + console.error("Error fetching stats:", error); + } + }; + + useEffect(() => { + fetchAcademies(); + fetchStats(); + }, [fetchAcademies]); + + const handleStatusChange = async (academyId, status) => { + try { + const response = await updateAcademyStatus({ academyId, status }); + if (response.data.success) { + toast.success("وضعیت آکادمی تغییر کرد"); + fetchAcademies(); + fetchStats(); + } else { + toast.error(response.data.message || "خطا در تغییر وضعیت"); + } + } catch (error) { + console.error("Error updating status:", error); + toast.error("خطا در تغییر وضعیت"); + } + }; + + const handleDelete = async (academyId) => { + if (window.confirm("آیا از حذف این آکادمی مطمئن هستید؟\nتوجه: با حذف آکادمی، تمام دوره‌های آن نیز حذف خواهند شد.")) { + try { + const response = await deleteAcademy(academyId); + if (response.data.success) { + toast.success("آکادمی حذف شد"); + fetchAcademies(); + fetchStats(); + } else { + toast.error(response.data.message || "خطا در حذف آکادمی"); + } + } catch (error) { + console.error("Error deleting academy:", error); + toast.error("خطا در حذف آکادمی"); + } + } + }; + + const handleSearch = (e) => { + e.preventDefault(); + setSearch(searchInput); + setPage(1); + }; + + const handleClearSearch = () => { + setSearchInput(""); + setSearch(""); + setPage(1); + }; + + const getImageUrl = (imagePath) => { + if (!imagePath) return null; + if (imagePath.startsWith("http")) return imagePath; + return `${IMAGE_BASE_URL}${imagePath}`; + }; + + const getStatusText = (status) => { + const statusMap = { + active: { text: "فعال", className: "bg-green-100 text-green-700" }, + inactive: { text: "غیرفعال", className: "bg-gray-100 text-gray-700" }, + blocked: { text: "مسدود", className: "bg-red-100 text-red-700" } + }; + return statusMap[status] || { text: status || "فعال", className: "bg-gray-100 text-gray-700" }; + }; + + + + + if (loading && page === 1) { + return ( + +
+
+
+
+ ); + } + + return ( + +
+
+

مدیریت آکادمی‌ها

+

لیست تمام آکادمی‌های ثبت شده در سامانه

+
+ + {/* Stats */} + {stats && ( +
+
+
+
+

تعداد آکادمی‌ها

+

{stats.totalAcademies?.toLocaleString() || 0}

+
+ +
+
+
+

میانگین امتیاز

+

{stats.avgRate?.toFixed(1) || 0}

+
+
+

مجموع امتیاز

+

{stats.totalRate?.toLocaleString() || 0}

+
+
+ )} + + {/* Search */} +
+
+ setSearchInput(e.target.value)} + className="w-full px-4 py-3 pl-12 pr-4 border rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500" + /> + + {searchInput && ( + + )} +
+
+ + {/* Search result info */} + {search && ( +
+ نتایج جستجو برای: {search} + +
+ )} + + {/* Academies Grid */} + {academies.length === 0 && !loading ? ( +
+ +

آکادمی‌ای یافت نشد

+ {search && ( + + )} +
+ ) : ( +
+ {academies.map((academy) => { + const statusInfo = getStatusText(academy.status); + return ( +
+
+
+ + {statusInfo.text} + +
+
+
+
+ {academy.academy_image ? ( + {academy.academy_name} + ) : ( +
+ +
+ )} +
+
+
+
+ +
+
+
+

{academy.academy_name}

+

مدیر: {academy.userId?.user_name || "نامشخص"}

+
+
+ + {academy.rate || 0} +
+
+ +

+ {academy.bio || "توضیحاتی ثبت نشده"} +

+ +
+
+ + +
+ {/* */} +
+
+
+ ); + })} +
+ )} + + {/* Pagination */} + {totalPages > 1 && ( +
+ + + صفحه {page} از {totalPages} + + +
+ )} + + {/* Modal */} + {showModal && selectedAcademy && ( +
+
+
+

جزئیات آکادمی

+ +
+
+
+
+ {selectedAcademy.academy_image ? ( + {selectedAcademy.academy_name} + ) : ( +
+ +
+ )} +
+
+ +
+ نام آکادمی: + {selectedAcademy.academy_name} +
+
+ مدیر: + {selectedAcademy.userId?.user_name || "-"} +
+
+ ایمیل: + {selectedAcademy.userId?.email || "-"} +
+
+ امتیاز: + {selectedAcademy.rate || 0} +
+
+ تعداد نظرات: + {selectedAcademy.number_of_rate || 0} +
+
+ شماره شبا: + {selectedAcademy.sheba || "ثبت نشده"} +
+
+ تاریخ ثبت: + {new Date(selectedAcademy.createdAt).toLocaleDateString("fa-IR")} +
+
+

درباره:

+

{selectedAcademy.bio || "توضیحاتی ثبت نشده"}

+
+
+
+ +
+
+
+ )} +
+
+ ); +}; + +export default Academies; \ No newline at end of file diff --git a/public/modstagram_panel/src/pages/academy/academy.jsx b/public/modstagram_panel/src/pages/academy/academy.jsx new file mode 100644 index 0000000..dcdee9f --- /dev/null +++ b/public/modstagram_panel/src/pages/academy/academy.jsx @@ -0,0 +1,293 @@ +// src/pages/Dashboard.js +import React, { useState, useEffect } from "react"; +import Layout from "../../components/academy/Layout"; +import { + getPaymentStats, + getCourseStats, + getPurchasedStats, + getAcademyStats, + getPayments, + getCourses +} from "../../components/adminApi"; +import { Link } from "react-router-dom"; +import { FaWallet, FaBook, FaShoppingCart, FaUniversity, FaStar } from "react-icons/fa"; + +const Dashboard = () => { + const [stats, setStats] = useState({ + payments: { totalAmount: 0, totalCount: 0, pendingCount: 0, successCount: 0, settledCount: 0 }, + courses: { totalCourses: 0, acceptCount: 0, pendingCount: 0, normalCount: 0, proCount: 0, legendCount: 0 }, + purchased: { totalPurchases: 0, uniqueUsers: 0 }, + academies: { totalAcademies: 0, avgRate: 0 } + }); + const [loading, setLoading] = useState(true); + const [recentPayments, setRecentPayments] = useState([]); + const [recentCourses, setRecentCourses] = useState([]); + + useEffect(() => { + const fetchStats = async () => { + setLoading(true); + try { + const [paymentsRes, coursesRes, purchasedRes, academiesRes] = await Promise.all([ + getPaymentStats(), + getCourseStats(), + getPurchasedStats(), + getAcademyStats() + ]); + + console.log("Payment Stats:", paymentsRes.data); + console.log("Course Stats:", coursesRes.data); + console.log("Purchased Stats:", purchasedRes.data); + console.log("Academy Stats:", academiesRes.data); + + setStats({ + payments: paymentsRes.data?.data || {}, + courses: coursesRes.data?.data || {}, + purchased: purchasedRes.data?.data || {}, + academies: academiesRes.data?.data || {} + }); + } catch (error) { + console.error("Error fetching stats:", error); + } finally { + setLoading(false); + } + }; + + const fetchRecentData = async () => { + try { + // دریافت 5 پرداخت آخر + const paymentsRes = await getPayments({ page: 1, limit: 5 }); + if (paymentsRes.data?.success) { + setRecentPayments(paymentsRes.data.data?.payments || []); + } + + // دریافت 5 دوره آخر + const coursesRes = await getCourses({ page: 1, limit: 5 }); + if (coursesRes.data?.success) { + setRecentCourses(coursesRes.data.data?.courses || []); + } + } catch (error) { + console.error("Error fetching recent data:", error); + } + }; + + fetchStats(); + fetchRecentData(); + }, []); + + const statCards = [ + // { + // title: "مجموع فروش", + // value: stats.payments.totalAmount?.toLocaleString() || 0, + // unit: "تومان", + // icon: , + // bgColor: "bg-blue-100", + // textColor: "text-blue-600", + // iconBg: "bg-blue-500" + // }, + { + title: "تعداد پرداخت‌ها", + value: stats.payments.totalCount || 0, + unit: "", + icon: , + bgColor: "bg-green-100", + textColor: "text-green-600", + iconBg: "bg-green-500" + }, + { + title: "دوره‌های تایید شده", + value: stats.courses.acceptCount || 0, + unit: "", + subValue: `در انتظار: ${stats.courses.pendingCount || 0}`, + icon: , + bgColor: "bg-purple-100", + textColor: "text-purple-600", + iconBg: "bg-purple-500" + }, + { + title: "کل دوره‌ها", + value: stats.courses.totalCourses || 0, + unit: "", + icon: , + bgColor: "bg-indigo-100", + textColor: "text-indigo-600", + iconBg: "bg-indigo-500" + }, + { + title: "خریدهای انجام شده", + value: stats.purchased.totalPurchases || 0, + unit: "", + icon: , + bgColor: "bg-orange-100", + textColor: "text-orange-600", + iconBg: "bg-orange-500" + }, + { + title: "کاربران خریدار", + value: stats.purchased.uniqueUsers || 0, + unit: "نفر", + icon: , + bgColor: "bg-rose-100", + textColor: "text-rose-600", + iconBg: "bg-rose-500" + }, + { + title: "آکادمی‌ها", + value: stats.academies.totalAcademies || 0, + unit: "", + icon: , + bgColor: "bg-teal-100", + textColor: "text-teal-600", + iconBg: "bg-teal-500" + }, + // { + // title: "میانگین امتیاز", + // value: stats.academies.avgRate?.toFixed(1) || 0, + // unit: "از 5", + // icon: , + // bgColor: "bg-yellow-100", + // textColor: "text-yellow-600", + // iconBg: "bg-yellow-500" + // } + ]; + + const getStatusBadge = (status) => { + const badges = { + pending: "bg-yellow-100 text-yellow-700", + accept: "bg-green-100 text-green-700", + success: "bg-blue-100 text-blue-700", + settled: "bg-purple-100 text-purple-700", + }; + const texts = { + pending: "در انتظار", + accept: "تایید شده", + success: "موفق", + settled: "تسویه شده", + }; + return ( + + {texts[status] || status} + + ); + }; + + console.log(stats); + + + if (loading) { + return ( + +
+
+
+
+ ); + } + + return ( + +
+
+

داشبورد مدیریتی

+

خلاصه وضعیت سیستم

+
+ + {/* Stat Cards */} +
+ {statCards.map((card, index) => ( +
+
+
+

{card.title}

+

+ {card.value} + {card.unit && {card.unit}} +

+ {card.subValue && ( +

{card.subValue}

+ )} +
+
+
{card.icon}
+
+
+
+ ))} +
+ + {/* Recent Payments & Courses */} +
+ {/* آخرین پرداخت‌ها */} +
+
+

آخرین پرداخت‌ها

+ + مشاهده همه + +
+
+ {recentPayments.length === 0 ? ( +
+ + هیچ پرداختی یافت نشد +
+ ) : ( +
+ {recentPayments.map((payment) => ( +
+
+

{payment.course_id?.cuorse_name || "-"}

+

{payment.user_id?.user_name}

+
+
+

{payment.price?.toLocaleString()} تومان

+ {getStatusBadge(payment.status)} +
+
+ ))} +
+ )} +
+
+ + {/* آخرین دوره‌ها */} +
+
+

آخرین دوره‌ها

+ + مشاهده همه + +
+
+ {recentCourses.length === 0 ? ( +
+ + هیچ دوره‌ای یافت نشد +
+ ) : ( +
+ {recentCourses.map((course) => ( +
+
+

{course.cuorse_name}

+

{course.teacher_name}

+
+
+

{parseInt(course.price).toLocaleString()} تومان

+ {getStatusBadge(course.status)} +
+
+ ))} +
+ )} +
+
+
+
+
+ ); +}; + +export default Dashboard; \ No newline at end of file diff --git a/public/modstagram_panel/src/pages/comments/CommentDetail.jsx b/public/modstagram_panel/src/pages/comments/CommentDetail.jsx new file mode 100644 index 0000000..00407a9 --- /dev/null +++ b/public/modstagram_panel/src/pages/comments/CommentDetail.jsx @@ -0,0 +1,286 @@ +import React, { useEffect, useState } from 'react' +import { useNavigate, useParams } from 'react-router-dom'; +import { BaseUrl } from '../../components/BaseUrl'; +import axios from 'axios'; +import AdminHeader from '../../components/admin-header'; +import Sidebar from '../../components/sidebar'; +import Loading from '../../components/elements/loading'; +import toast from 'react-hot-toast'; + +const CommentDetail = () => { + const navigate = useNavigate(); + const param = useParams(); + const id = param?.id; + const [loading, setLoading] = useState(false); + const [commentDetails, setCommentDetails] = useState([]); + const [commentStatus, setCommentStatus] = useState(''); + const [editingComment, setEditingComment] = useState(false); + const [newComment, setNewComment] = useState(''); + const getCommentDetails = (page = 1) => { + setLoading(true); + const config = { + url: `${BaseUrl}/comments/detail?comment_id=${id}`, + method: "GET", + }; + axios(config) + .then((res) => { + setCommentDetails(res?.data?.comment); + setLoading(false); + setNewComment(res?.data?.comment?.comment) + }) + .catch((err) => { + setLoading(false); + }); + }; + useEffect(() => { + getCommentDetails(); + }, [id]); + + const acceptComment = () => { + const data = { + id: commentDetails?._id, + status: "accepted", + text: newComment + }; + axios + .post(`${BaseUrl}/comments/accept`, data, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }) + .then(async (response) => { + try { + toast.success(response?.data?.message) + getCommentDetails() + } catch (error) { + if ( + error?.response?.data?.error + ) { + toast.error(error.response.data.error); + } else { + // نمایش پیام خطا برای سایر موارد + toast.error("خطای ناشناخته"); + } + } + }) + .catch((error) => { + console.error(error); + toast.show(error?.response?.data?.message, { + type: "danger", + placement: "top", + duration: 4000, + offset: 30, + animationType: "slide-in", + }); + }); + }; + + const rejectComment = () => { + const data = { + id: commentDetails?._id, + status: "rejected" + }; + axios + .post(`${BaseUrl}/comments/accept`, data, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }) + .then(async (response) => { + try { + toast.success(response?.data?.message) + getCommentDetails() + } catch (error) { + if ( + error?.response?.data?.error + ) { + toast.error(error.response.data.error); + } else { + // نمایش پیام خطا برای سایر موارد + toast.error("خطای ناشناخته"); + } + } + }) + .catch((error) => { + console.error(error); + toast.show(error?.response?.data?.message, { + type: "danger", + placement: "top", + duration: 4000, + offset: 30, + animationType: "slide-in", + }); + }); + }; + + const handleEditComment = () => { + // ارسال درخواست برای ویرایش کامنت به سرور + // سپس بروزرسانی متغیر مربوط به متن کامنت + setEditingComment(true); + }; + return (<> + {loading && } + {!loading && commentDetails && ( + <> + +
+
+
+
+
+

+ اطلاعات کامنت: +

+ +
+
+
+
+ عنوان پروژه: +
+
+ {commentDetails?.project} +
+
+
+
+ نام کاربری سازنده: +
+
+ {commentDetails?.creator?.user_name} +
+
+
+
+ نام و نام خانوادگی سازنده: +
+
+ {commentDetails?.creator?.first_name} {commentDetails?.creator?.last_name} +
+
+
+
+ نام کاربری کاربر: +
+
+ {commentDetails?.user?.user_name} +
+
+
+
+ نام و نام خانوادگی کاربر: +
+
+ {commentDetails?.user?.first_name} {commentDetails?.user?.last_name} +
+
+
+
+ تاریخ ثبت کامنت: +
+
+ {commentDetails?.createdAt} +
+
+
+
+ تعداد ستاره: +
+
+ {commentDetails?.rating} +
+
+
+
+ متن کامنت: +
+
+ {commentDetails?.comment} +
+
+
+
+ وضعیت: +
+
+ {commentDetails?.status + === "pending" ? + "در انتظار تایید" : + commentDetails?.status == "accepted" ? + "تایید شده" : + "رد شده" + } +
+
+
+
+ {!editingComment ? ( + <> + + + + + ) : ( + <> +
+ + +
+ + +
+
+
+
+
+ دلیل رد پروژه: +
+
+ {projectDetails?.reject_reason} +
+
+
+
+ کاربران پیشنهاد دهنده : +
+
+
+
+
+

+ نام و نام خانوادگی +

+
+
+

+ نام کاربری +

+
+
+

+ قیمت پینهادی +

+
+
+

+ زمان پیشنهادی +

+
+
+
+ {projectDetails?.requested_users?.map( + (user, index) => ( +
+
+
+
+ +

+ { + user?.first_name + }{" "} + { + user?.last_name + } +

+
+
+
+

+ { + user?.user_name + } +

+
+
+

+ {Number( + user?.price + ).toLocaleString()} +

+
+
+

+ { + user?.time + } +

+
+ +
+

+ +

+
+
+
+ ) + )} +
+
+
+
+ + )} + + + + + ); +}; + +export default ProjectDetail; diff --git a/public/modstagram_panel/src/pages/projects/Projects.jsx b/public/modstagram_panel/src/pages/projects/Projects.jsx new file mode 100644 index 0000000..4fe6029 --- /dev/null +++ b/public/modstagram_panel/src/pages/projects/Projects.jsx @@ -0,0 +1,161 @@ +import React, { useEffect, useState, useMemo } from "react"; +import AdminHeader from "../../components/admin-header"; +import Sidebar from "../../components/sidebar"; +import { useNavigate } from "react-router-dom"; +import { BaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import Loading from "../../components/elements/loading"; +import toast from "react-hot-toast"; +import Pagination from "../../components/Pagination"; +import Filters from "../../components/Filters"; + +const statusMap = { + all: { label: "همه", class: "text-yellow-300" }, + pre_payment: { label: "پرداخت نشده", class: "text-yellow-300" }, + paid: { label: "در دست بررسی", class: "text-yellow-300" }, + accepted: { label: "منتشر شده", class: "text-green-300" }, + ongoing: { label: "در دست اقدام", class: "text-green-300" }, + done: { label: "انجام شده", class: "text-green-300" }, + rejected: { label: "رد شده", class: "text-red-300" }, + cancled: { label: "کنسل شده", class: "text-red-300" }, +}; + +const Projects = () => { + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [projectsList, setProjectsList] = useState([]); + const [totalPages, setTotalPages] = useState(0); + const [currentPage, setCurrentPage] = useState(1); + const [filters, setFilters] = useState({ startDate: "", endDate: "", status: "" }); + + const getProjectList = async (page = 1) => { + try { + setLoading(true); + const { startDate, endDate, status } = filters; + const res = await axios.get( + `${BaseUrl}/projects?limit=20&page=${page}${startDate ? "&startDate=" + startDate : "" + }${endDate ? "&endDate=" + endDate : ""}${status ? "&status=" + status : ""}` + ); + setProjectsList(res?.data?.projects || []); + setTotalPages(res?.data?.totalPages || 0); + } catch (err) { + toast.error("خطا در دریافت لیست پروژه‌ها"); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + getProjectList(currentPage); + }, [currentPage, filters]); + + const toggleProjectStatus = async (project) => { + try { + const newStatus = project.status === "accepted" ? "rejected" : "accepted"; + await axios.post(`${BaseUrl}/projects/accept`, { + id: project._id, + user_id: project?.selected_user?._id, + status: newStatus, + }); + toast.success(`پروژه ${newStatus === "accepted" ? "تأیید" : "رد"} شد`); + getProjectList(currentPage); + } catch (error) { + toast.error(error?.response?.data?.message || "خطا در تغییر وضعیت"); + } + }; + + return ( + <> + +
+
+
+ {/* فیلترها */} + ({ + key, + label: val.label, + }))} + provinceOptions={[{ value: "", label: "همه استان‌ها" }]} + cityOptions={[{ value: "", label: "همه شهرها" }]} + photographyModelOptions={[{ value: "", label: "همه مدل‌ها" }]} + blockStatusOptions={[{ value: "", label: "همه کاربران" }]} + onFilterChange={setFilters} + /> + + {/* هدر جدول */} +
+ {[ + "عنوان پروژه", + "کارفرما", + "کاربر", + "تخصص", + "زمان پیشنهادی", + "زمان نهایی", + "قیمت پیشنهادی", + "قیمت نهایی", + "تاریخ ثبت", + "وضعیت", + "عملیات", + ].map((title, idx) => ( +
{title}
+ ))} +
+ + {/* لیست پروژه‌ها */} + {loading ? ( +
+ +
+ ) : ( +
+ {projectsList.map((project, index) => { + const statusInfo = statusMap[project?.status] || { label: "-", class: "text-gray-300" }; + return ( +
+
{project?.title}
+
{project?.creator?.first_name} {project?.creator?.last_name}
+
{project?.selected_user?.first_name} {project?.selected_user?.last_name}
+
{project?.expertise}
+
{project?.offer_time}
+
{project?.final_time}
+
{Number(project?.offer_price).toLocaleString()}
+
{Number(project?.final_price).toLocaleString()}
+
{new Date(project?.createdAt).toLocaleDateString("fa-IR")}
+
{statusInfo.label}
+
+ + +
+
+ ); + })} +
+ )} + + {/* صفحه‌بندی */} + setCurrentPage(page)} + /> +
+
+ + ); +}; + +export default Projects; diff --git a/public/modstagram_panel/src/pages/purchased/purchased.jsx b/public/modstagram_panel/src/pages/purchased/purchased.jsx new file mode 100644 index 0000000..b0d2108 --- /dev/null +++ b/public/modstagram_panel/src/pages/purchased/purchased.jsx @@ -0,0 +1,307 @@ +// src/pages/Purchased.js +import React, { useState, useEffect, useCallback } from "react"; +import toast from "react-hot-toast"; +import { getPurchasedCourses, getPurchasedStats } from "../../components/adminApi"; // اصلاح مسیر +import Layout from "../../components/academy/Layout"; +import { FaSearch, FaUser, FaBook, FaCalendar, FaEye, FaTimes } from "react-icons/fa"; + +const Purchased = () => { + const [purchases, setPurchases] = useState([]); + const [stats, setStats] = useState(null); + const [loading, setLoading] = useState(true); + const [page, setPage] = useState(1); + const [totalPages, setTotalPages] = useState(1); + const [search, setSearch] = useState(""); + const [searchInput, setSearchInput] = useState(""); + const [selectedPurchase, setSelectedPurchase] = useState(null); + const [showModal, setShowModal] = useState(false); + + const fetchPurchases = useCallback(async () => { + setLoading(true); + try { + const response = await getPurchasedCourses({ page, limit: 15, search }); + console.log("Purchased response:", response.data); + + if (response.data.success) { + const responseData = response.data.data; + setPurchases(responseData?.purchases || []); + setStats(responseData?.stats || null); + setTotalPages(responseData?.pagination?.totalPages || 1); + } else { + toast.error(response.data.message || "خطا در دریافت اطلاعات"); + } + } catch (error) { + console.error("Error fetching purchases:", error); + toast.error("خطا در دریافت اطلاعات"); + } finally { + setLoading(false); + } + }, [page, search]); + + const fetchStats = async () => { + try { + const response = await getPurchasedStats(); + console.log("Stats response:", response.data); + + if (response.data.success) { + setStats(response.data.data); + } + } catch (error) { + console.error("Error fetching stats:", error); + } + }; + + useEffect(() => { + fetchPurchases(); + fetchStats(); + }, [fetchPurchases]); + + const handleSearch = (e) => { + e.preventDefault(); + setSearch(searchInput); + setPage(1); + }; + + const handleClearSearch = () => { + setSearchInput(""); + setSearch(""); + setPage(1); + }; + + const getImageUrl = (imagePath) => { + if (!imagePath) return null; + if (imagePath.startsWith("http")) return imagePath; + // اگر نیاز به BASE_URL داری، اینجا اضافه کن + return imagePath; + }; + + if (loading && page === 1) { + return ( + +
+
+
+
+ ); + } + + return ( + +
+
+

دوره‌های خریداری شده

+

لیست تمام دوره‌هایی که کاربران خریداری کرده‌اند

+
+ + {/* Stats */} + {stats && ( +
+
+
+
+

تعداد کل خریدها

+

{stats.totalPurchases?.toLocaleString() || 0}

+
+ +
+
+
+
+
+

کاربران خریدار

+

{stats.uniqueUsers?.toLocaleString() || 0}

+
+ +
+
+
+ )} + + {/* Search */} +
+
+ setSearchInput(e.target.value)} + className="w-full px-4 py-3 pl-12 pr-4 border rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500" + /> + + {searchInput && ( + + )} +
+
+ + {/* Search result info */} + {search && ( +
+ نتایج جستجو برای: {search} + +
+ )} + + {/* Purchases List */} +
+ {purchases.length === 0 && !loading ? ( +
+ +

هیچ خریدی یافت نشد

+ {search && ( + + )} +
+ ) : ( + purchases.map((purchase) => ( +
+
+
+
+
+ {purchase.course_id?.course_image ? ( + {purchase.course_id?.cuorse_name} + ) : ( + + )} +
+
+

{purchase.course_id?.cuorse_name || "نامشخص"}

+

مدرس: {purchase.course_id?.teacher_name || "نامشخص"}

+
+ + + {purchase.user_id?.user_name || "کاربر ناشناس"} + + + + {new Date(purchase.createdAt).toLocaleDateString("fa-IR")} + +
+
+
+
+
+
+ {parseInt(purchase.course_id?.price || 0).toLocaleString()} تومان +
+ +
+
+
+ )) + )} +
+ + {/* Pagination */} + {totalPages > 1 && ( +
+ + + صفحه {page} از {totalPages} + + +
+ )} + + {/* Modal */} + {showModal && selectedPurchase && ( +
+
+
+

جزئیات خرید

+ +
+
+
+ کاربر: + {selectedPurchase.user_id?.user_name || "-"} +
+ {/*
+ ایمیل: + {selectedPurchase.user_id?.email || "-"} +
*/} +
+ دوره: + {selectedPurchase.course_id?.cuorse_name || "-"} +
+
+ مدرس: + {selectedPurchase.course_id?.teacher_name || "-"} +
+
+ تاریخ خرید: + {new Date(selectedPurchase.createdAt).toLocaleDateString("fa-IR")} +
+ {selectedPurchase.payment_ref_id && ( +
+ کد پیگیری: + {selectedPurchase.payment_ref_id} +
+ )} +
+
+ +
+
+
+ )} +
+
+ ); +}; + +export default Purchased; \ No newline at end of file diff --git a/public/modstagram_panel/src/pages/settings/settings.jsx b/public/modstagram_panel/src/pages/settings/settings.jsx new file mode 100644 index 0000000..4640fcd --- /dev/null +++ b/public/modstagram_panel/src/pages/settings/settings.jsx @@ -0,0 +1,281 @@ +// src/pages/Settings.js +import React, { useState, useEffect } from "react"; +import toast from "react-hot-toast"; +import { getAllSettings, updateAllSettings } from "../../components/adminApi"; +import Layout from "../../components/academy/Layout"; +import { FaSave, FaPercent, FaGem, FaSpinner, FaExclamationTriangle } from "react-icons/fa"; + +const Settings = () => { + const [settings, setSettings] = useState({ + tax: 8, + proPrice: "60000", + legendPrice: "199000", + }); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [errors, setErrors] = useState({}); + + const fetchSettings = async () => { + setLoading(true); + try { + const response = await getAllSettings(); + console.log("Settings response:", response.data); + + if (response.data.success) { + setSettings({ + tax: response.data.data.tax || 8, + proPrice: response.data.data.prices?.pro || "60000", + legendPrice: response.data.data.prices?.legend || "199000", + }); + } else { + toast.error(response.data.message || "خطا در دریافت تنظیمات"); + } + } catch (error) { + console.error("Error fetching settings:", error); + toast.error("خطا در دریافت تنظیمات"); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchSettings(); + }, []); + + const validateSettings = () => { + const newErrors = {}; + + // اعتبارسنجی مالیات + const taxNum = parseFloat(settings.tax); + if (isNaN(taxNum)) { + newErrors.tax = "مقدار مالیات باید عدد باشد"; + } else if (taxNum < 0) { + newErrors.tax = "مالیات نمی‌تواند منفی باشد"; + } else if (taxNum > 100) { + newErrors.tax = "مالیات نمی‌تواند بیشتر از 100 درصد باشد"; + } + + // اعتبارسنجی قیمت پرو + const proPriceNum = parseInt(settings.proPrice); + if (isNaN(proPriceNum)) { + newErrors.proPrice = "قیمت پرو باید عدد باشد"; + } else if (proPriceNum < 0) { + newErrors.proPrice = "قیمت نمی‌تواند منفی باشد"; + } + + // اعتبارسنجی قیمت لجند + const legendPriceNum = parseInt(settings.legendPrice); + if (isNaN(legendPriceNum)) { + newErrors.legendPrice = "قیمت لجند باید عدد باشد"; + } else if (legendPriceNum < 0) { + newErrors.legendPrice = "قیمت نمی‌تواند منفی باشد"; + } + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleChange = (e) => { + const { name, value } = e.target; + setSettings({ + ...settings, + [name]: value, + }); + // پاک کردن خطای مربوط به این فیلد + if (errors[name]) { + setErrors({ ...errors, [name]: "" }); + } + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + + // اعتبارسنجی + if (!validateSettings()) { + toast.error("لطفاً مقادیر را به درستی وارد کنید"); + return; + } + + setSaving(true); + try { + const response = await updateAllSettings({ + tax: parseFloat(settings.tax), + proPrice: parseInt(settings.proPrice) || 0, + legendPrice: parseInt(settings.legendPrice) || 0, + }); + + console.log("Save response:", response.data); + + if (response.data.success) { + toast.success("تنظیمات با موفقیت ذخیره شد"); + fetchSettings(); // رفرش کردن مقادیر از سرور + } else { + toast.error(response.data.message || "خطا در ذخیره تنظیمات"); + } + } catch (error) { + console.error("Error saving settings:", error); + toast.error(error.response?.data?.message || "خطا در ذخیره تنظیمات"); + } finally { + setSaving(false); + } + }; + + if (loading) { + return ( + +
+
+
+
+ ); + } + + return ( + +
+
+

تنظیمات سیستم

+

مدیریت مالیات و قیمت دوره‌های ویژه

+
+ +
+ {/* درصد مالیات */} +
+
+
+ +
+

درصد مالیات (تکس)

+
+
+
+ + {errors.tax && ( +

+ + {errors.tax} +

+ )} +
+ درصد +
+

+ این درصد به مبلغ هر فروش اضافه خواهد شد (محدوده: 0 تا 100) +

+
+ + {/* قیمت دوره‌های ویژه */} +
+
+
+ +
+

قیمت دوره‌های ویژه

+
+
+
+ دوره پرو: +
+ + {errors.proPrice && ( +

+ + {errors.proPrice} +

+ )} +
+ تومان +
+
+ دوره لجند: +
+ + {errors.legendPrice && ( +

+ + {errors.legendPrice} +

+ )} +
+ تومان +
+
+

+ قیمت دوره معمولی از قیمت تعیین شده توسط آکادمی محاسبه می‌شود +

+
+ + {/* دکمه ذخیره */} +
+ + +
+
+ + {/* توضیحات پایین صفحه */} +
+

ℹ️ نکات مهم:

+
    +
  • تغییر مالیات بر روی تمام فروش‌های جدید تأثیر می‌گذارد
  • +
  • قیمت دوره‌های پرو و لجند برای ساخت دوره‌های جدید اعمال می‌شود
  • +
  • دوره‌های موجود با قیمت قبلی خود باقی می‌مانند
  • +
+
+
+
+ ); +}; + +export default Settings; \ No newline at end of file diff --git a/public/modstagram_panel/src/pages/shops/ShopDetail.jsx b/public/modstagram_panel/src/pages/shops/ShopDetail.jsx new file mode 100644 index 0000000..bacb31a --- /dev/null +++ b/public/modstagram_panel/src/pages/shops/ShopDetail.jsx @@ -0,0 +1,106 @@ +import React, { useEffect, useState } from "react"; +import AdminHeader from "../../components/admin-header"; +import Sidebar from "../../components/sidebar"; +import Loading from "../../components/elements/loading"; +import { BaseUrl, ImageBaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import { useNavigate, useParams } from "react-router-dom"; +import ShopDet from "../../components/shops/ShopDet"; + +const ShopDetail = () => { + const navigate = useNavigate(); + const param = useParams(); + const id = param?.id; + const [loading, setLoading] = useState(false); + const [section, setSection] = useState(0); + const sectionTitles = [ + "جزئیات", + // "تبلیغ ها", + ]; + const [shopDetails, setShopDetails] = useState([]); + const getUserDetails = (page = 1) => { + setLoading(true); + const config = { + url: `${BaseUrl}/shops/detail?profile_id=${id}`, + method: "GET", + }; + axios(config) + .then((res) => { + setShopDetails(res?.data?.shop); + setLoading(false); + }) + .catch((err) => { + setLoading(false); + }); + }; + useEffect(() => { + getUserDetails(); + }, [id]); + const sectionItems = [ + , + + ]; + return ( + <> + +
+
+
+
+
+

+ اطلاعات کاربر: +

+ +
+
+ {sectionTitles?.map((title, index) => ( + + ))} +
+ {loading ? ( +
+ +
+ ) : ( + sectionItems?.filter( + (item, index) => index == section + ) + )} +
+
+
+ + ); +}; + +export default ShopDetail; diff --git a/public/modstagram_panel/src/pages/shops/Shops.jsx b/public/modstagram_panel/src/pages/shops/Shops.jsx new file mode 100644 index 0000000..e236ee6 --- /dev/null +++ b/public/modstagram_panel/src/pages/shops/Shops.jsx @@ -0,0 +1,203 @@ +import React, { useEffect, useState } from "react"; +import AdminHeader from "../../components/admin-header"; +import Sidebar from "../../components/sidebar"; +import Loading from "../../components/elements/loading"; +import { BaseUrl, ImageBaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import { useNavigate } from "react-router-dom"; +import Pagination from "../../components/Pagination"; + +const Shops = () => { + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [shopsList, setShopList] = useState([]); + const [totalPages, setTotalPages] = useState(0); + const [currentPage, setCurrentPage] = useState(1); + const getUserList = (page = 1) => { + setLoading(true); + const config = { + url: `${BaseUrl}/shops?limit=20&page=${page}`, + method: "GET", + }; + axios(config) + .then((res) => { + setShopList(res?.data?.shops); + setTotalPages(res?.data?.totalPages); // دریافت تعداد صفحات از API + setLoading(false); + }) + .catch((err) => { + setLoading(false); + }); + }; + useEffect(() => { + getUserList(currentPage); + }, [currentPage]); + return ( + <> + +
+
+
+
+
+
+
+

+ نام و نام خانوادگی کاربر +

+
+
+

+ عنوان فروشگاه +

+
+
+

+ دسته بندی +

+
+
+

+ استان +

+
+
+

+ شهر +

+
+
+

+ محله +

+
+
+

+ تاریخ ایجاد فروشگاه +

+
+ {/*
+

+ وضعیت +

+
*/} +
+

+
+
+
+ {loading ? ( +
+ +
+ ) : ( +
+ {shopsList?.map((shop, index) => ( +
+
+
+
+ +

+ {shop?.first_name}{" "} + {shop?.last_name} +

+
+
+
+

+ {shop?.vitrine_name} +

+
+
+

+ {shop?.category} +

+
+
+

+ {shop?.province?.name} +

+
+
+

+ {shop?.city?.name} +

+
+
+

+ {shop?.neighbourhood} +

+
+
+

+ {shop?.createdAt} +

+
+ {/*
+
+

+ {shop?.blocked + ? "غیر فعال" + : "فعال"} +

+ {shop?.blocked ? ( + + ) : ( + + )} +
+
*/} +
+

+ +

+
+
+
+ ))} +
+ )} + + setCurrentPage(page)} // تغییر صفحه + /> +
+
+
+ + ); +}; + +export default Shops; diff --git a/public/modstagram_panel/src/pages/terms/TermsAndConditionsEditor.js b/public/modstagram_panel/src/pages/terms/TermsAndConditionsEditor.js new file mode 100644 index 0000000..87ee1af --- /dev/null +++ b/public/modstagram_panel/src/pages/terms/TermsAndConditionsEditor.js @@ -0,0 +1,107 @@ +import React, { useEffect, useState } from "react"; +import ReactQuill from "react-quill"; +import "react-quill/dist/quill.snow.css"; +import AdminHeader from "../../components/admin-header"; +import Sidebar from "../../components/sidebar"; +import axios from "axios"; +import { BaseUrl } from "../../components/BaseUrl"; +import toast from "react-hot-toast"; + +const TermsAndConditionsEditor = () => { + const [editorContent, setEditorContent] = useState(""); + + useEffect(() => { + // دریافت قوانین و مقررات موجود از سرور در بارگذاری اولیه + axios + .get(`${BaseUrl}/settings/terms-and-conditions`) + .then((response) => { + setEditorContent(response.data.value); + }) + .catch((error) => { + console.error("Error fetching terms and conditions:", error); + }); + }, []); + + const handleSave = () => { + axios + .put(`${BaseUrl}/settings/terms-and-conditions`, { value: editorContent }, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }) + .then((response) => { + toast.success(response?.data?.message) + // نمایش پیغام موفقیت (در صورت نیاز از toast یا هر کتابخانه مشابه دیگر استفاده کنید) + }) + .catch((error) => { + console.error("Error updating terms and conditions:", error); + // نمایش پیغام خطا (در صورت نیاز از toast یا هر کتابخانه مشابه دیگر استفاده کنید) + }); + }; + return ( + <> + +
+
+
+
+

ویرایشگر قوانین و مقررات

+ + +
+
+
+ + ); +}; + +TermsAndConditionsEditor.modules = { + toolbar: [ + [ + { header: "1" }, + { header: "2" }, + { header: "3" }, + { header: "4" }, + { header: "5" }, + { header: "6" }, + { font: [] }, + ], + [{ list: "ordered" }, { list: "bullet" }], + ["bold", "italic", "underline", "strike", "blockquote"], + [{ align: [] }], + [{ color: [] }, { background: [] }], + ["link"], + ["clean"], + ], +}; + +TermsAndConditionsEditor.formats = [ + "header", + "font", + "list", + "bullet", + "bold", + "italic", + "underline", + "strike", + "blockquote", + "align", + "color", + "background", + "link", +]; + +export default TermsAndConditionsEditor; diff --git a/public/modstagram_panel/src/pages/tickets/TicketDetail.jsx b/public/modstagram_panel/src/pages/tickets/TicketDetail.jsx new file mode 100644 index 0000000..93b6a5d --- /dev/null +++ b/public/modstagram_panel/src/pages/tickets/TicketDetail.jsx @@ -0,0 +1,176 @@ +import React, { useEffect, useState } from "react"; +import AdminHeader from "../../components/admin-header"; +import Sidebar from "../../components/sidebar"; +import { useNavigate, useParams } from "react-router-dom"; +import { BaseUrl, ImageBaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import Loading from "../../components/elements/loading"; +import Modal from 'react-modal'; +const customStyles = { + content: { + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + position: "fixed", + }, +}; +const TicketDetail = () => { + const param = useParams(); + console.log(param); + const ticketId = param?.id; + const status = param?.status + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [messageList, setMessageList] = useState([]); + const [newMessage, setNewMessage] = useState(""); + const [modalIsOpen, setModalIsOpen] = useState(false); + const [modalImage, setModalImage] = useState(''); + + const openModal = (image) => { + setModalImage(image); + setModalIsOpen(true); + } + + const closeModal = () => { + setModalIsOpen(false); + } + const getMessageList = (page = 1) => { + setLoading(true); + const config = { + url: `${BaseUrl}/tickets/messages?ticketId=${ticketId}&page=${page}&limit=20`, + method: "GET", + }; + axios(config) + .then((res) => { + setMessageList(res?.data?.messages); + setLoading(false); + }) + .catch((err) => { + setLoading(false); + }); + }; + useEffect(() => { + getMessageList(); + }, []); + const handleSendMessage = () => { + if (!newMessage.trim()) return; + + const config = { + url: `${BaseUrl}/tickets/message`, + method: "POST", + data: { + ticketId, + text: newMessage, + }, + }; + axios(config) + .then((res) => { + setNewMessage(""); + getMessageList(); + }) + .catch((err) => { + console.error(err); + }); + }; + + const handleCloseTicket = () => { + const config = { + url: `${BaseUrl}/tickets/close`, + method: "POST", + data: { ticketId }, + }; + axios(config) + .then((res) => { + navigate(-1); + }) + .catch((err) => { + console.error(err); + }); + } + + return ( + <> + +
+ +
+

آیا مطمئنید میخواهید تیکت را ببندید ؟

+
+ + +
+
+
+
+ +
+ {loading ? ( + + ) : ( +
+ {messageList.map((message) => ( +
+
+ {message.senderType === "Admin" ? "Admin" : `${message.senderId?.first_name} ${message.senderId?.last_name}`} +
+
{message.createdAt}
+
{message.text}
+ {message.file && ( + + )} +
+ ))} +
+ )} +
+ + { + status && status == "Closed" && "تیکت بسته شده است" + } + + { + status !== "Closed" && + <> + + +
+ + + +
+ + } +
+
+
+
+ + ); +}; + +export default TicketDetail; diff --git a/public/modstagram_panel/src/pages/tickets/Tickets.jsx b/public/modstagram_panel/src/pages/tickets/Tickets.jsx new file mode 100644 index 0000000..098fee6 --- /dev/null +++ b/public/modstagram_panel/src/pages/tickets/Tickets.jsx @@ -0,0 +1,208 @@ +import React, { useCallback, useEffect, useState } from "react"; +import AdminHeader from "../../components/admin-header"; +import Sidebar from "../../components/sidebar"; +import { useLocation, useNavigate } from "react-router-dom"; +import { BaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import Loading from "../../components/elements/loading"; +import Pagination from "../../components/Pagination"; +import Filters from "../../components/Filters"; + +const Tickets = () => { + const navigate = useNavigate(); + const location = useLocation(); // اضافه شد + const [loading, setLoading] = useState(false); + const [ticketList, setTicketList] = useState([]); + const [totalPages, setTotalPages] = useState(0); + const [currentPage, setCurrentPage] = useState(1); + + const [filters, setFilters] = useState({ startDate: "", endDate: "", status: "" }); + + const getTicketList = useCallback((page = 1) => { + setLoading(true); + + // بررسی پارامتر URL + const urlParams = new URLSearchParams(location.search); + let statusParam = filters.status; + + if (urlParams.get("status") === "pending") { + statusParam = "Customer Response"; // فقط تیکت‌های در انتظار پاسخ + } + + const { startDate, endDate } = filters; + + const config = { + url: `${BaseUrl}/tickets?limit=20&page=${page}${ + startDate ? "&startDate=" + startDate : "" + }${endDate ? "&endDate=" + endDate : ""}${statusParam ? "&status=" + statusParam : ""}`, + method: "GET", + }; + + axios(config) + .then((res) => { + setTicketList(res?.data?.tickets || []); + setTotalPages(res?.data?.totalPages || 0); + }) + .catch(() => { + setTicketList([]); + }) + .finally(() => setLoading(false)); + }, [filters, location.search]); + + useEffect(() => { + getTicketList(currentPage); + }, [currentPage, filters, getTicketList]); + + return ( + <> + +
+
+
+
+ +
+
+
+

+ نام کاربری +

+
+
+

+ نوع کاربری +

+
+
+

+ نام و نام خانوادگی +

+
+
+

+ موبایل +

+
+
+

+ تاریخ ثبت تیکت +

+
+
+

+ وضعیت +

+
+
+

+
+
+
+ {loading ? ( +
+ +
+ ) : ( +
+ {ticketList?.map((ticket, index) => ( +
+
+
+

+ {ticket?.user?.user_name} +

+
+
+

+ {ticket?.user?.expertise} + +

+
+
+

+ {ticket?.user?.first_name}{" "}{ticket?.user?.last_name} +

+
+
+

+ {ticket?.user?.mobile} +

+
+
+
+

+ {ticket?.createdAt} +

+
+
+
+
+

+ {ticket?.status === "Pending" ? + "در انتظار پاسخ" : + ticket?.status === "Answered" ? + "پاسخ داده شده" : + ticket?.status === "Customer Response" ? + "پاسخ مشتری" : "بسته شده"} +

+
+
+
+

+ +

+
+
+
+ ))} +
+ )} + setCurrentPage(page)} // تغییر صفحه + /> +
+
+
+ + ); +}; + +export default Tickets; diff --git a/public/modstagram_panel/src/pages/users/UserDetail.jsx b/public/modstagram_panel/src/pages/users/UserDetail.jsx new file mode 100644 index 0000000..2d45e9f --- /dev/null +++ b/public/modstagram_panel/src/pages/users/UserDetail.jsx @@ -0,0 +1,122 @@ +import React, { useEffect, useState } from "react"; +import AdminHeader from "../../components/admin-header"; +import Sidebar from "../../components/sidebar"; +import Loading from "../../components/elements/loading"; +import { BaseUrl, ImageBaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import { useNavigate, useParams } from "react-router-dom"; +import UserPosts from "../../components/users/UserPosts"; +import UserDet from "../../components/users/UserDet"; +import UserWorkroom from "../../components/users/UserWorkroom"; +import UserComments from "../../components/users/UserComments"; +import UserMessages from "../../components/users/UserMessages"; +import UserFinancial from "../../components/users/UserFinancial"; +import UserChangePassword from "../../components/users/UserChangePassword"; + +const UserDetail = () => { + const navigate = useNavigate(); + const param = useParams(); + const id = param?.id; + const [loading, setLoading] = useState(false); + const [section, setSection] = useState(0); + const sectionTitles = [ + "جزئیات", + "پستها", + "درخواستها", + "نظرات", + "پیامها", + "مالی", + "تغییر رمز عبور", + ]; + const [userDetails, setUsersDetails] = useState([]); + const getUserDetails = (page = 1) => { + setLoading(true); + const config = { + url: `${BaseUrl}/users/detail?user_id=${id}`, + method: "GET", + }; + axios(config) + .then((res) => { + setUsersDetails(res?.data?.user); + setLoading(false); + }) + .catch((err) => { + setLoading(false); + }); + }; + useEffect(() => { + getUserDetails(); + }, [id]); + const sectionItems = [ + , + , + , + , + , + , + , + ]; + return ( + <> + +
+
+
+
+
+

+ اطلاعات کاربر: +

+ +
+
+ {sectionTitles?.map((title, index) => ( + + ))} +
+ {loading ? ( +
+ +
+ ) : ( + sectionItems?.filter( + (item, index) => index == section + ) + )} +
+
+
+ + ); +}; + +export default UserDetail; diff --git a/public/modstagram_panel/src/pages/users/Users.jsx b/public/modstagram_panel/src/pages/users/Users.jsx new file mode 100644 index 0000000..ec6c09f --- /dev/null +++ b/public/modstagram_panel/src/pages/users/Users.jsx @@ -0,0 +1,438 @@ +import React, { useEffect, useState } from "react"; +import Sidebar from "../../components/sidebar"; +import Loading from "../../components/elements/loading"; +import { BaseUrl, ImageBaseUrl } from "../../components/BaseUrl"; +import axios from "axios"; +import { useNavigate, useSearchParams } from "react-router-dom"; +import Pagination from "../../components/Pagination"; +import Filters from "../../components/Filters"; +import { FaCheck, FaTimes, FaInfoCircle, FaMoon, FaSun } from "react-icons/fa"; + +// تابع کمکی برای تبدیل تاریخ شمسی به فرمت قابل مقایسه +const parsePersianDate = (dateStr) => { + if (!dateStr) return null; + const [year, month, day] = dateStr.split(" ")[0].split("-").map(Number); + // تبدیل تاریخ شمسی به میلادی برای مقایسه (تقریبی) + const gregorianYear = year - 621; // تقریبی: 1404 شمسی ≈ 2025 میلادی + return new Date(gregorianYear, month - 1, day); +}; + +// تابع فرمت تاریخ شمسی برای نمایش +const formatPersianDate = (dateStr) => { + if (!dateStr) return "-"; + return dateStr.split(" ")[0]; // فقط تاریخ (مثل 1404-07-04) +}; + +// کامپوننت اصلی صفحه کاربران +const Users = () => { + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [allUsers, setAllUsers] = useState([]); // ذخیره همه کاربران + const [filteredUsers, setFilteredUsers] = useState([]); // کاربران فیلترشده + const [totalPages, setTotalPages] = useState(0); + const [currentPage, setCurrentPage] = useState(1); + const [error, setError] = useState(""); // حالت خطا + const [filters, setFilters] = useState({ + startDate: "", + endDate: "", + status: "", + province: "", + city: "", + photographyModel: "", + blockStatus: "", + }); + const [searchQuery, setSearchQuery] = useState(""); + const [darkMode, setDarkMode] = useState(false); + + // لیست‌های دینامیک برای فیلترها + const [provinces, setProvinces] = useState([{ value: "", label: "همه استان‌ها" }]); + const [cities, setCities] = useState({ "": [{ value: "", label: "همه شهرها" }] }); + const [photographyModels, setPhotographyModels] = useState([{ value: "", label: "همه مدل‌ها" }]); + + const itemsPerPage = 20; + + const blockStatusOptions = [ + { value: "", label: "همه وضعیت‌ها" }, + { value: "active", label: "فعال" }, + { value: "inactive", label: "غیرفعال" }, + ]; + + const statusOptions = [ + { key: "", label: "همه وضعیت‌ها" }, + { key: "none", label: "بدون مدارک" }, + { key: "pending", label: "در انتظار تایید" }, + { key: "verified", label: "تایید شده" }, + { key: "rejected", label: "رد شده" }, + ]; + + // تابع استخراج لیست‌های فیلتر از کاربران + const extractFilterOptions = (users) => { + // استخراج استان‌ها + const provinceSet = new Map(); + users.forEach((user) => { + if (user.province?.id && user.province?.name && !provinceSet.has(String(user.province.id))) { + provinceSet.set(String(user.province.id), user.province.name); + } + }); + const provinceList = [ + { value: "", label: "همه استان‌ها" }, + ...Array.from(provinceSet, ([value, label]) => ({ value, label })) + .sort((a, b) => a.label.localeCompare(b.label)), // مرتب‌سازی الفبایی + ]; + setProvinces(provinceList); + console.log("استان‌های استخراج‌شده:", provinceList); + + // استخراج شهرها بر اساس استان + const cityMap = {}; + users.forEach((user) => { + const provId = String(user.province?.id || ""); + if (!cityMap[provId]) cityMap[provId] = new Map(); + if (user.city?.id && user.city?.name && !cityMap[provId].has(String(user.city.id))) { + cityMap[provId].set(String(user.city.id), user.city.name); + } + }); + const cityObj = { "": [{ value: "", label: "همه شهرها" }] }; + Object.keys(cityMap).forEach((provId) => { + cityObj[provId] = [ + { value: "", label: "همه شهرها" }, + ...Array.from(cityMap[provId], ([value, label]) => ({ value, label })) + .sort((a, b) => a.label.localeCompare(b.label)), // مرتب‌سازی الفبایی + ]; + }); + setCities(cityObj); + console.log("شهرهای استخراج‌شده:", cityObj); + + // استخراج مدل‌های عکاسی + const modelSet = new Set(); + users.forEach((user) => { + if (user.sub_expertise) { + user.sub_expertise.forEach((model) => modelSet.add(model)); + } + }); + const modelList = [ + { value: "", label: "همه مدل‌ها" }, + ...Array.from(modelSet, (value) => ({ value, label: value })) + .sort((a, b) => a.label.localeCompare(b.label)), // مرتب‌سازی الفبایی + ]; + setPhotographyModels(modelList); + console.log("مدل‌های عکاسی استخراج‌شده:", modelList); + }; + + // تابع تغییر وضعیت کاربر (فعال/غیرفعال) + const toggleUserStatus = async (userId, currentStatus) => { + try { + await axios.post( + `${BaseUrl}/users/update-status`, + { userId, block_status: !currentStatus }, + { + headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }, + } + ); + // به‌روزرسانی حالت محلی + setAllUsers((prev) => + prev.map((u) => (u._id === userId ? { ...u, block_status: !currentStatus } : u)) + ); + } catch (err) { + console.error("خطا در تغییر وضعیت کاربر:", err); + setError("خطا در تغییر وضعیت کاربر. لطفاً دوباره تلاش کنید."); + } + }; + + // تابع تایید یا رد تصویر پروفایل + const handleApproveProfileImage = async (userId, approve) => { + try { + await axios.put( + `${BaseUrl}/users/update?userId=${userId}`, + { + approveProfileImage: approve, + ...(approve === false && { profile_image: "" }), + }, + { + headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }, + } + ); + // به‌روزرسانی حالت محلی + setAllUsers((prev) => + prev.map((u) => (u._id === userId ? { ...u, profile_image: approve ? u.profile_image : "" } : u)) + ); + } catch (err) { + console.error("خطا در تایید/رد تصویر پروفایل:", err); + setError("خطا در تایید/رد تصویر پروفایل. لطفاً دوباره تلاش کنید."); + } + }; + + // تابع دریافت کاربران از API + const fetchUsers = () => { + setLoading(true); + setError(""); + const url = `${BaseUrl}/users?limit=1000`; // دریافت تعداد زیادی کاربر + console.log("درخواست API:", url); + + axios + .get(url, { + headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }, + }) + .then((res) => { + if (res?.data?.users) { + console.log("داده‌های کاربران:", res.data.users); + setAllUsers(res.data.users); + extractFilterOptions(res.data.users); // استخراج گزینه‌های فیلتر + } else { + setAllUsers([]); + setError("داده‌ای از سرور دریافت نشد."); + } + setLoading(false); + }) + .catch((err) => { + console.error("خطا در دریافت کاربران:", err); + setError("خطا در دریافت لیست کاربران. لطفاً دوباره تلاش کنید."); + setLoading(false); + }); + }; + + // تابع اعمال فیلترهای محلی + const applyFilters = () => { + let result = [...allUsers]; + + // فیلتر جستجو + if (searchQuery) { + const query = searchQuery.toLowerCase(); + result = result.filter( + (user) => + user.first_name?.toLowerCase().includes(query) || + user.last_name?.toLowerCase().includes(query) || + user.user_name?.toLowerCase().includes(query) || + user.mobile?.toLowerCase().includes(query) + ); + } + + // فیلتر وضعیت مدارک + if (filters.status) { + result = result.filter((user) => user.is_verified === filters.status); + } + + + if (statusParam === "pending") { + result = result.filter((user) => user.is_verified === "pending"); + } + + // فیلتر استان + if (filters.province) { + result = result.filter((user) => String(user.province?.id) === filters.province); + } + if (filters.city) { + result = result.filter((user) => String(user.city?.id) === filters.city); + } + if (filters.photographyModel) { + result = result.filter((user) => user.sub_expertise?.includes(filters.photographyModel)); + } + if (filters.blockStatus) { + const isActive = filters.blockStatus === "active"; + result = result.filter((user) => user.block_status === !isActive); + } + + // فیلتر تاریخ + if (filters.startDate) { + const start = parsePersianDate(filters.startDate); + result = result.filter((user) => { + const userDate = parsePersianDate(user.createdAt); + return userDate && start && userDate >= start; + }); + } + if (filters.endDate) { + const end = parsePersianDate(filters.endDate); + result = result.filter((user) => { + const userDate = parsePersianDate(user.createdAt); + return userDate && end && userDate <= end; + }); + } + + // لاگ برای دیباگ + console.log("کاربران فیلترشده:", result); + + // به‌روزرسانی صفحه‌بندی و کاربران نمایش‌داده‌شده + setTotalPages(Math.ceil(result.length / itemsPerPage)); + const startIndex = (currentPage - 1) * itemsPerPage; + setFilteredUsers(result.slice(startIndex, startIndex + itemsPerPage)); + }; + + // بارگذاری کاربران هنگام بارگذاری صفحه + useEffect(() => { + fetchUsers(); + }, []); + + // اعمال فیلترها هنگام تغییر + useEffect(() => { + applyFilters(); + }, [allUsers, filters, searchQuery, currentPage]); + + // مدیریت تغییر صفحه + const handlePageChange = (page) => setCurrentPage(page); + + // تغییر حالت تاریک/روشن + const toggleDarkMode = () => { + setDarkMode(!darkMode); + }; + + const [searchParams] = useSearchParams(); +const statusParam = searchParams.get("status"); // مثلا "pending" + + return ( +
+
+ {/* سایدبار پاسخ‌گو */} +
+ +
+
+ + + {/* نمایش پیام خطا */} + {error && ( +
+ {error} +
+ )} + + {/* جستجو و فیلترها */} +
+ { + setSearchQuery(e.target.value); + setCurrentPage(1); + }} + /> + { + setFilters((prev) => ({ + ...prev, + ...newFilters, + city: newFilters.province !== prev.province ? "" : newFilters.city, // ریست شهر هنگام تغییر استان + })); + setCurrentPage(1); + }} + /> +
+ + {/* جدول کاربران */} +
+
+

نام و نام خانوادگی

+

نام کاربری

+

موبایل

+

تاریخ ثبت نام

+

وضعیت

+

عملیات

+
+ +
+ {loading ? ( +
+ +
+ ) : filteredUsers.length === 0 ? ( +
+ هیچ کاربری یافت نشد +
+ ) : ( + filteredUsers.map((user, index) => ( +
+
+ {`${user.first_name} (e.target.src = "/default-avatar.png")} + /> +

{user?.first_name} {user?.last_name}

+

+ {user?.first_name} {user?.last_name} +

+
+

{user?.user_name || "-"}

+

{user?.mobile || "-"}

+

{formatPersianDate(user?.createdAt)}

+
+ + {user?.block_status ? "غیرفعال" : "فعال"} + + +
+
+ + + +
+
+ )) + )} +
+
+ + +
+
+
+ ); +}; + +export default Users; \ No newline at end of file diff --git a/public/modstagram_panel/src/pages/version/Version.jsx b/public/modstagram_panel/src/pages/version/Version.jsx new file mode 100644 index 0000000..7455125 --- /dev/null +++ b/public/modstagram_panel/src/pages/version/Version.jsx @@ -0,0 +1,181 @@ +import React, { useEffect, useState } from 'react'; +import AdminHeader from '../../components/admin-header'; +import Sidebar from '../../components/sidebar'; +import axios from 'axios'; +import { BaseUrl } from '../../components/BaseUrl'; + +function Version() { + const [version, setVersion] = useState(null); // اطلاعات نسخه فعلی + const [loading, setLoading] = useState(false); // حالت بارگذاری + const [error, setError] = useState(null); // خطای احتمالی + const [formData, setFormData] = useState({ + version: '', + mandatory: false, + releaseNotes: '', + updateUrls: '', + }); // اطلاعات فرم + + // دریافت نسخه فعلی از سرور + useEffect(() => { + setLoading(true); + axios + .get(`${BaseUrl}/version`) + .then((response) => { + setVersion(response.data); + setFormData({ + version: response.data.version || '', + mandatory: response.data.mandatory || false, + releaseNotes: response.data.releaseNotes || '', + updateUrls: response.data.updateUrls ? response.data.updateUrls.join(', ') : '', + }); + setLoading(false); + }) + .catch((error) => { + setError('خطا در دریافت اطلاعات نسخه'); + setLoading(false); + }); + }, []); + + // مدیریت تغییرات فرم + const handleChange = (e) => { + const { name, value, type, checked } = e.target; + setFormData({ + ...formData, + [name]: type === 'checkbox' ? checked : value, + }); + }; + + // ارسال اطلاعات به سرور + const handleSubmit = (e) => { + e.preventDefault(); + setLoading(true); + setError(null); + + // تبدیل `updateUrls` به آرایه + const formattedData = { + ...formData, + updateUrls: formData.updateUrls.split(',').map((url) => url.trim()), + }; + + axios + .post(`${BaseUrl}/version`, formattedData) + .then((response) => { + setVersion(response.data.version); + setLoading(false); + alert('نسخه با موفقیت ذخیره شد.'); + }) + .catch((error) => { + setError('خطا در ذخیره اطلاعات نسخه'); + setLoading(false); + }); + }; + + return ( + <> + +
+
+
+
+

مدیریت ورژن برنامه

+ + {/* نمایش خطا */} + {error &&

{error}

} + + {/* حالت بارگذاری */} + {loading ? ( +
+

در حال بارگذاری...

+
+ ) : ( + <> + {/* نمایش اطلاعات نسخه */} + {version && ( +
+

نسخه فعلی:

+

ورژن: {version.version}

+

اجباری: {version.mandatory ? 'بله' : 'خیر'}

+

توضیحات: {version.releaseNotes}

+

لینک‌ها: {version.updateUrls.join(', ')}

+
+ )} + +
+ +

فرم ایجاد/ویرایش نسخه

+
+
+ + +
+ +
+ +
+ +
+ + +
+ +
+ + +
+ + +
+ + )} +
+
+
+ + ); +} + +export default Version; diff --git a/public/modstagram_panel/src/pages/vitrine/VitrineDetail.jsx b/public/modstagram_panel/src/pages/vitrine/VitrineDetail.jsx new file mode 100644 index 0000000..a035e20 --- /dev/null +++ b/public/modstagram_panel/src/pages/vitrine/VitrineDetail.jsx @@ -0,0 +1,427 @@ +import React, { useEffect, useState } from 'react' +import { useNavigate, useParams } from 'react-router-dom'; +import { BaseUrl, ImageBaseUrl } from '../../components/BaseUrl'; +import axios from 'axios'; +import AdminHeader from '../../components/admin-header'; +import Sidebar from '../../components/sidebar'; +import Loading from '../../components/elements/loading'; +import toast from 'react-hot-toast'; +import Modal from 'react-modal'; +const customStyles = { + content: { + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + position: "fixed", + }, +}; +const VitrineDetail = () => { + const navigate = useNavigate(); + const param = useParams(); + const id = param?.id; + const [loading, setLoading] = useState(false); + const [vitrineDetails, setVitrineDetails] = useState([]); + const [editingVitrine, setEditingVitrine] = useState(false); + const [newVitrine, setNewVitrine] = useState(''); + const [rejectReason, setRejectReason] = useState("") + const [modalIsOpen, setModalIsOpen] = useState(false); + const [modalImage, setModalImage] = useState(''); + + const openModal = (image) => { + setModalImage(image); + setModalIsOpen(true); + } + const closeModal = () => { + setModalIsOpen(false); + } + const getVitrineDetails = (page = 1) => { + setLoading(true); + const config = { + url: `${BaseUrl}/advertising/detail?advertisingId=${id}`, + method: "GET", + }; + axios(config) + .then((res) => { + setVitrineDetails(res?.data?.advertising); + setLoading(false); + }) + .catch((err) => { + setLoading(false); + }); + }; + useEffect(() => { + getVitrineDetails(); + }, [id]); + + const acceptVitrine = () => { + const data = { + advertisingId: vitrineDetails?._id, + }; + axios + .post(`${BaseUrl}/advertising/accept`, data, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }) + .then(async (response) => { + try { + toast.success(response?.data?.message) + getVitrineDetails() + } catch (error) { + if ( + error?.response?.data?.error + ) { + toast.error(error.response.data.error); + } else { + // نمایش پیام خطا برای سایر موارد + toast.error("خطای ناشناخته"); + } + } + }) + .catch((error) => { + console.error(error); + toast.show(error?.response?.data?.message, { + type: "danger", + placement: "top", + duration: 4000, + offset: 30, + animationType: "slide-in", + }); + }); + }; + + const rejectVitrine = () => { + const data = { + advertisingId: vitrineDetails?._id, + rejectReason: rejectReason, + }; + axios + .post(`${BaseUrl}/advertising/reject`, data, { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + }, + }) + .then(async (response) => { + try { + toast.success(response?.data?.message) + getVitrineDetails() + } catch (error) { + if ( + error?.response?.data?.error + ) { + toast.error(error.response.data.error); + } else { + // نمایش پیام خطا برای سایر موارد + toast.error("خطای ناشناخته"); + } + } + }) + .catch((error) => { + console.error(error); + toast.show(error?.response?.data?.message, { + type: "danger", + placement: "top", + duration: 4000, + offset: 30, + animationType: "slide-in", + }); + }); + }; + + const handleEditVitrine = () => { + // ارسال درخواست برای ویرایش ویترین به سرور + // سپس بروزرسانی متغیر مربوط به متن ویترین + setEditingVitrine(true); + }; + + + + const contactInfoArray = vitrineDetails?.contactInfo ? Object.keys(vitrineDetails.contactInfo).map(key => { + let title; + switch (key) { + case "phone": + title = "شماره ثابت"; + break; + case "mobile": + title = "شماره همراه"; + break; + case "telegramLink": + title = "لینک تلگرام"; + break; + case "whatsappNumber": + title = "شماره واتساپ"; + break; + case "instagramLink": + title = "لینک اینستاگرام"; + break; + case "saveInfoForNextAds": + title = "ذخیره اطلاعات برای آگهی‌های بعدی"; + break; + default: + title = key; + } + return { title, value: vitrineDetails.contactInfo[key] }; + }) : []; + + return (<> + {loading && } + {!loading && vitrineDetails && ( + <> + +
+ + {/* استفاده از ImageMagnify */} + Post + +
+
+
+
+

+ اطلاعات ویترین: +

+ +
+
+
+
+ عنوان ویترین: +
+
+ {vitrineDetails?.title} +
+
+
+
+ نام و نام خانوادگی سازنده: +
+
+ {vitrineDetails?.creator_id?.first_name} {vitrineDetails?.creator_id?.last_name} +
+
+
+
+ نام کاربری کاربر: +
+
+ {vitrineDetails?.creator_id?.user_name} +
+
+
+
+ دسته بندی +
+
+ {vitrineDetails?.category} +
+
+
+
+ استان +
+
+ {vitrineDetails?.province?.name} +
+
+
+
+ شهر +
+
+ {vitrineDetails?.city?.name} +
+
+
+
+ محله +
+
+ {vitrineDetails?.neighbourhood} +
+
+
+
+ لیست خدمات و کالا +
+
+
+ {vitrineDetails?.services && vitrineDetails?.services?.map(item => { + return (
+ { openModal(ImageBaseUrl + item?.image) }} + src={ImageBaseUrl + item?.image} className='w-[100px] h-[100px] rounded-sm' alt="" /> +

نام : {item?.title}

+

درصد تخفیف : {item?.discountPercentage}

+

قیمت اصلی : {item?.originalPrice}

+

قیمت تخفیف خورده : {item?.discountPrice}

+
) + })} +
+
+
+
+
+ لیست امکانات +
+
+
+ {vitrineDetails?.features && vitrineDetails?.features?.map(item => { + return (
+

{item?.title} :

+

{item?.value == true ? "دارد" : "ندارد"}

+
) + })} +
+
+
+
+
+ لیست تماس +
+
+
+ {contactInfoArray.map((item, index) => ( +
+

{item.title} :

+

{item.value}

+
+ ))} +
+
+
+
+
+ تصاویر +
+
+ {vitrineDetails?.images && vitrineDetails?.images?.map(item => { + return (
+ { openModal(ImageBaseUrl + item) }} + src={ImageBaseUrl + item} className='w-[100px] h-[100px] rounded-sm mx-4' alt="" /> +
) + })} +
+
+
+
+ توضیحات +
+
+ {vitrineDetails?.description} +
+
+
+
+ وضعیت: +
+
+

+ {vitrineDetails?.status + === "pre_payment" ? + "در انتظار پرداخت" : + vitrineDetails?.status == "paid" ? + "پرداخت شده" : vitrineDetails?.status == "accepted" ? + "تایید شده" : vitrineDetails?.status == "rejected" ? + "رد شده" : + "منقضی شده" + } +

+
+
+ {vitrineDetails?.reject_reason && + +
+
+ علت رد +
+
+ {vitrineDetails?.reject_reason} +
+
} +
+
+ {!editingVitrine ? ( + <> + {/* */} + +
+ + +
+ + ) : ( + <> + + {formik.touched.address && formik.errors.address && ( +

{formik.errors.address}

+ )} +
+ + + {selectedLocation && ( + + location icon + + )} + + {formik.touched.markerCoordinate && formik.errors.markerCoordinate && ( +

+ {formik.errors.markerCoordinate as string} +

+ )} +
+ + ); +}; + +export default LocationSelector; diff --git a/src/components/RegisterSW.tsx b/src/components/RegisterSW.tsx new file mode 100644 index 0000000..a3b8755 --- /dev/null +++ b/src/components/RegisterSW.tsx @@ -0,0 +1,14 @@ +"use client"; +import { useEffect } from "react"; + +export default function RegisterSW() { + useEffect(() => { + if ("serviceWorker" in navigator) { + navigator.serviceWorker.register("/service-worker.js").then(() => { + console.log("Service Worker Registered!"); + }); + } + }, []); + + return null; // این کامپوننت هیچ UI نداره، فقط Service Worker رو ثبت می‌کنه. +} diff --git a/src/components/TabNavigation.tsx b/src/components/TabNavigation.tsx new file mode 100644 index 0000000..54d29d7 --- /dev/null +++ b/src/components/TabNavigation.tsx @@ -0,0 +1,155 @@ +"use client"; + +import Link from "next/link"; +import { useEffect, useState } from "react"; +import toast from "react-hot-toast"; +import { cn } from "@/lib/utils"; + +const tabs = [ + { + href: "/", + icon: (color: string) => ( + + + + ), + label: "خانه", + }, + { + href: "/academy", + icon: (color: string) => ( + + + + + + ), + label: "آموزشگاه", + }, + { + href: "/new-post", + icon: (color: string) => ( + + + + + + + ), + label: "پست ها", + }, + { + href: "/billboards", + icon: (color: string) => ( + + + + + ), + label: "بیلبورد", + }, + { + href: "/settings", + icon: (color: string) => ( + + + + + ), + label: "تنظیمات", + }, +]; + +type TabNavigationProps = { + currentPage: string; +}; + +export default function TabNavigation({ currentPage }: TabNavigationProps) { + const [createTab, setCreateTab] = useState("/new-post"); + const [userTypeS, setUserTypeS] = useState(null); + const [mounted, setMounted] = useState(false); + const [isDark, setIsDark] = useState(false); + + useEffect(() => { + setMounted(true); + if (typeof window !== "undefined") { + const userType = localStorage.getItem("usertype"); + setUserTypeS(userType); + setCreateTab( + userType === "user" + ? "/new-post" + : userType === "employer" + ? "/new-project" + : "/new-post" + ); + } + }, []); + + useEffect(() => { + if (typeof window === "undefined") return; + const checkTheme = () => { + const theme = localStorage.getItem("theme"); + const isDarkMode = + theme === "dark" || + (theme === "system" && + window.matchMedia("(prefers-color-scheme: dark)").matches); + setIsDark(isDarkMode); + }; + checkTheme(); + window.addEventListener("storage", checkTheme); + return () => window.removeEventListener("storage", checkTheme); + }, []); + + if (!mounted) return null; + + const defaultColor = isDark ? "#a1a1aa" : "#52525b"; + const activeColor = "#ff107d"; + + return ( + + ); +} diff --git a/src/components/TitleGuardian.tsx b/src/components/TitleGuardian.tsx new file mode 100644 index 0000000..2306776 --- /dev/null +++ b/src/components/TitleGuardian.tsx @@ -0,0 +1,34 @@ +"use client"; + +import { useEffect } from "react"; +import { usePathname } from "next/navigation"; + +export default function TitleGuardian() { + const pathname = usePathname(); + + useEffect(() => { + // جلوگیری از تغییرات ناگهانی توسط اسکریپت‌های چت و اینماد + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === "childList" || mutation.type === "characterData") { + const newTitle = document.title; + // اگر تایتل خالی شد یا به localhost تغییر کرد یا حاوی کلمات سیستمی بود، دخالت نکن + // اما اگر اسکریپت خارجی مثل "گفتینو" تایتل را عوض کرد، اینجا می‌توانید منطق بازگشت بنویسید + } + }); + }); + + const titleElement = document.querySelector("title"); + if (titleElement) { + observer.observe(titleElement, { + childList: true, + characterData: true, + subtree: true + }); + } + + return () => observer.disconnect(); + }, [pathname]); + + return null; +} \ No newline at end of file diff --git a/src/components/academy/AcademyFilter.tsx b/src/components/academy/AcademyFilter.tsx new file mode 100644 index 0000000..e38116b --- /dev/null +++ b/src/components/academy/AcademyFilter.tsx @@ -0,0 +1,361 @@ +"use client"; + +import React, { useState, useEffect } from "react"; +import { useRouter, useSearchParams } from "next/navigation"; +import { motion } from "framer-motion"; +import { Search, Filter, X } from "lucide-react"; +import useAxios from "@/hooks/useAxios"; + +interface AcademyFilterProps { + onFilterChange?: (filters: any) => void; +} + +interface IAcademyCategory { + _id: string; + title: string; + slug: string; + description?: string; + icon?: string; + color?: string; + parent?: string | null; + level: number; + order: number; + course_count: number; + status: string; + is_featured: boolean; +} + +interface CategoryOption { + value: string; + label: string; + icon?: string; + color?: string; +} + +const sortOptions = [ + { value: "createdAt_desc", label: "جدیدترین" }, + { value: "createdAt_asc", label: "قدیمی‌ترین" }, + { value: "likes_desc", label: "محبوب‌ترین" }, + { value: "price_asc", label: "ارزان‌ترین" }, + { value: "price_desc", label: "گران‌ترین" }, +]; + +const courseTypes = [ + { value: "", label: "همه دوره‌ها" }, + { value: "normal", label: "معمولی" }, + { value: "pro", label: "پرو" }, +]; + +export default function AcademyFilter({ onFilterChange }: AcademyFilterProps) { + const router = useRouter(); + const searchParams = useSearchParams(); + + const [isOpen, setIsOpen] = useState(false); + const [filters, setFilters] = useState({ + search: "", + category: "", + minPrice: "", + maxPrice: "", + hasOffer: false, + type: "", + sortBy: "createdAt_desc", + }); + + const [categories, setCategories] = useState([ + { value: "", label: "همه دسته‌ها" } + ]); + const [categoriesLoading, setCategoriesLoading] = useState(false); + const { request } = useAxios(); + + // ========================================== + // دریافت دسته‌بندی‌های آکادمی از API جدید + // ========================================== + useEffect(() => { + const fetchAcademyCategories = async () => { + setCategoriesLoading(true); + try { + const response = await request<{ data: { docs: IAcademyCategory[] } }>( + "GET", + "/academy/categories?status=active&limit=100" + ); + + let categoriesList: IAcademyCategory[] = []; + + if (response?.data?.docs) { + categoriesList = response.data.docs; + } else if (response?.data && Array.isArray(response.data)) { + categoriesList = response.data; + } else if (Array.isArray(response)) { + categoriesList = response; + } + + console.log("دسته‌بندی‌های آکادمی:", categoriesList); + + // ========================================== + // ✅ تغییر مهم: استفاده از title به عنوان value + // ========================================== + const formattedCategories: CategoryOption[] = [ + { value: "", label: "همه دسته‌ها" }, + ...categoriesList.map((cat) => ({ + value: cat.title, // استفاده از عنوان دسته‌بندی + label: cat.title, + icon: cat.icon, + color: cat.color, + })) + ]; + + setCategories(formattedCategories); + console.log("دسته‌بندی فرمت شده:", formattedCategories); + } catch (err) { + console.log("خطا در دریافت دسته‌بندی آکادمی:", err); + } finally { + setCategoriesLoading(false); + } + }; + + fetchAcademyCategories(); + }, []); + + // خواندن فیلترها از URL + useEffect(() => { + setFilters({ + search: searchParams.get("search") || "", + category: searchParams.get("category") || "", + minPrice: searchParams.get("minPrice") || "", + maxPrice: searchParams.get("maxPrice") || "", + hasOffer: searchParams.get("hasOffer") === "true", + type: searchParams.get("type") || "", + sortBy: searchParams.get("sortBy") || "createdAt_desc", + }); + }, []); + + const updateURL = (newFilters: any) => { + const params = new URLSearchParams(); + + if (newFilters.search) params.set("search", newFilters.search); + if (newFilters.category) params.set("category", newFilters.category); + if (newFilters.minPrice) params.set("minPrice", newFilters.minPrice); + if (newFilters.maxPrice) params.set("maxPrice", newFilters.maxPrice); + if (newFilters.hasOffer) params.set("hasOffer", "true"); + if (newFilters.type) params.set("type", newFilters.type); + if (newFilters.sortBy && newFilters.sortBy !== "createdAt_desc") { + params.set("sortBy", newFilters.sortBy); + } + + const queryString = params.toString(); + const newUrl = queryString ? `/academy?${queryString}` : "/academy"; + router.push(newUrl, { scroll: false }); + }; + + const handleInputChange = (name: string, value: any) => { + const newFilters = { ...filters, [name]: value }; + setFilters(newFilters); + + let sortBy = "createdAt"; + let sortOrder = "desc"; + if (newFilters.sortBy === "createdAt_asc") { + sortBy = "createdAt"; + sortOrder = "asc"; + } else if (newFilters.sortBy === "price_asc") { + sortBy = "price"; + sortOrder = "asc"; + } else if (newFilters.sortBy === "price_desc") { + sortBy = "price"; + sortOrder = "desc"; + } else if (newFilters.sortBy === "likes_desc") { + sortBy = "likes"; + sortOrder = "desc"; + } + + const finalFilters = { + search: newFilters.search, + category: newFilters.category, + minPrice: newFilters.minPrice ? Number(newFilters.minPrice) : undefined, + maxPrice: newFilters.maxPrice ? Number(newFilters.maxPrice) : undefined, + hasOffer: newFilters.hasOffer, + type: newFilters.type, + sortBy, + sortOrder, + }; + + updateURL(newFilters); + if (onFilterChange) onFilterChange(finalFilters); + }; + + const handleSearch = (e: React.FormEvent) => { + e.preventDefault(); + handleInputChange("search", filters.search); + }; + + const clearFilters = () => { + const emptyFilters = { + search: "", + category: "", + minPrice: "", + maxPrice: "", + hasOffer: false, + type: "", + sortBy: "createdAt_desc", + }; + setFilters(emptyFilters); + router.push("/academy", { scroll: false }); + if (onFilterChange) onFilterChange({}); + }; + + const activeFiltersCount = Object.values(filters).filter(v => + v !== "" && v !== false && v !== "createdAt_desc" + ).length; + + const selectedCategory = categories.find(cat => cat.value === filters.category); + + return ( +
+
+ {/* نوار جستجو و فیلتر */} +
+
+
+ setFilters({ ...filters, search: e.target.value })} + placeholder="جستجوی دوره، مدرس، ..." + className="w-full px-4 py-2 pr-10 border border-gray-300 dark:border-gray-600 rounded-xl bg-gray-50 dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-transparent" + /> + +
+
+ + +
+ + +
+
+ {/* دسته بندی آکادمی */} +
+ + + + {selectedCategory && selectedCategory.value !== "" && ( +
+ انتخاب شده: + {selectedCategory.icon && {selectedCategory.icon}} + + {selectedCategory.label} + +
+ )} +
+ + {/* نوع دوره */} +
+ + +
+ + {/* محدوده قیمت */} +
+ +
+ handleInputChange("minPrice", e.target.value)} + className="w-1/2 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-pink-500" + /> + handleInputChange("maxPrice", e.target.value)} + className="w-1/2 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-pink-500" + /> +
+
+ + {/* مرتب سازی */} +
+ + +
+
+ +
+ handleInputChange("hasOffer", e.target.checked)} + className="w-4 h-4 text-pink-500 rounded focus:ring-pink-500" + /> + +
+ + {activeFiltersCount > 0 && ( + + )} +
+
+
+
+ ); +} \ No newline at end of file diff --git a/src/components/academy/CommentsModal.tsx b/src/components/academy/CommentsModal.tsx new file mode 100644 index 0000000..c0a3235 --- /dev/null +++ b/src/components/academy/CommentsModal.tsx @@ -0,0 +1,489 @@ +import React, { useState, useRef, useCallback, useEffect } from "react"; +import Modal from "../elements/Modal"; +import Image from "next/image"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import RoundedInput from "@/components/elements/RoundedInput"; +import useAxios from "@/hooks/useAxios"; +import toast from "react-hot-toast"; +import Rate from "rc-rate"; +import "rc-rate/assets/index.css"; +import { Course } from "@/types/types"; + +export interface Comments { + _id: string; + comment: string; + rate: number; + createdAt: string; + updatedAt: string; + status: string; + user_id: { + _id: string; + user_name: string; + profile_image: string; + is_verified: string; + }; + course_id: string; + likes: number; + isEdited: boolean; +} + +interface CommentsModalProps { + isOpen: boolean; + onClose: () => void; + postData: Course; + onCommentAdded?: () => void; +} + +function CommentsModal({ + isOpen, + onClose, + postData, + onCommentAdded, +}: CommentsModalProps) { + const { _id, cuorse_name } = postData; + + const [newMessage, setNewMessage] = useState(""); + const [rating, setRating] = useState(0); + const [comments, setComments] = useState([]); + const [totalComments, setTotalComments] = useState(0); + const [averageRate, setAverageRate] = useState(0); + const [loading, setLoading] = useState(false); + const [page, setPage] = useState(1); + const [hasMore, setHasMore] = useState(true); + const [statusFilter, setStatusFilter] = useState("accepted"); + const [sortBy, setSortBy] = useState("createdAt"); + const [sortOrder, setSortOrder] = useState("desc"); + const [usersCache, setUsersCache] = useState>({}); + + const { request } = useAxios(); + const containerRef = useRef(null); + + // تابع دریافت اطلاعات کاربر با caching + const fetchUserInfo = async (userId: string) => { + if (usersCache[userId]) { + return usersCache[userId]; + } + + try { + const response = await request("GET", `/profile/${userId}`); + if (response?.user) { + const userData = response.user; + setUsersCache((prev) => ({ ...prev, [userId]: userData })); + return userData; + } + } catch (error) { + console.error(`Error fetching user ${userId}:`, error); + } + return null; + }; + + // دریافت تعداد کل کامنت‌ها و آمار + const fetchCommentsStats = async () => { + if (!_id) return; + + try { + const response = await request( + "GET", + `/academy/course/${_id}/comments/count` + ); + if (response?.success) { + setTotalComments(response.data.totalComments); + setAverageRate(response.data.averageRate || 0); + } + } catch (error) { + console.error("Error fetching stats:", error); + } + }; + + // دریافت لیست کامنت‌ها + const fetchComments = async (pageNum: number, append = false) => { + if (loading || !_id) return; + + setLoading(true); + try { + const response = await request( + "GET", + `/academy/course/${_id}/comments?page=${pageNum}&limit=20&status=${statusFilter}&sortBy=${sortBy}&sortOrder=${sortOrder}` + ); + + if (response?.success) { + let newComments = response.data.comments; + const pagination = response.data.pagination; + + if (newComments && newComments.length > 0) { + // بررسی اینکه آیا بک‌اند اطلاعات کاربر را populate کرده است + if (newComments[0]?.user_id?.user_name) { + // اطلاعات کاربر قبلاً داخل کامنت است + setComments((prev) => + append ? [...prev, ...newComments] : newComments + ); + } else { + // اگر بک‌اند فقط user_id را برگردانده، اطلاعات کاربر را بگیریم + const uniqueUserIds = [...new Set(newComments.map((c) => c.user_id))]; + + // دریافت اطلاعات همه کاربران به صورت همزمان + const usersData = await Promise.all( + uniqueUserIds.map((id) => fetchUserInfo(id)) + ); + + // ساخت mapping از userId به اطلاعات کاربر + const userMap: Record = {}; + uniqueUserIds.forEach((id, index) => { + userMap[id] = usersData[index]; + }); + + // ترکیب کامنت‌ها با اطلاعات کاربران + const commentsWithUsers = newComments.map((comment) => ({ + ...comment, + user_id: userMap[comment.user_id] || { + _id: comment.user_id, + user_name: "کاربر ناشناس", + profile_image: null, + is_verified: "unverified" + }, + })); + + setComments((prev) => + append ? [...prev, ...commentsWithUsers] : commentsWithUsers + ); + } + } else { + setComments(append ? [...prev] : []); + } + + setHasMore(pagination?.hasNextPage || false); + if (pagination?.totalItems) { + setTotalComments(pagination.totalItems); + } + } + } catch (error) { + console.error("Error fetching comments:", error); + toast.error("خطا در دریافت نظرات"); + } finally { + setLoading(false); + } + }; + + // لود اولیه و هنگام تغییر فیلترها + useEffect(() => { + if (isOpen && _id) { + setPage(1); + setComments([]); + fetchComments(1, false); + fetchCommentsStats(); + } + }, [isOpen, _id, statusFilter, sortBy, sortOrder]); + + // اینفینیت اسکرول + const observer = useRef(null); + const lastCommentRef = useCallback( + (node: HTMLDivElement) => { + if (loading) return; + if (observer.current) observer.current.disconnect(); + observer.current = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting && hasMore) { + setPage((prev) => prev + 1); + } + }); + if (node) observer.current.observe(node); + }, + [loading, hasMore] + ); + + useEffect(() => { + if (page > 1) { + fetchComments(page, true); + } + }, [page]); + + // ارسال کامنت جدید + const sendMessageHandler = async () => { + if (!newMessage.trim()) { + toast.error("ثبت نظر الزامی است."); + return; + } + if (newMessage.length > 500) { + toast.error("کامنت نمی‌تواند بیش از 500 کاراکتر باشد."); + return; + } + if (rating === 0) { + toast.error("ثبت امتیاز الزامی است."); + return; + } + + try { + const response = await request("POST", "/academy/comment/create", { + course_id: _id, + comment: newMessage, + rate: rating, + }); + + if (response?.success) { + toast.success("نظر شما با موفقیت ثبت شد"); + setNewMessage(""); + setRating(0); + + // ریست کردن صفحه و دریافت مجدد کامنت‌ها + setPage(1); + setComments([]); + await fetchComments(1, false); + await fetchCommentsStats(); + + if (onCommentAdded) { + onCommentAdded(); + } + } + } catch (error: any) { + console.error("Error sending comment:", error); + toast.error(error?.response?.data?.message || "خطا در ثبت نظر"); + } + }; + + // تغییر وضعیت کامنت + const handleStatusChange = async (commentId: string, newStatus: string) => { + try { + const response = await request( + "PATCH", + `/academy/comment/${commentId}/status`, + { + status: newStatus, + } + ); + + if (response?.success) { + toast.success(response.message); + setPage(1); + setComments([]); + await fetchComments(1, false); + } + } catch (error: any) { + console.error("Error changing status:", error); + toast.error(error?.response?.data?.message || "خطا در تغییر وضعیت"); + } + }; + + // حذف کامنت + const handleDeleteComment = async (commentId: string) => { + if (!confirm("آیا از حذف این کامنت مطمئن هستید؟")) return; + + try { + const response = await request( + "DELETE", + `/academy/comment/${commentId}/delete` + ); + + if (response?.success) { + toast.success("کامنت با موفقیت حذف شد"); + setPage(1); + setComments([]); + await fetchComments(1, false); + await fetchCommentsStats(); + } + } catch (error: any) { + console.error("Error deleting comment:", error); + toast.error(error?.response?.data?.message || "خطا در حذف کامنت"); + } + }; + + // دریافت وضعیت نمایشی + const getStatusBadge = (status: string) => { + switch (status) { + case "accepted": + return ( + + تایید شده + + ); + case "pending": + return ( + + در انتظار تایید + + ); + case "rejected": + return ( + + رد شده + + ); + default: + return null; + } + }; + + // کامپوننت نمایش ستاره‌ها + const renderStars = (rate: number) => { + return ( +
+ {[1, 2, 3, 4, 5].map((star) => ( + + + + ))} +
+ ); + }; + + return ( + +
+ {/* هدر مودال */} +
+

{cuorse_name}

+
+ 📝 {totalComments} نظر + {averageRate > 0 && ⭐ {averageRate.toFixed(1)} / 5} +
+
+ + {/* بخش لیست کامنت‌ها */} +
+ {!loading && comments.length === 0 ? ( +

+ هنوز نظری ثبت نشده است. اولین نفری باشید که نظر می‌دهید! +

+ ) : ( + comments.map((item, index) => ( +
+
+ {/* آواتار کاربر */} +
+ {item?.user_id?.user_name +
+ +
+ {/* اطلاعات کاربر و امتیاز */} +
+ + {item?.user_id?.user_name || "کاربر ناشناس"} + + + {item?.user_id?.is_verified === "verified" && ( + verify + )} + + {item?.rate > 0 && ( +
+ {renderStars(item.rate)} +
+ )} + + {/* وضعیت کامنت (اختیاری) */} + {item.status && item.status !== "accepted" && ( +
+ {getStatusBadge(item.status)} +
+ )} +
+ + {/* متن کامنت */} +

+ {item.comment} +

+ + {/* متادیتا */} +
+ + {new Date(item.createdAt).toLocaleDateString("fa-IR")} + + + ❤️ {item.likes || 0} + + {item.isEdited && ( + (ویرایش شده) + )} +
+
+
+
+ )) + )} + + {loading && ( +
+
+

+ در حال بارگذاری نظرات... +

+
+ )} +
+ + {/* بخش ارسال نظر */} +
+
+ setRating(value)} + count={5} + style={{ fontSize: "28px" }} + /> +
+ + { + if (e.target.value.length <= 500) + setNewMessage(e.target.value); + }} + placeholder="نظر خود را بنویسید..." + className="flex-1" + /> +
+
+ {newMessage.length}/500 کاراکتر + {rating > 0 && امتیاز: {rating} از 5} +
+
+
+
+
+ ); +} + +export default CommentsModal; \ No newline at end of file diff --git a/src/components/academy/InfinitePakage.tsx b/src/components/academy/InfinitePakage.tsx new file mode 100644 index 0000000..b895b88 --- /dev/null +++ b/src/components/academy/InfinitePakage.tsx @@ -0,0 +1,292 @@ +"use client"; + +import React, { useEffect, useCallback, useState, useRef } from "react"; +import MainModelCard from "./MainModelCard"; +import { Course } from "@/types/types"; +import Image from "next/image"; +import useAxios from "@/hooks/useAxios"; +import toast from "react-hot-toast"; +import { motion, AnimatePresence } from "framer-motion"; + +interface InfinitePostsProps { + token: string; + filters: { + hashtag?: string; + expertise?: string; + province?: string; + city?: string; + userLevel?: string; + rateFilter?: string; + _id?: string; + search?: string; + category?: string; + minPrice?: number; + maxPrice?: number; + hasOffer?: boolean; + teacherName?: string; + type?: string; + sortBy?: string; + sortOrder?: string; + }; + typeFilter?: "image" | "video"; +} + +export default function InfinitePosts({ filters, token }: InfinitePostsProps) { + const [courses, setCourses] = useState([]); + const [coursesPage, setCoursesPage] = useState(1); + const [hasMoreCourses, setHasMoreCourses] = useState(true); + const [isLoadingMoreCourses, setIsLoadingMoreCourses] = useState(false); + const [isInitialCoursesLoading, setIsInitialCoursesLoading] = useState(true); + const [totalItems, setTotalItems] = useState(0); + const loadMoreRef = useRef(null); + const { request } = useAxios(); + + // ساخت query string از فیلترها + const buildQueryString = (page: number) => { + const params = new URLSearchParams(); + + // صفحه‌بندی + params.append("page", page.toString()); + params.append("limit", "5"); + params.append("status", "accept"); + + // فیلترهای جستجو - مطابق با بک‌اند + if (filters?.search && filters.search.trim() !== "") { + params.append("search", filters.search); + } + if (filters?.category && filters.category !== "") { + params.append("category", filters.category); + } + if (filters?.minPrice && filters.minPrice > 0) { + params.append("minPrice", filters.minPrice.toString()); + } + if (filters?.maxPrice && filters.maxPrice > 0) { + params.append("maxPrice", filters.maxPrice.toString()); + } + if (filters?.hasOffer) { + params.append("hasOffer", "true"); + } + if (filters?.teacherName && filters.teacherName.trim() !== "") { + params.append("teacherName", filters.teacherName); + } + if (filters?.type && filters.type !== "") { + params.append("type", filters.type); + } + if (filters?.sortBy && filters.sortBy !== "createdAt") { + params.append("sortBy", filters.sortBy); + } + if (filters?.sortOrder && filters.sortOrder !== "desc") { + params.append("sortOrder", filters.sortOrder); + } + + console.log("Query params:", params.toString()); + return params.toString(); + }; + + // تابع دریافت دوره‌ها با صفحه‌بندی و فیلتر + const fetchCourses = async (page: number, isLoadMore = false) => { + if (isLoadMore) { + setIsLoadingMoreCourses(true); + } + + try { + const queryString = buildQueryString(page); + // آدرس صحیح API - با توجه به بک‌اند شما + const url = `/academy/academy/get/curses${queryString ? `?${queryString}` : ""}`; + + console.log("Fetching URL:", url); + + const response = await request("GET", url); + + console.log(`Courses page ${page} response:`, response); + + let newCourses: Course[] = []; + let total = 0; + + // بررسی ساختار پاسخ بر اساس بک‌اند + if (response?.success && response?.data?.courses) { + newCourses = response.data.courses; + total = response.data.pagination?.totalItems || 0; + setHasMoreCourses(response.data.pagination?.hasNextPage || false); + setTotalItems(total); + } + // ساختار جایگزین + else if (response?.data?.courses) { + newCourses = response.data.courses; + total = response.data.pagination?.totalItems || 0; + setHasMoreCourses(response.data.pagination?.hasNextPage || false); + setTotalItems(total); + } + else if (response?.courses && Array.isArray(response.courses)) { + newCourses = response.courses; + setHasMoreCourses(newCourses.length === 5); + setTotalItems(newCourses.length); + } + else if (Array.isArray(response)) { + newCourses = response; + setHasMoreCourses(newCourses.length === 5); + setTotalItems(newCourses.length); + } + else { + console.error("Unexpected response structure:", response); + setHasMoreCourses(false); + if (!isLoadMore) { + setCourses([]); + } + } + + if (isLoadMore) { + setCourses((prev) => [...prev, ...newCourses]); + } else { + setCourses(newCourses); + } + + setCoursesPage(page); + } catch (err: any) { + console.error("get error:", err); + toast.error(err?.message || "خطا در دریافت اطلاعات"); + setHasMoreCourses(false); + } finally { + if (isLoadMore) { + setIsLoadingMoreCourses(false); + } + setIsInitialCoursesLoading(false); + } + }; + + // بازنشانی و لود مجدد هنگام تغییر فیلترها + useEffect(() => { + // ریست کردن state‌ها + setCourses([]); + setCoursesPage(1); + setHasMoreCourses(true); + setIsInitialCoursesLoading(true); + setTotalItems(0); + + // لود مجدد با فیلترهای جدید + fetchCourses(1, false); + }, [ + filters?.search, + filters?.category, + filters?.minPrice, + filters?.maxPrice, + filters?.hasOffer, + filters?.teacherName, + filters?.type, + filters?.sortBy, + filters?.sortOrder, + ]); + + // تنظیم Intersection Observer برای لود خودکار + useEffect(() => { + if (!hasMoreCourses || isLoadingMoreCourses || isInitialCoursesLoading) + return; + + const observer = new IntersectionObserver( + (entries) => { + if ( + entries[0].isIntersecting && + hasMoreCourses && + !isLoadingMoreCourses + ) { + fetchCourses(coursesPage + 1, true); + } + }, + { threshold: 0.1, rootMargin: "100px" } + ); + + if (loadMoreRef.current) { + observer.observe(loadMoreRef.current); + } + + return () => observer.disconnect(); + }, [ + hasMoreCourses, + isLoadingMoreCourses, + coursesPage, + isInitialCoursesLoading, + ]); + + if (isInitialCoursesLoading) { + return ( +
+
+
+
+
+
+ ); + } + + if (courses.length === 0 && !isInitialCoursesLoading) { + return ( +
+
📚
+

+ هیچ دوره‌ای با این فیلترها یافت نشد +

+

+ لطفاً فیلترهای دیگری را امتحان کنید +

+
+ ); + } + + return ( +
+ {/* نمایش تعداد نتایج */} +
+ {totalItems.toLocaleString()} دوره پیدا شد +
+ + {/* نمایش دوره‌ها */} + + {courses.map((post, index) => ( + + +
+
+ ))} +
+ + {/* المان تریگر برای لود خودکار */} + {hasMoreCourses && courses.length > 0 && ( +
+ {isLoadingMoreCourses ? ( +
+
+ + در حال بارگذاری دوره‌های بیشتر... + +
+ ) : ( +
+ +
+ )} +
+ )} + + {/* پیام پایان لیست */} + {!hasMoreCourses && courses.length > 0 && ( +
+ به انتهای لیست دوره‌ها رسیدید ({totalItems.toLocaleString()} دوره) +
+ )} +
+ ); +} \ No newline at end of file diff --git a/src/components/academy/MainModelCard.tsx b/src/components/academy/MainModelCard.tsx new file mode 100644 index 0000000..f5dc8ad --- /dev/null +++ b/src/components/academy/MainModelCard.tsx @@ -0,0 +1,557 @@ +"use client"; + +import React, { + useState, + useRef, + useEffect, + useContext, + createContext, + useCallback, +} from "react"; +import { Academy, Course } from "@/types/types"; +import Image from "next/image"; +import MainModelCardActions from "./MainModelCardActions"; +import Link from "next/link"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import { useUserById } from "@/hooks/getUserById"; +import "slick-carousel/slick/slick.css"; +import "slick-carousel/slick/slick-theme.css"; +import useAxios from "@/hooks/useAxios"; +import { useRouter } from "next/navigation"; +import { forEach } from "lodash"; + +// ایجاد Context برای به اشتراک گذاشتن وضعیت muted بین همه کارت‌ها +const MutedContext = createContext<{ + muted: boolean; + setMuted: React.Dispatch>; +}>({ + muted: true, + setMuted: () => {}, +}); + +interface AcademyResponse { + academy: Academy; +} + +function MainModelCard({ postData }: { postData: Course }) { + const { + user_id, + caption, + type, + price, + cuorse_name, + category, + offer, + academyId, + number_of_course_content, + course_image, + } = postData; + + // console.log(postData._id); + + + const user = useUserById(user_id); + const profile_image = user?.profile_image; + const is_verified = user?.is_verified; + const user_score = user?.user_score; + const rate = user?.rate; + + const { request } = useAxios(); + const router = useRouter() + const [academy, setAcademy] = useState(null); + + + const { _id } = postData; + + const [newScore, setNewScore] = useState(0); + const [rating, setRating] = useState(0); + const [comments, setComments] = useState([]); + const [totalComments, setTotalComments] = useState(0); + const [averageRate, setAverageRate] = useState(0); + const [loading, setLoading] = useState(false); + const [page, setPage] = useState(1); + const [hasMore, setHasMore] = useState(true); + const [statusFilter, setStatusFilter] = useState("accepted"); + const [sortBy, setSortBy] = useState("createdAt"); + const [sortOrder, setSortOrder] = useState("desc"); + const [usersCache, setUsersCache] = useState>({}); + + + const containerRef = useRef(null); + + // تابع دریافت اطلاعات کاربر با caching + const fetchUserInfo = async (userId: string) => { + if (usersCache[userId]) { + return usersCache[userId]; + } + + try { + const response = await request("GET", `/profile/${userId}`); + if (response?.user) { + const userData = response.user; + setUsersCache((prev) => ({ ...prev, [userId]: userData })); + return userData; + } + } catch (error) { + console.error(`Error fetching user ${userId}:`, error); + } + return null; + }; + + // دریافت تعداد کل کامنت‌ها و آمار + const fetchCommentsStats = async () => { + if (!_id) return; + + try { + const response = await request( + "GET", + `/academy/course/${_id}/comments/count` + ); + if (response?.success) { + setTotalComments(response.data.totalComments); + setAverageRate(response.data.averageRate || 0); + } + } catch (error) { + console.error("Error fetching stats:", error); + } + }; + + // دریافت لیست کامنت‌ها + const fetchComments = async (pageNum: number, append = false) => { + if (loading || !_id) return; + + setLoading(true); + try { + const response = await request( + "GET", + `/academy/course/${_id}/comments?page=${pageNum}&limit=20&status=${statusFilter}&sortBy=${sortBy}&sortOrder=${sortOrder}` + ); + + let sum = 0; + let count = 0; + + response.data.stats.rateDistribution.forEach(element => { + sum += Number(element); + count++; + }); + + const average = sum / count; + const averagesum = sum *1; + + const roundedRating = Math.round(average * 10) / 10 + setRating(roundedRating); + setNewScore(averagesum); + + + + + + if (response?.success) { + let newComments = response.data.comments; + const pagination = response.data.pagination; + + if (newComments && newComments.length > 0) { + // بررسی اینکه آیا بک‌اند اطلاعات کاربر را populate کرده است + if (newComments[0]?.user_id?.user_name) { + // اطلاعات کاربر قبلاً داخل کامنت است + setComments((prev) => + append ? [...prev, ...newComments] : newComments + ); + } else { + // اگر بک‌اند فقط user_id را برگردانده، اطلاعات کاربر را بگیریم + const uniqueUserIds = [...new Set(newComments.map((c) => c.user_id))]; + + // دریافت اطلاعات همه کاربران به صورت همزمان + const usersData = await Promise.all( + uniqueUserIds.map((id) => fetchUserInfo(id)) + ); + + // ساخت mapping از userId به اطلاعات کاربر + const userMap: Record = {}; + uniqueUserIds.forEach((id, index) => { + userMap[id] = usersData[index]; + }); + + // ترکیب کامنت‌ها با اطلاعات کاربران + const commentsWithUsers = newComments.map((comment) => ({ + ...comment, + user_id: userMap[comment.user_id] || { + _id: comment.user_id, + user_name: "کاربر ناشناس", + profile_image: null, + is_verified: "unverified" + }, + })); + + setComments((prev) => + append ? [...prev, ...commentsWithUsers] : commentsWithUsers + ); + } + } else { + setComments(append ? [...prev] : []); + } + + setHasMore(pagination?.hasNextPage || false); + if (pagination?.totalItems) { + setTotalComments(pagination.totalItems); + } + } + } catch (error) { + console.error("Error fetching comments:", error); + toast.error("خطا در دریافت نظرات"); + } finally { + setLoading(false); + } + }; + + // لود اولیه و هنگام تغییر فیلترها + useEffect(() => { + if (_id) { + setPage(1); + setComments([]); + fetchComments(1, false); + fetchCommentsStats(); + } + }, [ _id, statusFilter, sortBy, sortOrder]); + + // اینفینیت اسکرول + const observer = useRef(null); + const lastCommentRef = useCallback( + (node: HTMLDivElement) => { + if (loading) return; + if (observer.current) observer.current.disconnect(); + observer.current = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting && hasMore) { + setPage((prev) => prev + 1); + } + }); + if (node) observer.current.observe(node); + }, + [loading, hasMore] + ); + + useEffect(() => { + if (page > 1) { + fetchComments(page, true); + } + }, [page]); + useEffect(() => { + const fetchData = async () => { + try { + const response = (await request("POST", `/academy/findAcademyById`, { + _id: academyId, + })) as AcademyResponse; + setAcademy(response?.academy); + console.log(response); + } catch (error) { + console.error("خطا در دریافت اطلاعات:", error); + } + }; + + fetchData(); + }, []); + + const [showFullCaption, setShowFullCaption] = useState(false); + + const [imageLoading, setImageLoading] = useState(true); + const videoRef = useRef(null); + const [ripple, setRipple] = useState<{ + x: number; + y: number; + key: number; + } | null>(null); + + // استفاده از Context برای وضعیت muted گلوبال + const { muted, setMuted } = useContext(MutedContext); + + const displayCaption = showFullCaption ? caption : caption?.slice(0, 40); + + const subExpertise = user?.sub_expertise || []; + const keywords = ["نمونه کار دارم", "آرایشگر سیار", "عکاس سیار"]; + const keywords2 = ["آموزشگاه دارم"]; + const keywords3 = ["سالن دارم", "آتیله دارم"]; + + const matchedExpertise = subExpertise.filter((item) => + keywords.some((keyword) => item.includes(keyword)) + ); + const matchedExpertise2 = subExpertise.filter((item) => + keywords2.some((keyword) => item.includes(keyword)) + ); + const matchedExpertise3 = subExpertise.filter((item) => + keywords3.some((keyword) => item.includes(keyword)) + ); + + // تابع برای ایجاد افکت ripple و تغییر وضعیت صدا + const handleVideoClick = (e: React.MouseEvent) => { + const v = videoRef.current; + if (!v) return; + + const rect = v.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + setRipple({ x, y, key: Date.now() }); + + // --- مهمترین اصلاح --- + v.muted = !v.muted; // اول وضعیت ویدیو را تغییر بده + setMuted(v.muted); // بعد context را Sync کن + + if (!v.muted) { + v.play().catch(() => {}); + } + + setTimeout(() => setRipple(null), 600); + }; + + // استفاده از IntersectionObserver برای پخش/توقف ویدیو بر اساس ویوپورت + useEffect(() => { + const video = videoRef.current; + if (!video || type !== "video") return; + + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + // ویدیو در ویوپورت است: پخش کن + video.play().catch(() => { + /* ignore: ممکن است به دلیل محدودیت‌های مرورگر */ + }); + video.muted = muted; // اعمال وضعیت گلوبال + } else { + // ویدیو خارج از ویوپورت: توقف کن + video.pause(); + } + }); + }, + { + threshold: 0.5, // حداقل 50% ویدیو باید در ویوپورت باشد + } + ); + + observer.observe(video); + + return () => { + observer.unobserve(video); + }; + }, [muted, type]); + + // اعمال وضعیت muted گلوبال هنگام mount یا تغییر muted + useEffect(() => { + if (videoRef.current) { + videoRef.current.muted = muted; + } + }, [muted]); + + return ( +
+{/* {type === "pro" && ( +
+ + + + نسخه پرو +
+ )} */} + +
+
+ {cuorse_name} +
+
+
+ تعداد ویدیو : {number_of_course_content} +
+

{category}

+ {matchedExpertise.map((item, index) => ( +

+ {item} +

+ ))} +
+
+
+ + {offer && parseInt(offer) > 0 ? ( + <> + {/* + {parseInt(price).toLocaleString()} + {" "} + + تومان + */} + {( + (parseInt(price) * (100 - parseInt(offer))) / + 100 + ).toLocaleString()} + + ) : ( + parseInt(price).toLocaleString() + )} + تومان + + {offer && Number(offer) > 0 ? `%${offer}` : ""} + + +
+
+

{cuorse_name}

+ {is_verified === "verified" ? ( + {"verify + ) : is_verified === "pending" ? ( + {"not-verify + ) : is_verified === "true" ? ( + verify icon + ) : ( + "" + )} +
+ {newScore || 0} + star icon +
+
+ {rating || 0} + star icon +
+
+
+
+ + +
router.push(`/academy/${postData._id}/course`)} className=" overflow-hidden rounded-2xl"> +
+ {`media-${course_image}`} setImageLoading?.(false)} + /> +
+
+ + +

+ {(showFullCaption + ? caption + : caption?.slice(0, 40) + + (caption && caption.length > 40 ? " " : " ") + ) + ?.split(/(\s+)/) + .map((part, index) => + part.startsWith("#") ? ( + + {part} + + ) : ( + part + ) + )} + {caption && caption.length > 40 && ( + setShowFullCaption(!showFullCaption)} + > + {showFullCaption ? "کمتر" : "بیشتر"} + + )} +

+ + +
+ ); +} + +// Provider برای به اشتراک گذاشتن وضعیت muted +export const MutedProvider: React.FC<{ children: React.ReactNode }> = ({ + children, +}) => { + const [muted, setMuted] = useState(true); + + return ( + + {children} + + ); +}; + +export default MainModelCard; diff --git a/src/components/academy/MainModelCardActions.tsx b/src/components/academy/MainModelCardActions.tsx new file mode 100644 index 0000000..207f0e2 --- /dev/null +++ b/src/components/academy/MainModelCardActions.tsx @@ -0,0 +1,246 @@ +"use client"; + +import { Course, Post } from "@/types/types"; +import Image from "next/image"; +import React, { useEffect, useState } from "react"; +import ReportModal from "../main/ReportModal"; +import CommentsModal from "./CommentsModal"; +import useAxios from "@/hooks/useAxios"; +import toast from "react-hot-toast"; +import RoundedButton from "@/components/elements/RoundedButton"; +import ModelDetailModal from "../models/ModelDetailModal"; +import ModelServiceModal from "../models/ModelServiceModal"; +import { useUserById } from "@/hooks/getUserById"; +import { AxiosError } from "axios"; +import useInfiniteScroll from "@/hooks/useInfiniteScroll"; +import { useRouter } from "next/navigation"; + +function MainModelCardActions({ postData }: { postData: Course }) { + const { _id, user_id, likes } = postData; + + const user = useUserById(user_id); + const expertise = user?.expertise; + const hair_color = user?.hair_color; + const eye_color = user?.eye_color; + const height = user?.height; + const size = user?.size; + const weight = user?.weight; + const services = user?.services; + + const [showReportModal, setShowReportModal] = useState(false); + const [showCommentsModal, setShowCommentsModal] = useState(false); + const [showServicesModal, setShowServicesModal] = useState(false); + const [liked, setLiked] = useState(false); + const [likesCountState, setLikesCount] = useState(likes || 0); + + const { request, loading } = useAxios(); + const router = useRouter(); + useEffect(() => { + const fetchData = async () => { + try { + const response = await request( + "POST", + `/academy/academy/course/is-like`, + { + courseId: _id, + } + ); + + setLiked(response?.isLiked); + } catch (error) { + console.error("خطا در دریافت اطلاعات:", error); + } + }; + + fetchData(); + }, []); + + const toggleLike = async () => { + if (loading) return; + + if (liked === false) { + try { + const response = await request("POST", `/academy/academy/course/like`, { + courseId: _id, + }); + + setLiked(true); + setLikesCount(Number(likesCountState) + 1); + } catch (error) { + console.error("خطا در دریافت اطلاعات:", error); + } + } + if (liked === true) { + try { + const response = await request( + "POST", + `/academy/academy/course/dislike`, + { + courseId: _id, + } + ); + + setLiked(false); + setLikesCount(Number(likesCountState) - 1); + } catch (error) { + console.error("خطا در دریافت اطلاعات:", error); + } + } + }; + + const [totalComments, setTotalComments] = useState(0); + const [averageRate, setAverageRate] = useState(0); + + // دریافت تعداد کل کامنت‌ها و آمار + + useEffect(() => { + const fetchCommentsStats = async () => { + try { + const response = await request( + "GET", + `/academy/course/${_id}/comments/count` + ); + if (response?.success) { + setTotalComments(response.data.totalComments); + setAverageRate(response.data.averageRate); + } + } catch (error) { + console.error("Error fetching stats:", error); + } + }; + + fetchCommentsStats(); + }, []); + + const copyToClipboard = async (text: string) => { + try { + await navigator.clipboard.writeText(text); + // می‌توانید یک نوتیفیکیشن یا toast اضافه کنید + alert('لینک کپی شد!'); + } catch (err) { + console.error('Failed to copy:', err); + alert('کپی نشد، لطفاً دستی کپی کنید'); + } + }; + + return ( + <> + {showReportModal && ( + setShowReportModal(false)} + /> + )} + {showCommentsModal && ( + setShowCommentsModal(false)} + postData={postData} + /> + )} + {showServicesModal && + (expertise === "مدلینگ" ? ( + setShowServicesModal(false)} + isMain + userId={user_id} + /> + ) : ( + setShowServicesModal(false)} + userId={user_id} + /> + ))} +
+ router.push(`/academy/${_id}/course`)} + className="text-sm px-4 h-8 max-sm:text-xs" + > + مشاهده پکیج + +
+ + + +
+
+ + ); +} + +export default MainModelCardActions; diff --git a/src/components/academy/ModelHead.tsx b/src/components/academy/ModelHead.tsx new file mode 100644 index 0000000..847a2ce --- /dev/null +++ b/src/components/academy/ModelHead.tsx @@ -0,0 +1,145 @@ +"use client" +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import { User } from "@/types/types"; +import Image from "next/image"; +import React, { useState } from "react"; +import ModelHeadRowTwo from "../models/ModelPage/ModelHeadRowTwo"; +import ModelHeadRowThree from "../models/ModelPage/ModelHeadRowThree"; +import useInfiniteScroll from "@/hooks/useInfiniteScroll"; + + +interface ModelHeadProps { + item2: { + postsCount: number | undefined; + allProjectsCount: number | undefined; + successfulProjectsCount: number | undefined; + }; + user: User; +} + +function ModelHead({ user, item2 }: ModelHeadProps) { + const { + profile_image, + user_name, + expertise, + sub_expertise, + first_name, + last_name, + is_verified, + user_score, + rate, + user_level, + bio, + user_type, + _id + } = user; + + + const [filter] = useState("درخواست"); + + const { data } = useInfiniteScroll({ + endpoint: "/offers", + queryKey: ["offers", filter], + params: { status_filter: filter , id: user._id}, + }); + + let AllRequests = 0; + let SuccessfulRequests = 0; + + console.log(data); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data?.pages[0]?.offerbyid?.docs?.forEach((element: any) => { + console.log(element.status); + + if (element.status === "accepted") { + SuccessfulRequests += 1; + } + + AllRequests += 1; + }); + + + + + + return ( +
+
+
+ {user_type == "user" && ( +
+

+ {expertise} + {sub_expertise ? ( + <> + {" _ "} + {sub_expertise.length !== 0 && sub_expertise.length > 1 ? ( + sub_expertise.map((subItem, index) => ( + + {subItem} + {index !== sub_expertise.length - 1 && " - "} + + )) + ) : ( +

{sub_expertise}

+ )} + + ) : ( + "" + )} +

+
+ )} +
+ {user_type == "user" && ( +
+ {item2?.postsCount} + پکیج ها +
+ )} +
+ {SuccessfulRequests} + درخواست های موفق +
+
+ {AllRequests} + کل درخواستها +
+
+
+ {profile_image ? ( + {user_name} + ) : ( + {user_name} + )} +
+ + +
+ ); +} + +export default ModelHead; diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx new file mode 100644 index 0000000..a8bf6ca --- /dev/null +++ b/src/components/app-sidebar.tsx @@ -0,0 +1,129 @@ +"use client"; + +import * as React from "react"; +import { useState, useEffect } from "react"; +import Cookies from "js-cookie"; +import { + IconDashboard, + IconInnerShadowTop, + IconTransfer, + IconWallet, + IconShoppingBag, + IconMenuOrder, + IconCrown, + IconHeart, + IconAddressBook, + IconSettings, + IconTicket, + IconMoneybag, + IconPoint, + IconLogout, + IconSwitchHorizontal, + IconShoppingCart, + IconNotification, +} from "@tabler/icons-react"; +import { NavMain } from "@/components/nav-main"; +import { + Sidebar, + SidebarContent, + SidebarHeader, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + SidebarTrigger, +} from "@/components/ui/sidebar"; +import Link from "next/link"; +import { useTranslation } from "react-i18next"; +import { useRouter } from "next/navigation"; + +interface SidebarProps { + dir?: "ltr" | "rtl"; + data?: { + navMain: any[]; + }; +} + +export function AppSidebar({ dir = "ltr", data, ...props }: SidebarProps) { + + + + + // 🆕 نقش اولیه را از کوکی بخوان + const [currentRole, setCurrentRole] = useState<"user" | "Seller">( + (Cookies.get("role") as "user" | "Seller") || "user" + ); + + useEffect(() => { + Cookies.set("role", currentRole, { expires: 100 }); + }, [currentRole]); + + + + const defaultData = { + navMain: [ + { + title: "داشبورد", + url: "/settings/academy/Dashboard", + icon: IconDashboard, + }, + { + title:"پکیج ها", + url: "/settings/academy/course", + icon: IconShoppingBag, + }, + { + title:"حسابداری", + url: "/settings/academy/wallet", + icon: IconMoneybag, + }, + // { + // title: "نظرات", + // url: "/settings/academy/comments", + // icon: IconHeart, + // }, + { + title: "مشخصات آموزشگاه", + url: "/settings/academy/storeProfile", + icon: IconSettings, + }, + { + title: "پکیج های خریداری شده", + url: "/settings/academy/my-courses", + icon: IconShoppingCart, + }, + + ], + }; + + return ( + + + + + +
+ +

+ آموزشگاه +

+ + +
+
+
+
+
+ + + + + + + + +
+ ); +} diff --git a/src/components/auth/AuthButton.tsx b/src/components/auth/AuthButton.tsx new file mode 100644 index 0000000..58006d0 --- /dev/null +++ b/src/components/auth/AuthButton.tsx @@ -0,0 +1,15 @@ +import React, { ComponentProps } from "react"; +type TButton = ComponentProps<"button"> & {}; +function AuthButton({ children, style, className, ...rest }: TButton) { + return ( + + ); +} + +export default AuthButton; diff --git a/src/components/auth/AuthHead.tsx b/src/components/auth/AuthHead.tsx new file mode 100644 index 0000000..fe3dd39 --- /dev/null +++ b/src/components/auth/AuthHead.tsx @@ -0,0 +1,23 @@ +import Image from "next/image"; +import React from "react"; + +interface IAuthHeadProps { + title: string; +} + +function AuthHead({ title }: IAuthHeadProps) { + return ( +
+ {title} + logo +
+ ); +} + +export default AuthHead; diff --git a/src/components/auth/AuthInput.tsx b/src/components/auth/AuthInput.tsx new file mode 100644 index 0000000..9fc32f3 --- /dev/null +++ b/src/components/auth/AuthInput.tsx @@ -0,0 +1,13 @@ +import React, { ComponentProps } from "react"; +type TInput = ComponentProps<"input"> & {}; +function AuthInput({ style, className, ...rest }: TInput) { + return ( + + ); +} + +export default AuthInput; diff --git a/src/components/auth/AuthNextButton.tsx b/src/components/auth/AuthNextButton.tsx new file mode 100644 index 0000000..7e9f8a6 --- /dev/null +++ b/src/components/auth/AuthNextButton.tsx @@ -0,0 +1,15 @@ +import React, { ComponentProps } from "react"; +type TButton = ComponentProps<"button"> & {}; +function AuthNextButton({ children, style, className, ...rest }: TButton) { + return ( + + ); +} + +export default AuthNextButton; diff --git a/src/components/auth/AuthRules.tsx b/src/components/auth/AuthRules.tsx new file mode 100644 index 0000000..18cda0a --- /dev/null +++ b/src/components/auth/AuthRules.tsx @@ -0,0 +1,57 @@ +import { useEffect, useState } from "react"; +import Modal from "../elements/Modal"; +import useAxios from "@/hooks/useAxios"; + +type AuthRulesProps = { + isSetting?: boolean; + isModalOpen: boolean; + setModalOpen: (value: boolean) => void; // به جای any از تایپ مشخص استفاده شده +}; + +function AuthRules({ isModalOpen, setModalOpen, isSetting }: AuthRulesProps) { + const [rules, setRules] = useState(""); + + const { request, loading, error } = useAxios(); + + const fetchData = async () => { + try { + const data = await request<{ value: string }>( + "GET", + "/settings/terms-and-conditions" + ); + setRules(data?.value || ""); + } catch (err) { + console.log(err); + } + }; + + useEffect(() => { + if (isModalOpen) { + fetchData(); + } + }, [isModalOpen]); + + return ( + setModalOpen(false)} + height="500px" + > +
+ {loading ? ( +

در حال بارگذاری...

+ ) : error ? ( +

خطا در دریافت اطلاعات

+ ) : ( +
+ )} +
+ + ); +} + +export default AuthRules; diff --git a/src/components/auth/AuthUserDetails.tsx b/src/components/auth/AuthUserDetails.tsx new file mode 100644 index 0000000..8d61ecb --- /dev/null +++ b/src/components/auth/AuthUserDetails.tsx @@ -0,0 +1,32 @@ +"use client"; +import useAxios from "@/hooks/useAxios"; +import { IProfileData } from "@/types/types"; +import React, { useEffect, useState } from "react"; + +function AuthUserDetails() { + const [userDetail, setUserDetail] = useState(null); + const { request } = useAxios(); + // Fetch user data + const fetchData = async () => { + try { + const response = await request<{ user: IProfileData }>("GET", "/profile"); + setUserDetail(response?.user || null); + } catch (err) { + console.log(err); + } + }; + useEffect(() => { + fetchData(); + }, []); + + return ( + <> + + {userDetail?.first_name} {userDetail?.last_name} + +

{userDetail?.user_name}

+ + ); +} + +export default AuthUserDetails; diff --git a/src/components/billboards/BillboardPage/BillboardContactInfoModal.tsx b/src/components/billboards/BillboardPage/BillboardContactInfoModal.tsx new file mode 100644 index 0000000..47fac63 --- /dev/null +++ b/src/components/billboards/BillboardPage/BillboardContactInfoModal.tsx @@ -0,0 +1,78 @@ +import Modal from "@/components/elements/Modal"; +import RoundedDiv from "@/components/elements/RoundedDiv"; +import { IContactInfo } from "@/types/types"; +import Image from "next/image"; +import React from "react"; + +interface IBillboardModalProps { + showContactInfoModal: boolean; + setShowContactInfoModal: (e: boolean) => void; + contactInfo: IContactInfo; +} + +const BillboardContactInfoModal: React.FC = ({ + showContactInfoModal, + setShowContactInfoModal, + contactInfo, +}) => { + const contactMethods = [ + { key: "mobile", icon: "mobile.svg", link: `tel:${contactInfo?.mobile}` }, + { key: "phone", icon: "phone.svg", link: `tel:${contactInfo?.phone}` }, + { + key: "whatsappNumber", + icon: "whatsapp.svg", + link: `https://wa.me/${contactInfo?.whatsappNumber}`, + }, + { + key: "telegramLink", + icon: "telegram.svg", + link: `https://t.me/${contactInfo?.telegramLink}`, + }, + { + key: "instagramLink", + icon: "instagram.svg", + link: `https://instagram.com/${contactInfo?.instagramLink}`, + }, + ]; + + return ( + setShowContactInfoModal(false)} + height="430px" + > +
+ اطلاعات تماس +
+ {contactMethods.map( + ({ key, icon, link }) => + contactInfo?.[key as keyof IContactInfo] && ( + + + + {contactInfo[key as keyof IContactInfo]} + + {icon} + + + ) + )} +
+
+
+ ); +}; + +export default BillboardContactInfoModal; diff --git a/src/components/billboards/BillboardPage/BillboardDescriptionModal.tsx b/src/components/billboards/BillboardPage/BillboardDescriptionModal.tsx new file mode 100644 index 0000000..23af2fa --- /dev/null +++ b/src/components/billboards/BillboardPage/BillboardDescriptionModal.tsx @@ -0,0 +1,28 @@ +import Modal from "@/components/elements/Modal"; +import React from "react"; + +interface IBillboardModalProps { + showDescriptionModal: boolean; + setShowDescriptionModal: (e: boolean) => void; + description?: string | null; +} +function BillboardDescriptionModal({ + showDescriptionModal, + setShowDescriptionModal, + description, +}: IBillboardModalProps) { + return ( + setShowDescriptionModal(false)} + height="450px" + > +
+ اطلاعات تماس +
{description}
+
+
+ ); +} + +export default BillboardDescriptionModal; diff --git a/src/components/billboards/BillboardPage/BillboardDetails.tsx b/src/components/billboards/BillboardPage/BillboardDetails.tsx new file mode 100644 index 0000000..3890812 --- /dev/null +++ b/src/components/billboards/BillboardPage/BillboardDetails.tsx @@ -0,0 +1,160 @@ +"use client"; + +import RoundedButton from "@/components/elements/RoundedButton"; +import { IContactInfo, IFeature, Service } from "@/types/types"; +import React, { useState } from "react"; +import Rate from "rc-rate"; +import "rc-rate/assets/index.css"; +import Image from "next/image"; +import useAxios from "@/hooks/useAxios"; +import BillboardServicesModal from "./BillboardServicesModal"; +import BillboardFeaturesModal from "./BillboardFeaturesModal"; +import BillboardContactInfoModal from "./BillboardContactInfoModal"; +import BillboardDescriptionModal from "./BillboardDescriptionModal"; +import ShowMap from "@/components/main/ShowMap"; +import DirectionMapModal from "@/components/main/DirectionMapModal"; + +function BillboardDetails({ + services, + features, + contactInfo, + description, + lat, + lng, + _id, + noDirection, +}: { + services?: Service[]; + features?: IFeature[]; + contactInfo?: IContactInfo; + description?: string | null; + lat?: string | number | undefined; + lng?: string | number | undefined; + _id: string; + noDirection?: boolean; +}) { + const { request } = useAxios(); + const [rating, setRating] = useState(0); + const [showServicesModal, setShowServicesModal] = useState(false); + const [showFeaturesModal, setShowFeaturesModal] = useState(false); + const [showContactInfoModal, setShowContactInfoModal] = + useState(false); + const [showDescriptionModal, setShowDescriptionModal] = + useState(false); + const [showNavigationModal, setShowNavigationModal] = + useState(false); + + const submitRateHandler = async () => { + try { + await request("POST", "/advertising/rate", { + rating: rating, + advertisingId: _id, + }); + } catch (error: unknown) { + console.log(error); + } + }; + + // lat و lng جابجاست + const correctedLat = Number(lng); + const correctedLng = Number(lat); + + return ( +
+
+ setRating(value)} + count={5} + style={{ fontSize: "28px" }} + /> +
+ {"submit.svg"} +
+
+
+ setShowServicesModal(true)} + className="text-[#00C1C2] border-[#00C1C2] h-9 mx-auto w-full" + > + لیست خدمات و کالا + + setShowFeaturesModal(true)} + className="text-[#00C1C2] border-[#00C1C2] h-9 mx-auto w-full" + > + سایر امکانات + + setShowContactInfoModal(true)} + className="text-[#00C1C2] border-[#00C1C2] h-9 mx-auto w-full" + > + نمایش تماس + + setShowDescriptionModal(true)} + className="text-[#00C1C2] border-[#00C1C2] h-9 mx-auto w-full" + > + توضیحات + +
+ {showServicesModal && services && ( + + )} + {showFeaturesModal && features && ( + + )} + {showContactInfoModal && contactInfo && ( + + )} + {showDescriptionModal && ( + + )} + {lat && lng && lat !== "undefined" && lng !== "undefined" && ( +
+ +
+ )} + {showNavigationModal && ( + + )} + {!noDirection && ( + setShowNavigationModal(true)} + className="h-9 mx-auto px-10" + > + مسیریابی + + )} +
+ ); +} + +export default BillboardDetails; diff --git a/src/components/billboards/BillboardPage/BillboardFeaturesModal.tsx b/src/components/billboards/BillboardPage/BillboardFeaturesModal.tsx new file mode 100644 index 0000000..b14b7cb --- /dev/null +++ b/src/components/billboards/BillboardPage/BillboardFeaturesModal.tsx @@ -0,0 +1,42 @@ +import Modal from "@/components/elements/Modal"; +import { IFeature } from "@/types/types"; +import React from "react"; + +interface IBillboardModalProps { + showFeaturesModal: boolean; + setShowFeaturesModal: (e: boolean) => void; + features: IFeature[]; +} +function BillboardFeaturesModal({ + showFeaturesModal, + setShowFeaturesModal, + features, +}: IBillboardModalProps) { + + return ( + setShowFeaturesModal(false)} + height="500px" + > +
+ سایر امکانات + {features?.map((feature: IFeature, index) => ( +
+
+ {feature?.value ? ( +
+ ) : ( +
+ )} + {feature?.title} +
+
+
+ ))} +
+
+ ); +} + +export default BillboardFeaturesModal; diff --git a/src/components/billboards/BillboardPage/BillboardImageSlider.tsx b/src/components/billboards/BillboardPage/BillboardImageSlider.tsx new file mode 100644 index 0000000..33b82df --- /dev/null +++ b/src/components/billboards/BillboardPage/BillboardImageSlider.tsx @@ -0,0 +1,43 @@ +"use client"; + +import React from "react"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import { Pagination } from "swiper/modules"; +import Image from "next/image"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; + +interface BillboardImageSliderProps { + images: string[]; +} + +const BillboardImageSlider: React.FC = ({ + images, +}) => { + return ( +
+ + {images.map((src, index) => ( + + {`Slide + + ))} + +
+ ); +}; + +export default BillboardImageSlider; diff --git a/src/components/billboards/BillboardPage/BillboardServicesModal.tsx b/src/components/billboards/BillboardPage/BillboardServicesModal.tsx new file mode 100644 index 0000000..108bb30 --- /dev/null +++ b/src/components/billboards/BillboardPage/BillboardServicesModal.tsx @@ -0,0 +1,32 @@ +import Modal from "@/components/elements/Modal"; +import ServiceItem from "@/components/main/Services/ServiceItem"; +import { Service } from "@/types/types"; +import React from "react"; + +interface IBillboardModalProps { + showServicesModal: boolean; + setShowServicesModal: (e: boolean) => void; + services: Service[]; +} +function BillboardServicesModal({ + showServicesModal, + setShowServicesModal, + services, +}: IBillboardModalProps) { + return ( + setShowServicesModal(false)} + height="500px" + > +
+ لیست خدمات + {services?.map((service) => ( + + ))} +
+
+ ); +} + +export default BillboardServicesModal; diff --git a/src/components/billboards/BillboardPage/BillboardsFilter.tsx b/src/components/billboards/BillboardPage/BillboardsFilter.tsx new file mode 100644 index 0000000..c8f18d1 --- /dev/null +++ b/src/components/billboards/BillboardPage/BillboardsFilter.tsx @@ -0,0 +1,164 @@ +"use client"; +import Image from "next/image"; +import { useRouter, useParams, useSearchParams } from "next/navigation"; // اضافه شدن useParams و useSearchParams +import React, { useState, useEffect } from "react"; +import RoundedInput from "@/components/elements/RoundedInput"; +import FilterModal from "./FilterModal"; +import Link from "next/link"; + +// وارد کردن دیتاها برای تبدیل نام فارسی به ID جهت روشن ماندن فیلترها +import provinces from "@/data/provinces.json"; +import cities from "@/data/cities.json"; + +function BillboardsFilter() { + const router = useRouter(); + const params = useParams(); // برای خواندن اسلاگ فارسی از URL + const searchParams = useSearchParams(); // برای خواندن کوئری پارامترها (search و sort) + + const [showFilterModal, setShowFilterModal] = useState(false); + const [stateId, setStateId] = useState(""); + const [cityId, setCityId] = useState(""); + const [category, setCategory] = useState(""); + const [sort, setSort] = useState(""); + const [searchText, setSearchText] = useState(""); + + // --- بخش جدید: همگام‌سازی وضعیت فیلتر با URL در هنگام لود شدن صفحه --- + useEffect(() => { + const slugSegments = params.slug as string[]; + if (slugSegments && slugSegments.length > 0) { + const fullText = decodeURIComponent(slugSegments[0]).replace(/-/g, ' '); + + if (fullText.startsWith("تبلیغات")) { + // استخراج دسته‌بندی + const afterAds = fullText.split("تبلیغات")[1]?.trim(); + if (afterAds) { + const extractedCat = afterAds.split("در")[0]?.trim(); + if (extractedCat && !extractedCat.includes("خدمات مد و زیبایی")) { + setCategory(extractedCat); + } + } + + // استخراج شهر یا استان و ست کردن ID آن‌ها برای فعال ماندن در مدال + if (fullText.includes("در شهر")) { + const cityName = fullText.split("در شهر")[1]?.trim(); + const foundCity = cities.find(c => cityName.includes(c.name)); + if (foundCity) setCityId(foundCity.id.toString()); + } else if (fullText.includes("در استان")) { + const provinceName = fullText.split("در استان")[1]?.trim(); + const foundProvince = provinces.find(p => provinceName.includes(p.name)); + if (foundProvince) setStateId(foundProvince.id.toString()); + } + } + } + + // ست کردن مقادیر سرچ و سورت از URL + setSearchText(searchParams.get("search") || ""); + setSort(searchParams.get("sort") || ""); + }, [params, searchParams]); + // ----------------------------------------------------------------- + + const handleFilterChange = () => { + const provinceObj = provinces.find(p => String(p.id) === String(stateId)); + const cityObj = cities.find(c => String(c.id) === String(cityId)); + + let slugParts = []; + const prefix = "تبلیغات"; + + if (category) { + slugParts.push(`${prefix}-${category.replace(/\s+/g, '-')}`); + } else { + slugParts.push(`${prefix}-خدمات-مد-و-زیبایی`); + } + + if (cityObj) { + slugParts.push(`در-شهر-${cityObj.name.replace(/\s+/g, '-')}`); + } else if (provinceObj) { + slugParts.push(`در-استان-${provinceObj.name.replace(/\s+/g, '-')}`); + } + + const finalSlug = slugParts.join("-"); + + const queryParams = new URLSearchParams(); + if (searchText) queryParams.set("search", searchText); + if (sort) queryParams.set("sort", sort); + + const queryString = queryParams.toString(); + const finalPath = `/billboards/${encodeURIComponent(finalSlug)}`; + + router.push(`${finalPath}${queryString ? `?${queryString}` : ""}`); + setShowFilterModal(false); + }; + + const clearFilters = () => { + setStateId(""); + setCityId(""); + setCategory(""); + setSort(""); + setSearchText(""); + + router.push("/billboards"); + setShowFilterModal(false); + }; + + return ( +
+
+
+ setSearchText(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && handleFilterChange()} + placeholder="جستجو" + className="w-full" + /> + handleFilterChange()} + width={25} + height={25} + alt="search icon" + src="/images/icons/search-normal.svg" + className=" min-w-[25px] absolute left-3 top-[7px] cursor-pointer" + /> +
+
+ + + add icon + +
+
+ {showFilterModal && ( + + )} +
+ ); +} + +export default BillboardsFilter; \ No newline at end of file diff --git a/src/components/billboards/BillboardPage/FilterModal.tsx b/src/components/billboards/BillboardPage/FilterModal.tsx new file mode 100644 index 0000000..48e8d52 --- /dev/null +++ b/src/components/billboards/BillboardPage/FilterModal.tsx @@ -0,0 +1,164 @@ +import React, { useEffect, useState } from "react"; +import { ICity, IProvince } from "@/types/types"; +import useAxios from "@/hooks/useAxios"; +import Modal from "@/components/elements/Modal"; +import SelectBox from "@/components/elements/SelectBox"; +import RoundedButton from "@/components/elements/RoundedButton"; + +interface IFilterProps { + setShowFilterModal: (e: boolean) => void; + setStateId: (e: string) => void; + setCityId: (e: string) => void; + setSort: (e: string) => void; + setCategory: (e: string) => void; + handleFilterChange: (e?: string) => void; + showFilterModal: boolean; + stateId: string; + cityId: string; + sort: string; + category: string; + clearFilters: () => void; +} +interface ICategory { + title: string; + _id: string; + status: boolean; +} + +function FilterModal({ + setStateId, + setCityId, + setCategory, + setSort, + stateId, + cityId, + category, + sort, + setShowFilterModal, + showFilterModal, + handleFilterChange, + clearFilters, +}: IFilterProps) { + const { request } = useAxios(); + const [allStates, setAllStates] = useState(null); + const [cities, setCities] = useState(null); + const [categories, setCategories] = useState(null); + useEffect(() => { + const fetchStates = async () => { + const response = await request<{ provinces: IProvince[] }>( + "GET", + "/provinces" + ); + setAllStates(response?.provinces || null); + }; + fetchStates(); + }, []); + useEffect(() => { + const fetchCategories = async () => { + const response = await request<{ categories: ICategory[] }>( + "GET", + "/advertising/categories" + ); + setCategories(response?.categories || null); + }; + fetchCategories(); + }, []); + + useEffect(() => { + if (stateId) { + const fetchCities = async () => { + const response = await request<{ cities: ICity[] }>( + "GET", + `/cities/${stateId}` + ); + setCities(response?.cities || []); + }; + fetchCities(); + } + }, [stateId]); + + return ( + setShowFilterModal(false)} + height="500px" + > +
+ مرتب سازی + setStateId(e.target.value)} + > + + {allStates?.map((item) => ( + + ))} + + setCityId(e.target.value)} + > + + {cities?.map((city) => ( + + ))} + + setCategory(e.target.value)} + > + + {categories?.map((cat: ICategory) => ( + + ))} + + { + if (sort !== "mostDiscount") { + setSort("mostDiscount"); + } else { + setSort(""); + } + }} + className={`h-9 w-40 mt-4 ${ + sort && sort == "mostDiscount" ? "bg-[#23bace]" : "" + }`} + > + بیشترین تخفیف + + + +
+
+ ); +} + +export default FilterModal; diff --git a/src/components/billboards/InfiniteBillboard.tsx b/src/components/billboards/InfiniteBillboard.tsx new file mode 100644 index 0000000..806bb21 --- /dev/null +++ b/src/components/billboards/InfiniteBillboard.tsx @@ -0,0 +1,115 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; + +import { fetchBillboards } from "@/api/fetchBillboards"; +import { IAdvertising } from "@/types/types"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import React, { useEffect, useRef } from "react"; +import MainBillboardCard from "./MainBillboardCard/MainBillboardCard"; +import { useRouter } from "next/navigation"; +import PageLoader from "@/components/ui/PageLoader"; + +interface InfiniteBillboardProps { + initialData: any; + token: string; + filters: { + province?: string; + city?: string; + category?: string; + sort?: string; + search?: string; + }; +} + +export default function InfiniteBillboard({ + initialData, + filters, + token, +}: InfiniteBillboardProps) { + const observerRef = useRef(null); + const router = useRouter(); + + + // تبدیل فیلترها به رشته برای استفاده در queryKey + const filterString = JSON.stringify({ + province: filters.province || "", + city: filters.city || "", + category: filters.category || "", + sort: filters.sort || "", + search: filters.search || "", + }); + + const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, refetch } = + useInfiniteQuery({ + queryKey: ["billboards", filterString], + queryFn: ({ pageParam }) => + fetchBillboards(pageParam, 10, filters, token), + initialData: { + pages: [initialData], + pageParams: [1], + }, + initialPageParam: 1, + getNextPageParam: (lastPage, allPages) => + lastPage.totalItems > allPages.length * 10 + ? allPages.length + 1 + : undefined, + staleTime: 60_000, + gcTime: 300_000, + retry: 2, + retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 8000), + placeholderData: (prev) => prev, + }); + + // بازخوانی داده‌ها هنگام تغییر فیلترها + useEffect(() => { + refetch(); + }, [filterString, refetch]); + + useEffect(() => { + if (!observerRef.current || !hasNextPage) return; + + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting && hasNextPage && !isFetchingNextPage) { + fetchNextPage(); + } + }, + { + threshold: 0.3, + rootMargin: "100px", + } + ); + + const currentRef = observerRef.current; + if (currentRef) observer.observe(currentRef); + + return () => { + if (currentRef) observer.unobserve(currentRef); + }; + }, [hasNextPage, fetchNextPage, isFetchingNextPage]); + return ( +
+ {isLoading && !data?.pages?.[0]?.advertisings?.length && ( + + )} +
+ {data?.pages?.map((page, pageIndex) => + page?.advertisings?.map((item: IAdvertising) => ( +
+ router.push(`/billboards/${item?._id}/${item?.title}`) + } + className="cursor-pointer" + key={`${item?._id}-${pageIndex}`} + > + +
+ )) + )} +
+
+ {isFetchingNextPage && } +
+
+ ); +} diff --git a/src/components/billboards/MainBillboardCard/BillboardCommentsModal.tsx b/src/components/billboards/MainBillboardCard/BillboardCommentsModal.tsx new file mode 100644 index 0000000..02d62a1 --- /dev/null +++ b/src/components/billboards/MainBillboardCard/BillboardCommentsModal.tsx @@ -0,0 +1,144 @@ +import React, { useState } from "react"; +import Modal from "../../elements/Modal"; +import Image from "next/image"; +import useInfiniteScroll from "@/hooks/useInfiniteScroll"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import RoundedInput from "@/components/elements/RoundedInput"; +import useAxios from "@/hooks/useAxios"; + +export interface Comments { + _id: string; + text: string; + createdAt: string; + updatedAt: string; + status: string; + advertisingId: string; + userId: User; + __v: never; +} + +export interface User { + profile_image: string | null; + first_name: string; + last_name: string; + user_name: string; + is_verified: string; + user_type: string; + _id: string; +} + +type ReportModalProps = { + isOpen: boolean; + onClose: () => void; + advertisingId: string; +}; + +function BillboardCommentsModal({ + isOpen, + onClose, + advertisingId, +}: ReportModalProps) { + const { data, containerRef, isFetchingNextPage } = useInfiniteScroll({ + endpoint: "/advertising/comments", + queryKey: ["comments", advertisingId], + params: { advertisingId: advertisingId }, + }); + const [newMessage, setNewMessage] = useState(""); + const { request } = useAxios(); + const sendMessageHandler = async () => { + try { + const data = { + text: newMessage, + advertisingId: advertisingId, + }; + await request("POST", "/advertising/comment", data); + } catch (error) { + console.log(error); + } + }; + return ( +
{ + e.stopPropagation(); + }} + > + +
+ {data?.pages.length === 0 || + (data?.pages[0]?.comments?.length === 0 && !isFetchingNextPage) ? ( +

نظری وجود ندارد.

+ ) : ( + data?.pages?.map((page, pageIndex) => ( + + {page?.comments?.map((item: Comments) => ( +
+
+ {item?.userId?.user_name} +
+
+ {item?.userId?.user_name} + {item?.userId?.is_verified === "verified" ? ( + {"verify + ) : item?.userId?.is_verified === "pending" ? ( + {"not-verify + ) : ( + "" + )} +
+

{item.text}

+
+
+
+ ))} +
+ )) + )} + + {isFetchingNextPage && ( +

+ در حال بارگذاری نظرات... +

+ )} +
+ + setNewMessage(e.target.value)} + /> +
+
+
+
+ ); +} + +export default BillboardCommentsModal; diff --git a/src/components/billboards/MainBillboardCard/BillboardLocationModal.tsx b/src/components/billboards/MainBillboardCard/BillboardLocationModal.tsx new file mode 100644 index 0000000..283c33e --- /dev/null +++ b/src/components/billboards/MainBillboardCard/BillboardLocationModal.tsx @@ -0,0 +1,110 @@ +"use client"; + +import React, { useMemo, useRef } from "react"; +import dynamic from "next/dynamic"; +import Image from "next/image"; +import "mapbox-gl/dist/mapbox-gl.css"; + +// Lazy load Map and Marker +const Map = dynamic(() => import("react-map-gl").then((mod) => mod.Map), { ssr: false }); +const Marker = dynamic(() => import("react-map-gl").then((mod) => mod.Marker), { ssr: false }); + +interface BillboardLocationModalProps { + showLocationModal: boolean; + setShowLocationModal: (show: boolean) => void; + lat: number; + lng: number; + address?: string; +} + +function BillboardLocationModal({ + showLocationModal, + setShowLocationModal, + lat, + lng, + address, +}: BillboardLocationModalProps) { + const mapRef = useRef(null); + const mapboxToken ="pk.eyJ1IjoiYWxkZjkyIiwiYSI6ImNscHh5ZG56dTByMXAycnJ2cDNmdDQ5M3YifQ.a_sUt1rLFMfA0jHrETcM7A" + + // لینک مسیریابی به Google Maps + const navigationLink = `https://www.google.com/maps/dir/?api=1&destination=${lat},${lng}`; + + // Memoize initial view state + const initialViewState = useMemo( + () => ({ + latitude: lat, + longitude: lng, + zoom: 14, + }), + [lat, lng] + ); + + if (!mapboxToken) { + return ( +
+
+

خطا

+

توکن Mapbox تنظیم نشده است.

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

آدرس و لوکیشن

+ {address &&

{address}

} +
+ + + آیکون مکان + + +
+
+ + مسیریابی با Google Maps + + +
+
+
+ ); +} + +export default BillboardLocationModal; \ No newline at end of file diff --git a/src/components/billboards/MainBillboardCard/MainBillboardCard.tsx b/src/components/billboards/MainBillboardCard/MainBillboardCard.tsx new file mode 100644 index 0000000..10a506d --- /dev/null +++ b/src/components/billboards/MainBillboardCard/MainBillboardCard.tsx @@ -0,0 +1,160 @@ +import RoundedDiv from "@/components/elements/RoundedDiv"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import { IAdvertising } from "@/types/types"; +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; +import MainBillboardCardActions from "./MainBillboardCardActions"; +import SEO from "@/config/SEO"; + +function MainBillboardCard({ + billboard, + adStatus, + color, + textColor, + borderColor, + showExpire, +}: { + billboard: IAdvertising; + adStatus?: string; + color?: string; + textColor?: string; + borderColor?: string; + showExpire?: boolean; +}) { + return ( +
+ + + {/* نوع تبلیغ */} + {billboard?.type === "special" && ( + + ویژه + + )} + + {/* تخفیف */} + {billboard?.showDiscount && billboard?.mostDiscountPercentage && ( +
+ {billboard?.mostDiscountPercentage}% +
+ )} + + {/* وضعیت */} + {adStatus && ( + + {adStatus} + + )} + +
+
+ {/* عنوان و دسته‌بندی */} +
+ +

+ {billboard?.category} +

+

+ {billboard?.title} +

+ + + {/* شهر، محله، آدرس */} +
+

شهر: {billboard?.city?.name || "نامشخص"}

+
محله: {billboard?.neighbourhood || "—"}
+ {/* آدرس: {billboard?.address || "—"} + {billboard?.lat && billboard?.lng && ( + + نمایش در نقشه + + )} */} +
+
+ + + + {showExpire && ( + انقضا: {billboard?.remainingTime} + )} +
+ + {/* عکس تبلیغ یا پروفایل فروشگاه */} +
+
+ {/* امتیاز */} +
+ {billboard?.rate?.adTotalRatings || "0"} + total ratings +
+
+ {billboard?.rate?.adAverageRating || "0"} + average rating +
+
+ + {/* عکس پروفایل یا اولین تصویر */} + {billboard?.images?.[0] ? ( + {billboard?.title} + ) : ( +
+ بدون تصویر +
+ )} +
+
+
+ ); +} + +export default MainBillboardCard; diff --git a/src/components/billboards/MainBillboardCard/MainBillboardCardActions.tsx b/src/components/billboards/MainBillboardCard/MainBillboardCardActions.tsx new file mode 100644 index 0000000..e2131b8 --- /dev/null +++ b/src/components/billboards/MainBillboardCard/MainBillboardCardActions.tsx @@ -0,0 +1,132 @@ +"use client"; + +import useAxios from "@/hooks/useAxios"; +import Image from "next/image"; +import React, { useEffect, useState } from "react"; +import BillboardCommentsModal from "./BillboardCommentsModal"; + +function MainBillboardCardActions({ + _id, + likedByUser, + likesCount: lCount, + viewCount, + commentsCount, + isDetail, +}: { + _id: string; + likedByUser: boolean | null; + likesCount: number; + viewCount: number; + commentsCount: number; + isDetail?: boolean; +}) { + const [showCommentsModal, setShowCommentsModal] = useState(false); + const [liked, setLiked] = useState(); + const [likesCount, setLikesCount] = useState(); + const { request, loading } = useAxios(); + + useEffect(() => { + setLiked(likedByUser); + setLikesCount(lCount); + }, []); + // تابع برای لایک کردن پست + const toggleLike = async () => { + if (loading) return; + const newLiked = !liked; + const newLikesCount = newLiked + ? Number(likesCount) + 1 + : Number(likesCount) - 1; + + // به روز رسانی وضعیت محلی برای لایک و شمارش لایک‌ها + setLiked(newLiked); + setLikesCount(newLikesCount); + + try { + await request( + "POST", + "/advertising/like", + { + advertisingId: _id, + }, + { noToast: true } + ); + } catch (error: unknown) { + console.log(error); + setLiked(!newLiked); + setLikesCount(likesCount); + } + }; + return ( +
+ {showCommentsModal && ( + setShowCommentsModal(false)} + advertisingId={_id} + /> + )} + + + +
+ ); +} + +export default MainBillboardCardActions; diff --git a/src/components/billboards/NewBillboard/MultiStepForm.tsx b/src/components/billboards/NewBillboard/MultiStepForm.tsx new file mode 100644 index 0000000..7907deb --- /dev/null +++ b/src/components/billboards/NewBillboard/MultiStepForm.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { useState } from "react"; +import Step1 from "./Step1"; +import Step2 from "./Step2"; +import Step3 from "./Step3"; +import Step4 from "./Step4"; +import Step5 from "./Step5"; + +const MultiStepForm = () => { + const [step, setStep] = useState(1); + + return ( +
+ {step === 1 && setStep(2)} />} + {step === 2 && setStep(3)} />} + {step === 3 && setStep(4)} />} + {step === 4 && setStep(5)} />} + {step === 5 && } +
+ ); +}; + +export default MultiStepForm; diff --git a/src/components/billboards/NewBillboard/Step1.tsx b/src/components/billboards/NewBillboard/Step1.tsx new file mode 100644 index 0000000..499c4df --- /dev/null +++ b/src/components/billboards/NewBillboard/Step1.tsx @@ -0,0 +1,142 @@ +"use client"; + +import RoundedButton from "@/components/elements/RoundedButton"; +import { useFormik } from "formik"; +import * as Yup from "yup"; +import LocationSelector from "./step1/LocationSelector"; +import { useBillboardForm } from "@/contexts/BillboardFormContext"; +import { useEffect, useState } from "react"; +import useAxios from "@/hooks/useAxios"; +import SelectBox from "@/components/elements/SelectBox"; +import { IAdvertisingCategory } from "@/types/types"; +import RoundedInput from "@/components/elements/RoundedInput"; +import ImageUploader from "./step1/ImageUploader"; + +const validationSchema = Yup.object({ + stateId: Yup.string().required("انتخاب استان الزامی است"), + cityId: Yup.string().required("انتخاب شهر الزامی است"), + categoryId: Yup.string().required("لطفا دسته‌بندی را انتخاب کنید"), + adsTitle: Yup.string().required("لطفا عنوان وارد کنید"), + description: Yup.string().required("توضیحات الزامی است"), + neighbourhood: Yup.string().required("محله الزامی است"), + address: Yup.string().required("آدرس الزامی است"), + images: Yup.array() + .min(1, "حداقل یک عکس انتخاب کنید") + .max(5, "حداکثر ۵ عکس می‌توانید انتخاب کنید") + .required("انتخاب تصویر الزامی است"), + markerCoordinate: Yup.array() + .of(Yup.number().required()) + .length(2, "انتخاب موقعیت روی نقشه الزامی است") + .required("انتخاب موقعیت روی نقشه الزامی است"), +}); + +const Step1 = ({ nextStep }: { nextStep: () => void }) => { + const { formData, updateForm } = useBillboardForm(); + const [categories, setCategories] = useState([]); + const { request } = useAxios(); + useEffect(() => { + const fetchData = async () => { + try { + const response = await request<{ categories: IAdvertisingCategory[] }>( + "GET", + "/advertising/categories" + ); + setCategories(response?.categories); + } catch (err) { + console.log(err); + } + }; + fetchData(); + }, []); +console.log(categories); + + const formik = useFormik({ + initialValues: { + cityId: formData.cityId || "", + stateId: formData.stateId || "", + adsTitle: formData.adsTitle || "", + categoryId: formData.categoryId || "", + images: formData.images || [], + address: formData.address || "", + neighbourhood: formData.neighbourhood || "", + description: formData.description || "", + markerCoordinate: formData.markerCoordinate || null, + }, + validationSchema, + onSubmit: (values) => { + updateForm(values); + nextStep(); + }, + }); + console.log(formik?.values); + + return ( +
+
ثبت بیلبورد
+ formik.setFieldValue("categoryId", e.target.value)} + > + + {categories?.map((item: IAdvertisingCategory) => ( + + ))} + + {formik.touched.categoryId && formik.errors.categoryId && ( +

{formik.errors.categoryId}

+ )} +
+ + {formik.touched.adsTitle && formik.errors.adsTitle && ( +

{formik.errors.adsTitle}

+ )} + + {formik.touched.address && formik.errors.address && ( +

{formik.errors.address}

+ )} +
+ + + {selectedLocation && ( + + location icon + + )} + + {formik.touched.markerCoordinate && formik.errors.markerCoordinate && ( +

+ {formik.errors.markerCoordinate as string} +

+ )} +
+ + ); +}; + +export default LocationSelector; diff --git a/src/components/billboards/NewBillboard/submitBillboard.ts b/src/components/billboards/NewBillboard/submitBillboard.ts new file mode 100644 index 0000000..8be4f91 --- /dev/null +++ b/src/components/billboards/NewBillboard/submitBillboard.ts @@ -0,0 +1,147 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { dataURLtoBlob } from "@/helpers/helpers"; +import { BillboardFormData } from "@/contexts/BillboardFormContext"; + +interface CreateAdvertisingResponse { + success: boolean; + message: string; + data: { + id: string; + }; +} + +type RequestFn = ( + method: "GET" | "POST" | "PUT" | "DELETE", + url: string, + data?: unknown +) => Promise; + +export async function submitBillboard( + formData: BillboardFormData, + isEditing: boolean, + request: RequestFn +): Promise<{ id: string } | null> { + const { + adsTitle, + categoryId, + description, + stateId, + cityId, + neighbourhood, + address, + markerCoordinate, + services, + selectedFeatures, + landline, + mobile, + telegram, + whatsapp, + instagram, + saveData, + images, + } = formData; + + const data = new FormData(); + data.append("title", adsTitle); + data.append("category", categoryId); + if (description) { + data.append("description", description); + } + data.append("province", stateId ? stateId : ""); + data.append("city", cityId ? cityId : ""); + if (neighbourhood) { + data.append("neighbourhood", neighbourhood); + } + if (address) { + data.append("address", address); + } + if (markerCoordinate) { + data.append("lat", markerCoordinate[0]); + data.append("lng", markerCoordinate[1]); + } + data.append("services", JSON.stringify(services)); + data.append("features", JSON.stringify(selectedFeatures)); + if (landline) { + data.append("contactInfo[phone]", landline); + } + if (mobile) { + data.append("contactInfo[mobile]", mobile); + } + if (telegram) { + data.append("contactInfo[telegramLink]", telegram); + } + if (whatsapp) { + data.append("contactInfo[whatsappNumber]", whatsapp); + } + if (instagram) { + data.append("contactInfo[instagramLink]", instagram); + } + if (saveData !== null && typeof saveData === "boolean") { + data.append("contactInfo[saveInfoForNextAds]", String(saveData)); + } + + data.append("type", isEditing ? formData.selectedType || "free" : "free"); + + const mostDiscountPercentage = + services.length > 0 + ? services.reduce((max, service) => { + const discount = + typeof service.discountPercentage === "number" + ? service.discountPercentage + : 0; + return discount > max ? discount : max; + }, 0) + : 0; + + if (mostDiscountPercentage) { + data.append("mostDiscountPercentage", String(mostDiscountPercentage)); + } + + images?.forEach((image) => { + if (typeof image === "string" && image.startsWith("/advertising/")) { + data.append("existingImages[]", image); + } else { + const blob = dataURLtoBlob(image); + data.append("images", blob); + } + }); + + services.forEach((service) => { + if ( + typeof service.image === "string" && + service.image.startsWith("/services/") + ) { + data.append(`existingServiceImages[${service.id}]`, service.image); + } else if (service.image) { + const blob = dataURLtoBlob(service.image); + data.append( + `serviceImages[${service.id}]`, + blob, + `service-${service.id}.jpg` + ); + } + }); + + if (isEditing) { + await request<{ id: string; message: string }>( + "POST", + `/advertising/edit/${formData?._id}`, + data + ); + return null; + } + + const response = await request( + "POST", + "/advertising/create", + data + ); + + await request("POST", "/advertising/initiate-payment-web", { + item_name: "free", + advertisingId: response.data.id, + showDiscount: false, + }); + + return { id: response.data.id }; +} diff --git a/src/components/billboards/Profile/AdProfileContent.tsx b/src/components/billboards/Profile/AdProfileContent.tsx new file mode 100644 index 0000000..47a8682 --- /dev/null +++ b/src/components/billboards/Profile/AdProfileContent.tsx @@ -0,0 +1,94 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; + +import React, { useState } from "react"; +import RoundedDiv from "@/components/elements/RoundedDiv"; +import { IAdvertisingProfile } from "@/types/types"; +import RoundedButton from "@/components/elements/RoundedButton"; +import AdProfileContentPosts from "./AdProfileContentPosts"; +import BillboardServicesModal from "../BillboardPage/BillboardServicesModal"; +import BillboardFeaturesModal from "../BillboardPage/BillboardFeaturesModal"; +import BillboardContactInfoModal from "../BillboardPage/BillboardContactInfoModal"; +import BillboardLocationModal from "../MainBillboardCard/BillboardLocationModal"; + +function AdProfileContent({ profile }: { profile: IAdvertisingProfile }) { + const [showServicesModal, setShowServicesModal] = useState(false); + const [showFeaturesModal, setShowFeaturesModal] = useState(false); + const [showContactInfoModal, setShowContactInfoModal] = useState(false); + const [showLocationModal, setShowLocationModal] = useState(false); + + const { allServices, allFeatures, contactInfo, address, lat, lng, allImages } = profile; + + return ( +
+
+ + {profile?.city?.name ? profile?.city?.name : "شهر"} + + + {profile?.neighbourhood ? profile?.neighbourhood : "محله"} + + setShowLocationModal(true)} + className="text-[12px] md:text-sm h-7 md:h-8" + > + آدرس و لوکیشن + +
+
+ setShowServicesModal(true)} + className="text-[12px] md:text-sm h-7 md:h-8" + > + خدمات و کالا + + setShowFeaturesModal(true)} + className="text-[12px] md:text-sm h-7 md:h-8" + > + امکانات + + setShowContactInfoModal(true)} + className="text-[12px] md:text-sm h-7 md:h-8" + > + تماس + +
+ + + {showServicesModal && allServices && ( + + )} + {showFeaturesModal && allFeatures && ( + + )} + {showContactInfoModal && contactInfo && ( + + )} + {showLocationModal && lat && lng && ( + + )} +
+ ); +} + +export default AdProfileContent; \ No newline at end of file diff --git a/src/components/billboards/Profile/AdProfileContentPosts.tsx b/src/components/billboards/Profile/AdProfileContentPosts.tsx new file mode 100644 index 0000000..47c4c14 --- /dev/null +++ b/src/components/billboards/Profile/AdProfileContentPosts.tsx @@ -0,0 +1,78 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; + +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import React, { useState } from "react"; +import Modal from "react-modal"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/navigation"; +import { Navigation } from "swiper/modules"; + +Modal.setAppElement("body"); + +function AdProfileContentPosts({ allImages }: { allImages: string[] }) { + const [modalIsOpen, setModalIsOpen] = useState(false); + const [selectedImageIndex, setSelectedImageIndex] = useState(0); + const images = allImages?.map((post: any) => post); + + const openModal = (index: number) => { + setSelectedImageIndex(index); + setModalIsOpen(true); + }; + + const closeModal = () => { + setModalIsOpen(false); + }; + + return ( +
+ {allImages.map((item: string, index: number) => ( +
openModal(index)} + > + post +
+))} + + + +
+ + {images.map((image, index) => ( + + Selected post + + ))} + + +
+
+
+ ); +} + +export default AdProfileContentPosts; diff --git a/src/components/billboards/Profile/AdProfileHead.tsx b/src/components/billboards/Profile/AdProfileHead.tsx new file mode 100644 index 0000000..6ac8e8d --- /dev/null +++ b/src/components/billboards/Profile/AdProfileHead.tsx @@ -0,0 +1,141 @@ +"use client" +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import { IAdvertisingProfile } from "@/types/types"; +import Image from "next/image"; +import React, { useState } from "react"; +import AdProfileHeadRowTwo from "@/components/billboards/Profile/AdProfileHeadRowTwo"; + +interface AdProfileHeadProps { + profile: IAdvertisingProfile; + id: string | null; +} + +function AdProfileHead({ profile, id }: AdProfileHeadProps) { + const { profile_image, is_self, adTotalRatings,neighbourhood, adAverageRating, about_us } = profile; + + + const [expanded, setExpanded] = useState(false); + const maxLength = 100; + + const toggleExpanded = () => setExpanded(!expanded); + + if (!about_us) return ( +
+
+
+

{neighbourhood}

+
+
+ {profile?.allImages?.length} + تصاویر +
+
+ {profile?.totalLikesCount} + لایک ها +
+
+ {profile?.totalCommentsCount} + نظرات +
+
+
+ {profile_image ? ( + {profile?.vitrine_name + ) : ( +
+ {profile?.vitrine_name +
+ )} +
+ +
+ ); + + + + return ( +
+
+
+

{neighbourhood}

+
+
+ {profile?.allImages?.length} + تصاویر +
+
+ {profile?.totalLikesCount} + لایک ها +
+
+ {profile?.totalCommentsCount} + نظرات +
+
+
+ {profile_image ? ( + {profile?.vitrine_name + ) : ( +
+ {profile?.vitrine_name +
+ )} +
+ +
+ + {about_us.length <= maxLength ? ( + about_us + ) : ( + <> + {expanded ? about_us : about_us.slice(0, maxLength) + "..."} + + + )} +
+
+ ); +} + +export default AdProfileHead; diff --git a/src/components/billboards/Profile/AdProfileHeadRowTwo.tsx b/src/components/billboards/Profile/AdProfileHeadRowTwo.tsx new file mode 100644 index 0000000..848562a --- /dev/null +++ b/src/components/billboards/Profile/AdProfileHeadRowTwo.tsx @@ -0,0 +1,65 @@ +import Image from "next/image"; +import Link from "next/link"; +import React from "react"; + +interface ProfileHeadRowTwoProps { + is_self: boolean | null; + adTotalRatings: number | null; + adAverageRating: number | null; + id: string | null; +} + +function AdProfileHeadRowTwo({ + is_self, + adTotalRatings, + adAverageRating, + id, +}: ProfileHeadRowTwoProps) { + + + return ( +
+
+
+ <> + {adAverageRating ? adAverageRating : "0"} + {"verify + +
+
+ <> + {adTotalRatings ? adTotalRatings : "0"} + {"verify + +
+
+
+ {is_self ? ( + + {"verify + + ) : ( + "" + )} +
+
+ ); +} + +export default AdProfileHeadRowTwo; diff --git a/src/components/chart-area-interactive.tsx b/src/components/chart-area-interactive.tsx new file mode 100644 index 0000000..a765a05 --- /dev/null +++ b/src/components/chart-area-interactive.tsx @@ -0,0 +1,449 @@ +"use client"; + +import * as React from "react"; +import { useState, useEffect } from "react"; +import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"; + +import { useIsMobile } from "@/hooks/use-mobile"; +import { + Card, + CardAction, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { + ChartConfig, + ChartContainer, + ChartTooltip, + ChartTooltipContent, +} from "@/components/ui/chart"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; +import useAxios from "@/hooks/useAxios"; +import toast from "react-hot-toast"; + +interface Payment { + _id: string; + price: number; + course_name: string; + course_id: any; + academy_id: string; + status: string; // "success" = پرداخت نشده, "settled" = پرداخت شده + createdAt: string; + updatedAt: string; + payment_authority: string; + payment_ref_id: string; + discountAmount: number; + taxAmount: number; + taxRate: number; + user_id: any; +} + +interface ChartDataItem { + date: string; + amount: number; + count: number; + formattedDate: string; + persianDate: string; + jalaliDate: string; +} + +const chartConfig = { + amount: { + label: "مبلغ فروش", + color: "#ff107d", + }, + count: { + label: "تعداد فروش", + color: "#10b981", + }, +} satisfies ChartConfig; + +// تبدیل تاریخ میلادی به شمسی +const toJalaliDate = (date: Date): string => { + return new Intl.DateTimeFormat("fa-IR", { + year: "numeric", + month: "numeric", + day: "numeric", + }).format(date); +}; + +// نمایش ساده برای محور X +const getJalaliDayMonth = (date: Date): string => { + return new Intl.DateTimeFormat("fa-IR", { + month: "numeric", + day: "numeric", + }).format(date); +}; + +// تابع برای تولید تمام روزهای بازه زمانی +const generateDateRange = (startDate: Date, endDate: Date): string[] => { + const dates: string[] = []; + const currentDate = new Date(startDate); + + while (currentDate <= endDate) { + dates.push(currentDate.toISOString().split("T")[0]); + currentDate.setDate(currentDate.getDate() + 1); + } + + return dates; +}; + +export function ChartAreaInteractive() { + const isMobile = useIsMobile(); + const [timeRange, setTimeRange] = useState("90d"); + const [isLoading, setIsLoading] = useState(false); + const [chartData, setChartData] = useState([]); + const [totalSales, setTotalSales] = useState(0); // مجموع فروش‌های موفق (تسویه نشده) + const [totalCount, setTotalCount] = useState(0); + const [averageAmount, setAverageAmount] = useState(0); + const [settledAmount, setSettledAmount] = useState(0); // مبلغ تسویه شده (پرداخت شده) + + const { request } = useAxios(); + + useEffect(() => { + if (isMobile) { + setTimeRange("30d"); + } + }, [isMobile]); + + // محاسبه تاریخ شروع بر اساس بازه زمانی + const getStartDate = (range: string, endDate: Date): Date => { + const start = new Date(endDate); + switch (range) { + case "7d": + start.setDate(start.getDate() - 6); + break; + case "30d": + start.setDate(start.getDate() - 29); + break; + case "90d": + start.setDate(start.getDate() - 89); + break; + default: + start.setDate(start.getDate() - 89); + } + start.setHours(0, 0, 0, 0); + return start; + }; + + // پردازش داده‌ها و تکمیل روزهای بدون فروش + const processPaymentsData = (payments: Payment[], range: string) => { + const now = new Date(); + now.setHours(23, 59, 59, 999); + const startDate = getStartDate(range, now); + + // گروه‌بندی پرداخت‌های موجود بر اساس تاریخ + const groupedByDate: { [key: string]: { amount: number; count: number } } = + {}; + let settledTotal = 0; // مجموع مبالغ تسویه شده (پرداخت شده) + + payments.forEach((payment) => { + const date = new Date(payment.createdAt); + const dateKey = date.toISOString().split("T")[0]; + + // مبلغ: price یا taxAmount + const amount = payment.taxAmount || 0; + + // محاسبه مبالغ تسویه شده (status = settled) + if (payment.status === "settled") { + settledTotal += amount; + } + + // فقط پرداخت‌های داخل بازه زمانی را برای چارت در نظر بگیر + // برای چارت، فقط فروش‌های موفق (success) را نشان می‌دهیم + if (payment.status === "success" && date >= startDate && date <= now) { + if (!groupedByDate[dateKey]) { + groupedByDate[dateKey] = { amount: 0, count: 0 }; + } + groupedByDate[dateKey].amount += amount; + groupedByDate[dateKey].count += 1; + } + if (payment.status === "settled" && date >= startDate && date <= now) { + if (!groupedByDate[dateKey]) { + groupedByDate[dateKey] = { amount: 0, count: 0 }; + } + groupedByDate[dateKey].amount += amount; + groupedByDate[dateKey].count += 1; + } + }); + + setSettledAmount(settledTotal); + + // تولید تمام روزهای بازه زمانی + const allDates = generateDateRange(startDate, now); + + // ساخت آرایه نهایی با تمام روزها (روزهای بدون فروش مقدار صفر دارند) + const result: ChartDataItem[] = allDates.map((date) => { + const existing = groupedByDate[date]; + const currentDate = new Date(date); + + return { + date: date, + amount: existing?.amount || 0, + count: existing?.count || 0, + formattedDate: currentDate.toLocaleDateString("fa-IR", { + month: "numeric", + day: "numeric", + }), + persianDate: toJalaliDate(currentDate), + jalaliDate: getJalaliDayMonth(currentDate), + }; + }); + + // محاسبه مجموع کل فروش در بازه زمانی (فقط success ها) + const total = result.reduce((sum, item) => sum + item.amount, 0); + const count = result.reduce((sum, item) => sum + item.count, 0); + const avg = count > 0 ? Math.round(total / count) : 0; + + setTotalSales(total); + setTotalCount(count); + setAverageAmount(avg); + + return result; + }; + + const fetchCoursesPayment = async () => { + setIsLoading(true); + try { + // دریافت تمام پرداخت‌ها (هم success و هم settled) + const response = await request( + "GET", + `/academy/course/getAllAcademyPayments` + ); + + console.log("تمامی پرداخت‌ها:", response?.data?.payments); + + if (response?.data?.payments && Array.isArray(response.data.payments)) { + const processedData = processPaymentsData( + response.data.payments, + timeRange + ); + setChartData(processedData); + } else { + // اگر داده‌ای نبود، یک بازه خالی با تمام روزها و مقدار صفر ایجاد کن + const now = new Date(); + const startDate = getStartDate(timeRange, now); + const allDates = generateDateRange(startDate, now); + const emptyData: ChartDataItem[] = allDates.map((date) => ({ + date: date, + amount: 0, + count: 0, + formattedDate: new Date(date).toLocaleDateString("fa-IR", { + month: "numeric", + day: "numeric", + }), + persianDate: toJalaliDate(new Date(date)), + jalaliDate: getJalaliDayMonth(new Date(date)), + })); + setChartData(emptyData); + setTotalSales(0); + setTotalCount(0); + setAverageAmount(0); + setSettledAmount(0); + } + } catch (err) { + console.log("get error:", err); + toast.error("خطا در دریافت اطلاعات"); + setChartData([]); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + fetchCoursesPayment(); + }, []); + + useEffect(() => { + if (chartData.length > 0) { + fetchCoursesPayment(); + } + }, [timeRange]); + + if (isLoading) { + return ( + + + مقدار فروش + در حال بارگذاری داده‌ها... + + +
+
+
+ ); + } + + // فرمتر محور X با تاریخ شمسی + const formatXAxis = (value: string) => { + const date = new Date(value); + return getJalaliDayMonth(date); + }; + + return ( + + +
+
+ + آمار فروش آکادمی + +
+ + + ۹۰ روز + ۳۰ روز + ۷ روز + + + +
+
+ + {chartData.length === 0 ? ( +
+
+ + + +

هیچ داده‌ای برای نمایش وجود ندارد

+

هنوز فروشی ثبت نشده است

+
+
+ ) : ( + + + + + + + + + + + + + + + { + const date = new Date(value); + return toJalaliDate(date); + }} + formatter={(value, name) => { + if (name === "amount") { + return [ + `${Number(value).toLocaleString("fa-IR")}`, + "مبلغ فروش", + ]; + } + if (name === "count") { + return [`${value}`, "تعداد فروش"]; + } + return [value, name]; + }} + indicator="dot" + /> + } + /> + + + + + )} +
+
+ ); +} diff --git a/src/components/chat/AttachmentMenu.tsx b/src/components/chat/AttachmentMenu.tsx new file mode 100644 index 0000000..3eb832e --- /dev/null +++ b/src/components/chat/AttachmentMenu.tsx @@ -0,0 +1,90 @@ +"use client"; + +import { useEffect, useRef } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import { + FiCamera, + FiFile, + FiImage, + FiMapPin, + FiVideo, +} from "react-icons/fi"; + +export type AttachmentType = "image" | "video" | "file" | "location" | "camera"; + +interface AttachmentMenuProps { + open: boolean; + onClose: () => void; + onSelect: (type: AttachmentType) => void; + anchorRef?: React.RefObject; +} + +const items: { type: AttachmentType; label: string; icon: React.ReactNode; color: string }[] = [ + { type: "camera", label: "دوربین", icon: , color: "bg-red-500" }, + { type: "image", label: "گالری", icon: , color: "bg-purple-500" }, + { type: "video", label: "ویدیو", icon: , color: "bg-blue-500" }, + { type: "file", label: "فایل", icon: , color: "bg-orange-500" }, + { type: "location", label: "موقعیت", icon: , color: "bg-green-500" }, +]; + +export default function AttachmentMenu({ + open, + onClose, + onSelect, + anchorRef, +}: AttachmentMenuProps) { + const menuRef = useRef(null); + + useEffect(() => { + if (!open) return; + const handleClick = (e: MouseEvent) => { + const target = e.target as Node; + if ( + menuRef.current && + !menuRef.current.contains(target) && + !anchorRef?.current?.contains(target) + ) { + onClose(); + } + }; + document.addEventListener("mousedown", handleClick); + return () => document.removeEventListener("mousedown", handleClick); + }, [open, onClose, anchorRef]); + + return ( + + {open && ( + + {items.map((item, i) => ( + { + onSelect(item.type); + onClose(); + }} + className="gentle-transition flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-right hover:bg-black/5 active:scale-[0.98] dark:hover:bg-white/10" + > + + {item.icon} + + {item.label} + + ))} + + )} + + ); +} diff --git a/src/components/chat/ChatActionBar.tsx b/src/components/chat/ChatActionBar.tsx new file mode 100644 index 0000000..1a43fed --- /dev/null +++ b/src/components/chat/ChatActionBar.tsx @@ -0,0 +1,52 @@ +"use client"; + +import { motion } from "framer-motion"; +import { FiCornerUpLeft, FiShare2 } from "react-icons/fi"; + +interface ChatActionBarProps { + onReply: () => void; + onForward: () => void; + onCancel: () => void; +} + +export default function ChatActionBar({ + onReply, + onForward, + onCancel, +}: ChatActionBarProps) { + return ( + +
+ + + +
+
+ ); +} diff --git a/src/components/chat/ChatDateSeparator.tsx b/src/components/chat/ChatDateSeparator.tsx new file mode 100644 index 0000000..22f66c4 --- /dev/null +++ b/src/components/chat/ChatDateSeparator.tsx @@ -0,0 +1,12 @@ +"use client"; + +/** Telegram-style centered date capsule */ +export default function ChatDateSeparator({ label }: { label: string }) { + return ( +
+ + {label} + +
+ ); +} diff --git a/src/components/chat/ChatHeader.tsx b/src/components/chat/ChatHeader.tsx new file mode 100644 index 0000000..5b91735 --- /dev/null +++ b/src/components/chat/ChatHeader.tsx @@ -0,0 +1,102 @@ +"use client"; + +import { User } from "@/types/types"; +import Image from "next/image"; +import Link from "next/link"; +import { useState } from "react"; +import { FiChevronRight } from "react-icons/fi"; +import { IMAGE_BASE_URL } from "../main/BaseUrl"; +import { useRouter } from "next/navigation"; +import ChatHeaderMenu from "./ChatHeaderMenu"; + +function ChatHeader({ + user, + searchQuery = "", + onSearchChange, + onBlockChange, +}: { + user: User | undefined; + searchQuery?: string; + onSearchChange?: (q: string) => void; + onBlockChange?: () => void; +}) { + const router = useRouter(); + const [searchOpen, setSearchOpen] = useState(false); + + const isOnline = user?.last_online === "آنلاین"; + + return ( +
+
+ + + + {user?.profile_image && !user?.blocked_you ? ( + + ) : ( +
+ )} +
+ + {user?.first_name} {user?.last_name} + + + {isOnline ? ( + آنلاین + ) : ( + user?.last_online || user?.user_name + )} + +
+ + + +
+ + + {searchOpen && ( + + onSearchChange?.(e.target.value)} + placeholder="جستجو در پیام‌ها…" + className="glass-chat-input mt-2 w-full rounded-full px-4 py-2 text-sm outline-none" + /> + + )} + +
+ ); +} + +// framer-motion for search expand +import { AnimatePresence, motion } from "framer-motion"; + +export default ChatHeader; diff --git a/src/components/chat/ChatHeaderMenu.tsx b/src/components/chat/ChatHeaderMenu.tsx new file mode 100644 index 0000000..e90a698 --- /dev/null +++ b/src/components/chat/ChatHeaderMenu.tsx @@ -0,0 +1,94 @@ +"use client"; + +import { useState } from "react"; +import { FiMoreVertical, FiSearch } from "react-icons/fi"; +import { motion, AnimatePresence } from "framer-motion"; +import { User } from "@/types/types"; +import useAxios from "@/hooks/useAxios"; + +interface ChatHeaderMenuProps { + user: User | undefined; + onSearchToggle: (open: boolean) => void; + searchOpen: boolean; + onBlockChange?: (blocked: boolean) => void; +} + +export default function ChatHeaderMenu({ + user, + onSearchToggle, + searchOpen, + onBlockChange, +}: ChatHeaderMenuProps) { + const [open, setOpen] = useState(false); + const [isBlocked, setIsBlocked] = useState(user?.is_blocked); + const { request } = useAxios(); + + const block = async () => { + await request("POST", "/users/block", { user_to_block: user?._id }); + setIsBlocked(true); + onBlockChange?.(true); + setOpen(false); + }; + + const unblock = async () => { + await request("POST", "/users/unblock", { user_to_unblock: user?._id }); + setIsBlocked(false); + onBlockChange?.(false); + setOpen(false); + }; + + return ( +
+ + + {open && ( + <> +
setOpen(false)} /> + + + {isBlocked ? ( + + ) : ( + + )} + + + )} + +
+ ); +} diff --git a/src/components/chat/ChatMessageCard.tsx b/src/components/chat/ChatMessageCard.tsx new file mode 100644 index 0000000..31ae52a --- /dev/null +++ b/src/components/chat/ChatMessageCard.tsx @@ -0,0 +1,260 @@ +"use client"; + +import Image from "next/image"; +import { useState } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import Link from "next/link"; +import { User } from "@/types/types"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import ReadReceipt from "./ReadReceipt"; +import VoiceMessagePlayer from "./VoiceMessagePlayer"; +import FileMessageBubble from "./FileMessageBubble"; +import VideoMessageBubble from "./VideoMessageBubble"; +import LocationMessageBubble, { + parseLocationContent, +} from "./LocationMessageBubble"; +import { detectChatFileType } from "@/lib/chat/detectFileType"; +import { formatBubbleTime } from "@/lib/chat/formatMessageTime"; + +export interface ChatMessage { + _id: string; + content: string; + senderId: string; + receiverId?: string; + createdAt: string; + file?: string; + fileType?: "image" | "video" | "file" | "voice" | "location"; + status?: "pending" | "sent" | "seen"; + replyTo?: { + _id: string; + content: string; + senderName?: string; + }; + forwardedFrom?: { + userId: string; + userName: string; + displayName: string; + }; +} + +interface ChatMessageCardProps { + message: ChatMessage; + userDetail: User | undefined; + selected?: boolean; + onBubbleClick?: (message: ChatMessage) => void; +} + +function parseForwarded(content: string): ChatMessage["forwardedFrom"] | null { + try { + const line = content.split("\n")[0]; + const j = JSON.parse(line); + return j.forwardedFrom ?? null; + } catch { + return null; + } +} + +const ChatMessageCard = ({ + message, + userDetail, + selected = false, + onBubbleClick, +}: ChatMessageCardProps) => { + const isSender = !!(userDetail && message.senderId === userDetail._id); + const [preview, setPreview] = useState(null); + + const forwarded = + message.forwardedFrom || parseForwarded(message.content || ""); + const locationData = parseLocationContent(message.content); + const hasLocation = message.fileType === "location" || !!locationData; + + if (!message.content && !message.file && !hasLocation) return null; + + const fileUrl = message.file?.startsWith("blob:") + ? message.file + : message.file + ? IMAGE_BASE_URL + message.file + : ""; + + const fileType = hasLocation + ? "location" + : detectChatFileType(message.file || "", message.fileType); + + const textContent = + message.content && + !parseLocationContent(message.content) && + !forwarded + ? message.content.replace(/^\{.*\}\n?/, "").trim() + : message.content?.replace(/^\{.*\}\n?/, "").trim() || ""; + + const showTextBubble = + textContent && + fileType !== "file" && + fileType !== "location" && + (!message.file || (fileType === "image" && textContent)); + + const tailClass = isSender ? "bubble-tail-out" : "bubble-tail-in"; + const timeLabel = formatBubbleTime(message.createdAt); + + const TimeInline = () => ( + + {timeLabel} + {isSender && ( + + + + )} + + ); + + const TimeBelow = () => ( + + {timeLabel} + {isSender && ( + + + + )} + + ); + + const handleBubbleClick = (e: React.MouseEvent) => { + e.stopPropagation(); + onBubbleClick?.(message); + }; + + return ( + <> + +
+ {forwarded && ( + e.stopPropagation()} + > + {forwarded.displayName} + + )} + + {message.replyTo && ( +
+ + {message.replyTo.senderName} + +

{message.replyTo.content}

+
+ )} + + +
+
+ + + {preview && ( + setPreview(null)} + > + e.stopPropagation()} + > + {fileType === "video" ? ( + + + )} + + + ); +}; + +export default ChatMessageCard; diff --git a/src/components/chat/ChatMessageList.tsx b/src/components/chat/ChatMessageList.tsx new file mode 100644 index 0000000..68b9946 --- /dev/null +++ b/src/components/chat/ChatMessageList.tsx @@ -0,0 +1,271 @@ +"use client"; + +import React, { useEffect, useState, useRef, useMemo } from "react"; +import { BASE_URL, SOCKET_URL } from "../main/BaseUrl"; +import axios from "axios"; +import ChatMessageCard, { ChatMessage } from "./ChatMessageCard"; +import ChatDateSeparator from "./ChatDateSeparator"; +import { groupMessagesByDate } from "@/lib/chat/groupMessagesByDate"; +import { dedupeChatMessages } from "@/lib/chat/dedupeMessages"; +import { formatBubbleTime } from "@/lib/chat/formatMessageTime"; +import { io } from "socket.io-client"; +import { useInfiniteQuery, useQueryClient } from "@tanstack/react-query"; +import { User } from "@/types/types"; +import { ChatMessagesSkeleton } from "@/components/ui/ChatSkeletons"; +import TypingIndicator from "./TypingIndicator"; +import IOSSpinner from "@/components/ui/IOSSpinner"; +import { AnimatePresence } from "framer-motion"; + +function belongsToThread( + msg: ChatMessage, + userId: string, + otherId: string +): boolean { + const s = String(msg.senderId); + const r = String(msg.receiverId); + return ( + (s === userId && r === otherId) || (s === otherId && r === userId) + ); +} + +interface ChatMessageListProps { + userDetail: User | undefined; + userTwoDetail: User | undefined; + pendingMessages: ChatMessage[]; + isTyping?: boolean; + onTypingChange?: (typing: boolean) => void; + searchQuery?: string; + selectedMessageId?: string; + onBubbleClick?: (message: ChatMessage) => void; +} + +const ChatMessageList = ({ + userDetail, + userTwoDetail, + pendingMessages, + isTyping = false, + onTypingChange, + searchQuery = "", + selectedMessageId, + onBubbleClick, +}: ChatMessageListProps) => { + const [receiverId, setReceiverId] = useState(""); + const scrollRef = useRef(null); + const prevScrollHeight = useRef(0); + const [toEnd, setToEnd] = useState(true); + const queryClient = useQueryClient(); + + useEffect(() => { + setReceiverId(userTwoDetail?._id || ""); + }, [userDetail, userTwoDetail]); + + const fetchMessages = async ({ pageParam = 1 }) => { + if (!userDetail?._id || !receiverId) + return { messages: [], nextPage: undefined }; + + try { + const response = await axios.get( + `${BASE_URL}/chat?senderId=${userDetail?._id}&receiverId=${receiverId}&page=${pageParam}&limit=50&_t=${Date.now()}` + ); + const msgs = (response.data.messages || []).map((m: ChatMessage) => ({ + ...m, + createdAt: formatBubbleTime(m.createdAt), + })); + return { + messages: msgs, + nextPage: + pageParam < response.data.totalPages ? pageParam + 1 : undefined, + }; + } catch (error) { + console.error("Error fetching messages:", error); + return { messages: [], nextPage: undefined }; + } + }; + + const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } = + useInfiniteQuery({ + queryKey: ["messages", userDetail?._id, receiverId], + queryFn: fetchMessages, + initialPageParam: 1, + getNextPageParam: (lastPage) => lastPage.nextPage, + staleTime: 0, + gcTime: 0, + }); + + useEffect(() => { + if (toEnd && scrollRef.current) { + setTimeout(() => { + scrollRef.current?.scrollTo({ + top: scrollRef.current.scrollHeight, + behavior: "smooth", + }); + }, 100); + } + }, [data, toEnd, pendingMessages, isTyping]); + + const handleScroll = (e: React.UIEvent) => { + if (!scrollRef.current) return; + + const isAtTopOfScroll = e.currentTarget.scrollTop === 0; + const isAtBottomOfScroll = + Math.abs( + e.currentTarget.scrollHeight - + (e.currentTarget.scrollTop + e.currentTarget.clientHeight) + ) < 48; + + if (isAtTopOfScroll && hasNextPage && !isFetchingNextPage) { + prevScrollHeight.current = e.currentTarget.scrollHeight; + fetchNextPage().then(() => { + if (scrollRef.current) { + scrollRef.current.scrollTop = + scrollRef.current.scrollHeight - prevScrollHeight.current; + } + }); + } + + setToEnd(isAtBottomOfScroll); + }; + + useEffect(() => { + if (!userDetail?._id || !receiverId) return; + const socket = io(SOCKET_URL); + + socket.emit("joinChat", { userId: userDetail._id, receiverId }); + + const belongs = (msg: ChatMessage) => + belongsToThread(msg, userDetail._id, receiverId) || + (msg.senderId === userDetail._id && msg.receiverId === receiverId) || + (msg.senderId === receiverId && msg.receiverId === userDetail._id); + + socket.on("newMessage", (message: ChatMessage) => { + if (!belongs(message)) return; + + const formatted = { + ...message, + createdAt: formatBubbleTime(message.createdAt), + }; + + queryClient.setQueryData( + ["messages", userDetail._id, receiverId], + (oldData: { pages: { messages: ChatMessage[] }[] } | undefined) => { + if (!oldData?.pages?.length) return oldData; + const exists = oldData.pages.some((p) => + p.messages.some((m) => m._id === formatted._id) + ); + if (exists) return oldData; + const newPages = [...oldData.pages]; + newPages[0] = { + ...newPages[0], + messages: [formatted, ...newPages[0].messages], + }; + return { ...oldData, pages: newPages }; + } + ); + setToEnd(true); + + if (message.senderId === receiverId) { + socket.emit("messageSeen", { + messageId: message._id, + senderId: message.senderId, + receiverId: userDetail._id, + }); + } + }); + + socket.on( + "messageStatusUpdate", + ({ messageId, status }: { messageId: string; status: ChatMessage["status"] }) => { + queryClient.setQueryData( + ["messages", userDetail._id, receiverId], + (oldData: { pages: { messages: ChatMessage[] }[] } | undefined) => { + if (!oldData) return oldData; + return { + ...oldData, + pages: oldData.pages.map((page) => ({ + ...page, + messages: page.messages.map((m) => + m._id === messageId ? { ...m, status } : m + ), + })), + }; + } + ); + } + ); + + socket.on("userTyping", ({ userId }: { userId: string }) => { + if (userId === receiverId) { + onTypingChange?.(true); + setTimeout(() => onTypingChange?.(false), 3000); + } + }); + + return () => { + socket.off("newMessage"); + socket.off("messageStatusUpdate"); + socket.off("userTyping"); + socket.disconnect(); + }; + }, [userDetail, receiverId, queryClient, onTypingChange]); + + const allMessages = useMemo(() => { + const server = + data?.pages.flatMap((page) => page.messages).reverse() || []; + const serverIds = new Set(server.map((m) => m._id)); + const pendingOnly = pendingMessages.filter((p) => !serverIds.has(p._id)); + const merged = dedupeChatMessages([...server, ...pendingOnly]); + const q = searchQuery.trim().toLowerCase(); + if (!q) return merged; + return merged.filter((m) => + (m.content || "").toLowerCase().includes(q) + ); + }, [data, pendingMessages, searchQuery]); + + const grouped = useMemo( + () => groupMessagesByDate(allMessages), + [allMessages] + ); + + return ( +
+ {isFetchingNextPage && ( +
+ +
+ )} + + {isLoading ? ( + + ) : ( +
+ {grouped.map((item, index) => + item.type === "date" ? ( + + ) : ( + + ) + )} +
+ )} + + + {isTyping && !isLoading && ( + + )} + +
+ ); +}; + +export default ChatMessageList; diff --git a/src/components/chat/FileMessageBubble.tsx b/src/components/chat/FileMessageBubble.tsx new file mode 100644 index 0000000..2ace020 --- /dev/null +++ b/src/components/chat/FileMessageBubble.tsx @@ -0,0 +1,105 @@ +"use client"; + +import { useState } from "react"; +import { FiDownload, FiFile } from "react-icons/fi"; +import IOSSpinner from "@/components/ui/IOSSpinner"; +import { cn } from "@/lib/utils"; + +interface FileMessageBubbleProps { + url: string; + fileName?: string; + isOutgoing?: boolean; +} + +/** Telegram-style file message with upload/download progress */ +export default function FileMessageBubble({ + url, + fileName = "فایل پیوست", + isOutgoing = false, +}: FileMessageBubbleProps) { + const [progress, setProgress] = useState(0); + const [downloading, setDownloading] = useState(false); + const isPending = url.startsWith("blob:"); + + const handleDownload = async () => { + if (downloading) return; + setDownloading(true); + setProgress(0); + try { + const xhr = new XMLHttpRequest(); + xhr.open("GET", url, true); + xhr.responseType = "blob"; + xhr.onprogress = (e) => { + if (e.lengthComputable) { + setProgress(Math.round((e.loaded / e.total) * 100)); + } + }; + xhr.onload = () => { + if (xhr.status === 200) { + const a = document.createElement("a"); + a.href = URL.createObjectURL(xhr.response); + a.download = fileName; + a.click(); + setProgress(100); + } + setDownloading(false); + }; + xhr.onerror = () => { + window.open(url, "_blank"); + setDownloading(false); + }; + xhr.send(); + } catch { + window.open(url, "_blank"); + setDownloading(false); + } + }; + + return ( +
+
+ {isPending || downloading ? ( + + ) : ( + + )} +
+
+

{fileName}

+ {(isPending || downloading) && ( +
+
+
+ )} + + {isPending ? "در حال آپلود…" : downloading ? `${progress}%` : "فایل"} + +
+ {!isPending && ( + + )} +
+ ); +} diff --git a/src/components/chat/ForwardMessageModal.tsx b/src/components/chat/ForwardMessageModal.tsx new file mode 100644 index 0000000..08382d4 --- /dev/null +++ b/src/components/chat/ForwardMessageModal.tsx @@ -0,0 +1,188 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { motion, AnimatePresence } from "framer-motion"; +import Image from "next/image"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import useAxios from "@/hooks/useAxios"; +import toast from "react-hot-toast"; +import IOSSpinner from "@/components/ui/IOSSpinner"; + +export interface ChatUserItem { + _id: string; + user_name: string; + first_name: string; + last_name: string; + profile_image?: string; +} + +interface ForwardMessageModalProps { + open: boolean; + onClose: () => void; + message: { + content: string; + file?: string; + fileType?: string; + forwardedFrom?: { + userId: string; + userName: string; + displayName: string; + }; + }; + currentUserId: string; + /** جلوگیری از دوباره‌نمایش در چت فعلی هنگام فوروارد به گیرندهٔ همین مکالمه */ + currentReceiverId?: string; +} + +export default function ForwardMessageModal({ + open, + onClose, + message, + currentUserId, + currentReceiverId, +}: ForwardMessageModalProps) { + const { request } = useAxios(); + const [users, setUsers] = useState([]); + const [selected, setSelected] = useState>(new Set()); + const [loading, setLoading] = useState(false); + const [sending, setSending] = useState(false); + + const loadUsers = async () => { + setLoading(true); + try { + const res = await request<{ filteredUsersData: ChatUserItem[] }>( + "GET", + "/messages?limit=100", + null, + { noToast: true } + ); + setUsers( + (res?.filteredUsersData || []).filter((u) => u._id !== currentUserId) + ); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + if (open) loadUsers(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [open]); + + const toggle = (id: string) => { + setSelected((prev) => { + const next = new Set(prev); + if (next.has(id)) next.delete(id); + else if (next.size < 50) next.add(id); + else toast.error("حداکثر ۵۰ کاربر"); + return next; + }); + }; + + const forward = async () => { + if (selected.size === 0) return; + setSending(true); + const fwdMeta = message.forwardedFrom + ? JSON.stringify({ forwardedFrom: message.forwardedFrom }) + : ""; + const content = + (fwdMeta ? fwdMeta + "\n" : "") + (message.content || "پیام فوروارد"); + + try { + const targets = Array.from(selected); + await Promise.all( + targets.map((receiverId) => + request("POST", "/chat", { + content, + receiverId, + senderId: currentUserId, + forwardedFrom: message.forwardedFrom, + }) + ) + ); + toast.success(`پیام به ${selected.size} نفر ارسال شد`); + onClose(); + setSelected(new Set()); + } catch { + toast.error("خطا در فوروارد"); + } finally { + setSending(false); + } + }; + + return ( + + {open && ( + + e.stopPropagation()} + className="glass-panel max-h-[70vh] w-full max-w-md overflow-hidden rounded-t-3xl sm:rounded-3xl" + > +
+ فوروارد به ({selected.size}/50) +
+
+ {loading ? ( +
+ +
+ ) : ( + users.map((u) => ( + + )) + )} +
+
+ + +
+
+
+ )} +
+ ); +} diff --git a/src/components/chat/ImageModal.tsx b/src/components/chat/ImageModal.tsx new file mode 100644 index 0000000..3dcc75c --- /dev/null +++ b/src/components/chat/ImageModal.tsx @@ -0,0 +1,49 @@ +import Image from "next/image"; +import RoundedButton from "@/components/elements/RoundedButton"; +import Modal from "../elements/Modal"; + +interface ImageModalProps { + isOpen: boolean; + selectedImage: File | null; + cancelImage: () => void; + confirmImage: () => void; +} + +const ImageModal = ({ + isOpen, + selectedImage, + cancelImage, + confirmImage, +}: ImageModalProps) => { + if (!isOpen || !selectedImage) return null; + + return ( + cancelImage()} height="700px"> +
+ Selected +
+ + ارسال + + + لغو + +
+
+
+ ); +}; + +export default ImageModal; diff --git a/src/components/chat/LocationMessageBubble.tsx b/src/components/chat/LocationMessageBubble.tsx new file mode 100644 index 0000000..0bf7a6e --- /dev/null +++ b/src/components/chat/LocationMessageBubble.tsx @@ -0,0 +1,68 @@ +"use client"; + +import { FiMapPin, FiNavigation } from "react-icons/fi"; + +export interface LocationData { + lat: number; + lng: number; + label?: string; +} + +interface LocationMessageBubbleProps { + location: LocationData; + isOutgoing?: boolean; +} + +export function parseLocationContent(content: string): LocationData | null { + try { + const parsed = JSON.parse(content); + if (typeof parsed.lat === "number" && typeof parsed.lng === "number") { + return parsed as LocationData; + } + } catch { + /* not JSON */ + } + return null; +} + +export default function LocationMessageBubble({ + location, + isOutgoing = false, +}: LocationMessageBubbleProps) { + const mapsUrl = `https://www.google.com/maps?q=${location.lat},${location.lng}`; + const embedUrl = `https://maps.google.com/maps?q=${location.lat},${location.lng}&z=15&output=embed`; + + return ( +
+
+ +
+ ) : ( +

+ مختصات نامعتبر — نقشه در دسترس نیست. +

+ )} + + {/* دکمه‌ها */} + +
+ + +
+ ); +} diff --git a/src/components/models/ModelPage/MainModelCardPost.tsx b/src/components/models/ModelPage/MainModelCardPost.tsx new file mode 100644 index 0000000..e61030b --- /dev/null +++ b/src/components/models/ModelPage/MainModelCardPost.tsx @@ -0,0 +1,453 @@ +"use client"; + +import React, { useState, useRef, useEffect, useContext, createContext } from "react"; +import { Post } from "@/types/types"; +import Image from "next/image"; +import MainModelCardActions from "../MainModelCard/MainModelCardActions"; +import Link from "next/link"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import { useUserById } from "@/hooks/getUserById"; +import Slider from "react-slick"; +import "slick-carousel/slick/slick.css"; +import "slick-carousel/slick/slick-theme.css"; + +// ایجاد Context برای به اشتراک گذاشتن وضعیت muted بین همه کارت‌ها +const MutedContext = createContext<{ + muted: boolean; + setMuted: React.Dispatch>; +}>({ + muted: true, + setMuted: () => {}, +}); + +function MainModelCard({ postData }: { postData: Post }) { + const { + user_id, + user_name, + first_name, + last_name, + expertise, + city, + user_level, + caption, + files, + type, + } = postData; + + const user = useUserById(user_id); + const profile_image = user?.profile_image; + const is_verified = user?.is_verified; + const user_score = user?.user_score; + const rate = user?.rate; +// console.log(user); + + const [showFullCaption, setShowFullCaption] = useState(false); + const [currentSlide, setCurrentSlide] = useState(0); + const [imageLoading, setImageLoading] = useState(true); + const videoRef = useRef(null); + const [ripple, setRipple] = useState<{ x: number; y: number; key: number } | null>(null); + + // استفاده از Context برای وضعیت muted گلوبال + const { muted, setMuted } = useContext(MutedContext); + + const displayCaption = showFullCaption ? caption : caption?.slice(0, 40); + + const subExpertise = user?.sub_expertise || []; + const keywords = ["نمونه کار دارم", "آرایشگر سیار", "عکاس سیار"]; + const keywords2 = ["آموزشگاه دارم"]; + const keywords3 = ["سالن دارم", "آتیله دارم"]; + + const matchedExpertise = subExpertise.filter((item) => + keywords.some((keyword) => item.includes(keyword)) + ); + const matchedExpertise2 = subExpertise.filter((item) => + keywords2.some((keyword) => item.includes(keyword)) + ); + const matchedExpertise3 = subExpertise.filter((item) => + keywords3.some((keyword) => item.includes(keyword)) + ); + + const mediaFiles = + files?.map((file) => ({ + ...file, + src: `${IMAGE_BASE_URL}${file.path.replace( + "/root/modstagram-back/storage", + "" + )}`, + })) || []; + + const sliderSettings = { + dots: mediaFiles.length > 1, + infinite: mediaFiles.length > 1, + speed: 500, + slidesToShow: 1, + slidesToScroll: 1, + arrows: true, + autoplay: false, + adaptiveHeight: false, + lazyLoad: "progressive" as const, + afterChange: (index: number) => setCurrentSlide(index), + }; + + // تابع برای ایجاد افکت ripple و تغییر وضعیت صدا + const handleVideoClick = (e: React.MouseEvent) => { + const v = videoRef.current; + if (!v) return; + + // گرفتن مختصات کلیک نسبت به ویدیو + const rect = v.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + // تنظیم افکت ripple + setRipple({ x, y, key: Date.now() }); + + // تغییر وضعیت صدا (گلوبال) + const newMuted = !muted; + setMuted(newMuted); + v.muted = newMuted; + if (!newMuted) { + v.play().catch(() => { + /* ignore */ + }); + } + + // حذف افکت بعد از اتمام انیمیشن + setTimeout(() => { + setRipple(null); + }, 600); // مدت زمان انیمیشن (600ms) + }; + + // استفاده از IntersectionObserver برای پخش/توقف ویدیو بر اساس ویوپورت + useEffect(() => { + const video = videoRef.current; + if (!video || type !== "video") return; + + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + // ویدیو در ویوپورت است: پخش کن + video.play().catch(() => { + /* ignore: ممکن است به دلیل محدودیت‌های مرورگر */ + }); + video.muted = muted; // اعمال وضعیت گلوبال + } else { + // ویدیو خارج از ویوپورت: توقف کن + video.pause(); + } + }); + }, + { + threshold: 0.5, // حداقل 50% ویدیو باید در ویوپورت باشد + } + ); + + observer.observe(video); + + return () => { + observer.unobserve(video); + }; + }, [muted, type]); + + // اعمال وضعیت muted گلوبال هنگام mount یا تغییر muted + useEffect(() => { + const video = videoRef.current; + if (video) { + video.muted = muted; + } + }, [muted]); + + return ( +
+ +
+
+ {user_name} +
+
+
+ {user_name} + {is_verified === "verified" && ( + verify icon + )} +
+ {user_score || 0} + star icon +
+
+ {rate || 0} + star icon +
+
+
+
+ {first_name} {last_name} +
+
+
+ {matchedExpertise2.length > 0 && ( + + + + + + + + )} + {matchedExpertise3.length > 0 && ( + + + + + + + + + + + + + )} +
+
+
+
+ {user_level || "تازه وارد"} +
+ {expertise} + + {city?.name} + + {matchedExpertise.map((item, index) => ( + + {item} + + ))} +
+
+
+
+ + +
+ {type === "image" && mediaFiles.length > 0 && ( +
+ + {mediaFiles.map((file, idx) => ( +
+ {`post-image-${idx}`} setImageLoading(false)} + loading={idx === 0 ? "eager" : "lazy"} + /> + {imageLoading && idx === currentSlide && ( +
+
+
+ )} +
+ ))} +
+ {mediaFiles.length > 1 && ( +
+ {currentSlide + 1} / {mediaFiles.length} +
+ )} +
+ )} + {type === "video" && mediaFiles.length > 0 && ( +
+
+ )} +
+ + +

+ {displayCaption} + {caption?.length && caption.length > 40 && ( + setShowFullCaption(!showFullCaption)} + > + {showFullCaption ? "کمتر" : "بیشتر"} + + )} +

+ + +
+ ); +} + +// Provider برای به اشتراک گذاشتن وضعیت muted +export const MutedProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [muted, setMuted] = useState(true); + + return ( + + {children} + + ); +}; + +export default MainModelCard; diff --git a/src/components/models/ModelPage/ModelContent.tsx b/src/components/models/ModelPage/ModelContent.tsx new file mode 100644 index 0000000..1edf22e --- /dev/null +++ b/src/components/models/ModelPage/ModelContent.tsx @@ -0,0 +1,238 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import dynamic from "next/dynamic"; +import RoundedDiv from "@/components/elements/RoundedDiv"; +import { User } from "@/types/types"; +import RoundedButton from "@/components/elements/RoundedButton"; +import ModelContentPosts from "./ModelContentPosts"; +import ModelContentProjects from "./ModelContentProjects"; +import ModelDetailModal from "../ModelDetailModal"; +import ModelServiceModal from "../ModelServiceModal"; +import Link from "next/link"; +import Cookies from "js-cookie"; +import { useRouter } from "next/navigation"; +import toast from "react-hot-toast"; +import { debounce } from "lodash"; + + +const LocationModal = dynamic(() => import("./LocationModal"), { + ssr: false, +}); + +interface ModelContentProps { + user: User | undefined; + searchParams: { + expertise?: string; + province?: string; + city?: string; + userLevel?: string; + rateFilter?: string; + }; +} + +interface Filters { + expertise?: string; + province?: string; + city?: string; + userLevel?: string; + rateFilter?: string; +} + +function ModelContent({ user, searchParams }: ModelContentProps) { + const [showProjects] = useState(false); + const [showModelDetailModal, setShowModelDetailModal] = useState(false); + const [showLocationModal, setShowLocationModal] = useState(false); + const [usertype, setUsertype] = useState(null); + + useEffect(() => { + if (typeof window !== "undefined") { + setUsertype(localStorage.getItem("usertype")); + } + }, []); + + const router = useRouter(); + const sendMsgHandler = () => { + if (user?.offer_status) { + if (usertype) { + router.push(`/settings/chats/${user?.user_name}/${user?._id}`); + } else { + notRegister(); + } + } else { + offerNeed(); + } + }; + + const notRegister = () => { + toast.error("لطفا از بخش تنظیمات، ثبت نام خود را کامل کنید."); + }; + + const offerNeed = () => { + toast.error( + "برای ارسال پیام باید یک درخواست همکاری برای کاربر ثبت کرده باشید." + ); + }; + + const [filters, setFilters] = useState({}); + const [token, setToken] = useState(""); + + useEffect(() => { + const fetchData = async () => { + const search = await searchParams; + setFilters(search); + const t = Cookies.get("token") || ""; + setToken(t); + }; + fetchData(); + }, [searchParams]); + + // Debounce برای جلوگیری از باز شدن سریع مودال + const openLocationModal = debounce(() => { + if (user?.show_location) { + setShowLocationModal(true); + } + }, 300); + + return ( +
+ + + {showModelDetailModal && + (user?.expertise == "مدلینگ" ? ( + setShowModelDetailModal(false)} + userId={user?._id} + isMain + /> + ) : ( + user && ( + setShowModelDetailModal(false)} + userId={user?._id} + /> + ) + ))} + {showLocationModal && user?.show_location && ( + setShowLocationModal(false)} + location={{ + address: user?.address, + lat: user?.lat, + lng: user?.lng, + city: user?.city, + province: user?.province, + }} + /> + )} + {user?.user_type == "user" ? ( +
+ + سایز: {user?.size || "نامشخص"} + + + وزن: {user?.weight || "نامشخص"} + + + قد: {user?.height || "نامشخص"} + + setShowModelDetailModal(!showModelDetailModal)} + className="text-[9px] md:text-sm h-7 md:h-8 max-sm:text-[8px]" + > + {user?.expertise == "مدلینگ" ? "مشخصات ظاهری" : "لیست خدمات"} + +
+ ) : ( +
+ + تاریخ آخرین بازدید: {user?.created_at || "نامشخص"} + + + تاریخ ورود: {user?.last_online || "نامشخص"} + +
+ )} + + {user?.is_self !== false && user?.is_self !== "false" ? ( +
+ + + پروفایل + + + + + پیامها + + + + لوکیشن + +
+ ) : user?.user_type == "user" ? ( +
+ setShowModelDetailModal(!showModelDetailModal)} + className="text-xs h-7 md:h-8 max-w-full max-sm:text-[8px]" + > + درخواست همکاری + + + ارسال پیام + + + لوکیشن + +
+ ) : ( +
+ setShowModelDetailModal(!showModelDetailModal)} + className="text-xs h-7 md:h-8 max-w-full max-sm:text-[8px]" + > + دعوت به همکاری + + + ارسال پیام + +
+ )} + + {user && + (showProjects ? ( + + ) : ( + + ))} +
+ ); +} + +export default ModelContent; \ No newline at end of file diff --git a/src/components/models/ModelPage/ModelContentPosts.tsx b/src/components/models/ModelPage/ModelContentPosts.tsx new file mode 100644 index 0000000..feeadcc --- /dev/null +++ b/src/components/models/ModelPage/ModelContentPosts.tsx @@ -0,0 +1,142 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { useRouter } from "next/navigation"; +import { fetchPosts } from "@/api/fetchPosts"; +import { Post, User } from "@/types/types"; +import axios from "axios"; +import { BASE_URL, IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import Image from "next/image"; +import { FaPlay } from "react-icons/fa"; +import { ChatListSkeleton } from "@/components/ui/ChatSkeletons"; +import PageLoader from "@/components/ui/PageLoader"; + +interface InfinitePostsProps { + token: string; + _id: string; + filters: { + expertise?: string; + province?: string; + city?: string; + userLevel?: string; + rateFilter?: string; + }; +} + +function ModelContentPosts({ filters, token, _id }: InfinitePostsProps) { + const router = useRouter(); + const [allUsers, setAllUsers] = useState([]); + + const fetchUsers = async () => { + try { + const response = await axios.get(`${BASE_URL}/users?limit=1000`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (response?.data?.users) { + setAllUsers(response.data.users); + } + } catch (err) { + console.error("خطا در دریافت کاربران:", err); + } + }; + + useEffect(() => { + fetchUsers(); + }, []); + + const { data, isFetchingNextPage, isLoading, isError } = useInfiniteQuery({ + queryKey: ["posts", filters, _id], + queryFn: ({ pageParam = 1 }) => + fetchPosts(pageParam as number, 9999, { ...filters, _id }, token), + getNextPageParam: (lastPage, allPages) => + lastPage.posts.length > 0 ? allPages.length + 1 : undefined, + initialPageParam: 1, + refetchOnWindowFocus: false, + }); + + const posts: Post[] = data?.pages?.flatMap((page) => page.posts) ?? []; + + const filteredPosts = posts.filter((post) => { + const user = allUsers.find((u) => u._id === post.userId); + if (!user) return true; + + let include = true; + if (filters.province && user.province?.id) + include &&= String(user.province.id) === filters.province; + if (filters.city && user.city?.id) + include &&= String(user.city.id) === filters.city; + if (filters.expertise && user.sub_expertise) + include &&= user.sub_expertise.includes(filters.expertise); + if (filters.userLevel) include &&= user.user_type === filters.userLevel; + if (filters.rateFilter) include &&= String(post.rate) === filters.rateFilter; + return include; + }); + + const openPost = (post: Post) => { + router.push(`/posts/${post._id}?userId=${_id}`); + }; + + if (isLoading) return ; + + if (isError) + return

خطایی رخ داده است.

; + + if (filteredPosts.length === 0) + return

هیچ پستی یافت نشد.

; + + return ( +
+
+ {filteredPosts.map((post) => { + const mediaFiles = + post.files?.map((file) => ({ + ...file, + src: `${IMAGE_BASE_URL}${file.path.replace("/root/modstagram-back/storage", "")}`, + })) || []; + + const firstMedia = mediaFiles[0]?.src || "/images/placeholder.png"; + + return ( + + ); + })} +
+ {isFetchingNextPage && } +
+ ); +} + +export default ModelContentPosts; diff --git a/src/components/models/ModelPage/ModelContentProjects.tsx b/src/components/models/ModelPage/ModelContentProjects.tsx new file mode 100644 index 0000000..b81fc23 --- /dev/null +++ b/src/components/models/ModelPage/ModelContentProjects.tsx @@ -0,0 +1,33 @@ +import MainProjectCard from "@/components/projects/MainProjectCard"; +import useInfiniteScroll from "@/hooks/useInfiniteScroll"; +import { Project, } from "@/types/types"; +import React from "react"; + +function ModelContentProjects({ userId }: { userId: string }) { + const { data, containerRef, isFetchingNextPage } = useInfiniteScroll({ + endpoint: `/projects/user-projects/web`, + queryKey: ["projects", userId], + params: { user_id: userId }, + }); + return ( +
+ {data?.pages.length === 0 || + (data?.pages[0]?.projects?.length === 0 && !isFetchingNextPage) ? ( +

پروژه ای وجود ندارد.

+ ) : ( + data?.pages?.map((page, pageIndex) => ( + + {page?.projects?.map((item: Project) => { + return ; + })} + + )) + )} +
+ ); +} + +export default ModelContentProjects; diff --git a/src/components/models/ModelPage/ModelHead.tsx b/src/components/models/ModelPage/ModelHead.tsx new file mode 100644 index 0000000..1386f82 --- /dev/null +++ b/src/components/models/ModelPage/ModelHead.tsx @@ -0,0 +1,145 @@ +"use client" +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import { User } from "@/types/types"; +import Image from "next/image"; +import React, { useState } from "react"; +import ModelHeadRowTwo from "./ModelHeadRowTwo"; +import ModelHeadRowThree from "./ModelHeadRowThree"; +import useInfiniteScroll from "@/hooks/useInfiniteScroll"; + + +interface ModelHeadProps { + item2: { + postsCount: number | undefined; + allProjectsCount: number | undefined; + successfulProjectsCount: number | undefined; + }; + user: User; +} + +function ModelHead({ user, item2 }: ModelHeadProps) { + const { + profile_image, + user_name, + expertise, + sub_expertise, + first_name, + last_name, + is_verified, + user_score, + rate, + user_level, + bio, + user_type, + _id + } = user; + + + const [filter] = useState("درخواست"); + + const { data } = useInfiniteScroll({ + endpoint: "/offers", + queryKey: ["offers", filter], + params: { status_filter: filter , id: user._id}, + }); + + let AllRequests = 0; + let SuccessfulRequests = 0; + + console.log(data); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data?.pages[0]?.offerbyid?.docs?.forEach((element: any) => { + console.log(element.status); + + if (element.status === "accepted") { + SuccessfulRequests += 1; + } + + AllRequests += 1; + }); + + + + + + return ( +
+
+
+ {user_type == "user" && ( +
+

+ {expertise} + {sub_expertise ? ( + <> + {" _ "} + {sub_expertise.length !== 0 && sub_expertise.length > 1 ? ( + sub_expertise.map((subItem, index) => ( + + {subItem} + {index !== sub_expertise.length - 1 && " - "} + + )) + ) : ( +

{sub_expertise}

+ )} + + ) : ( + "" + )} +

+
+ )} +
+ {user_type == "user" && ( +
+ {item2?.postsCount} + پست‌ها +
+ )} +
+ {SuccessfulRequests} + درخواست های موفق +
+
+ {AllRequests} + کل درخواستها +
+
+
+ {profile_image ? ( + {user_name} + ) : ( + {user_name} + )} +
+ + +
+ ); +} + +export default ModelHead; diff --git a/src/components/models/ModelPage/ModelHeadRowThree.tsx b/src/components/models/ModelPage/ModelHeadRowThree.tsx new file mode 100644 index 0000000..0e1c3c2 --- /dev/null +++ b/src/components/models/ModelPage/ModelHeadRowThree.tsx @@ -0,0 +1,41 @@ +'use client' +import React, { useState } from "react"; + +interface ProfileHeadRowThreeProps { + user_level: string | undefined; + bio: string | undefined; +} + +function ModelHeadRowThree({ user_level, bio }: ProfileHeadRowThreeProps) { + const [showFull, setShowFull] = useState(false); + + if (!bio) bio = ""; // اطمینان از اینکه bio همیشه رشته است + const shouldTruncate = bio.length > 100; + const displayedBio = showFull || !shouldTruncate ? bio : bio.slice(0, 100); + + return ( +
+
+

+ {displayedBio} + {shouldTruncate && !showFull ? "..." : "..."} + {shouldTruncate && ( + + )} +

+
+
+ سطح: {user_level ? user_level : "تازه وارد"} +
+
+
+
+ ); +} + +export default ModelHeadRowThree; diff --git a/src/components/models/ModelPage/ModelHeadRowTwo.tsx b/src/components/models/ModelPage/ModelHeadRowTwo.tsx new file mode 100644 index 0000000..5e69b92 --- /dev/null +++ b/src/components/models/ModelPage/ModelHeadRowTwo.tsx @@ -0,0 +1,91 @@ +import { useUserById } from "@/hooks/getUserById"; +import Image from "next/image"; +import React from "react"; + +interface ProfileHeadRowTwoProps { + first_name: string; + last_name: string; + is_verified: string; + user_name: string; + user_score?: string; + rate?: string; + user_id:string +} + +function ModelHeadRowTwo({ + first_name, + last_name, + user_name, + user_score, + rate, + user_id +}: ProfileHeadRowTwoProps) { + + + const user = useUserById( user_id); + const is_verified = user?.is_verified; + return ( +
+
+ <> + {rate ? rate : "0"} + {"verify + +
+
+ <> + {user_score ? user_score : "0"} + {"verify + +
+
+

+ {first_name} {last_name} +

+
+ +

+ {user_name} + + {is_verified === "verified" ? ( + {"verify + ) : is_verified === "pending" ? ( + {"not-verify + ) : is_verified === "true" ? ( + verify icon + ) : ( + "" + )} +

+
+
+
+ ); +} + +export default ModelHeadRowTwo; diff --git a/src/components/models/ModelPage/ModelReportDiv.tsx b/src/components/models/ModelPage/ModelReportDiv.tsx new file mode 100644 index 0000000..ef09650 --- /dev/null +++ b/src/components/models/ModelPage/ModelReportDiv.tsx @@ -0,0 +1,34 @@ +"use client"; + +import ReportModal from "@/components/main/ReportModal"; +import Image from "next/image"; +import React, { useState } from "react"; + +function ModelReportDiv() { + const [showReportModal, setShowReportModal] = useState(false); + + return ( + <> + {showReportModal && ( + setShowReportModal(false)} + /> + )} + + + ); +} + +export default ModelReportDiv; diff --git a/src/components/models/ModelServiceModal.tsx b/src/components/models/ModelServiceModal.tsx new file mode 100644 index 0000000..a1eed0c --- /dev/null +++ b/src/components/models/ModelServiceModal.tsx @@ -0,0 +1,41 @@ +import React from "react"; +import Modal from "../elements/Modal"; +import { Service } from "@/types/types"; +import ServiceItem from "../main/Services/ServiceItem"; +import RoundedButton from "../elements/RoundedButton"; +import Link from "next/link"; + +type ModelModalProps = { + services: Service[] | undefined; + isOpen: true; + onClose: () => void; + userId: string; +}; + +function ModelServiceModal({ + isOpen, + userId, + onClose, + services, +}: ModelModalProps) { + return ( + +
+ لیست خدمات + {services + ?.filter((service) => service.status !== "UnderReview") + .map((service) => ( + + ))} + + + + ثبت درخواست + + +
+
+ ); +} + +export default ModelServiceModal; diff --git a/src/components/models/ModelsFilter.tsx b/src/components/models/ModelsFilter.tsx new file mode 100644 index 0000000..28c86fa --- /dev/null +++ b/src/components/models/ModelsFilter.tsx @@ -0,0 +1,146 @@ +"use client"; +import Image from "next/image"; +import { useRouter, usePathname } from "next/navigation"; // اضافه شدن usePathname برای تشخیص صفحه +import React, { useState } from "react"; +import FilterModal from "./FilterModal"; + +// وارد کردن دیتاها برای تبدیل ID به نام فارسی جهت ساخت URL +import provinces from "@/data/provinces.json"; +import cities from "@/data/cities.json"; + +const expertiseList = [ + { name: "مدل", color: "#B89FFF" }, + { name: "آرایشگر", color: "#23bace" }, + { name: "عکاس", color: "#dace63" }, +]; + +interface ModelsFilterProps { + expertise: string; +} + +function ModelsFilter({ expertise }: ModelsFilterProps) { + const router = useRouter(); + const pathname = usePathname(); // دریافت مسیر فعلی (مثلا /videos یا /) + const [showFilterModal, setShowFilterModal] = useState(false); + const [stateId, setStateId] = useState(""); + const [cityId, setCityId] = useState(""); + const [rateFilter, setRateFilter] = useState(""); + const [userLevel, setUserLevel] = useState(""); + + // تابع اصلی برای ساخت URL فارسی و سئو شده + const handleFilterChange = (filter?: string) => { + // ۱. تعیین تخصص + const currentExpertise = filter || expertise || ""; + const currentLevel = userLevel; + + // ۲. پیدا کردن نام فارسی استان و شهر بر اساس ID ها + const provinceObj = provinces.find(p => String(p.id) === String(stateId)); + const cityObj = cities.find(c => String(c.id) === String(cityId)); + + // ۳. تشخیص مسیر پایه و تعیین کلمه کلیدی (استخدام یا ویدئو ها) + const isVideoPage = pathname.startsWith("/videos"); + const basePath = isVideoPage ? "/videos" : ""; + const prefix = isVideoPage ? "ویدئو-ها-و-نمونه-کارهای" : "استخدام"; + + // ۴. جمله‌سازی برای بخش Slug آدرس + let slugParts = []; + + if (currentExpertise) { + slugParts.push(`${prefix}-${currentExpertise.replace(/\s+/g, '-')}`); + } else { + // اگر تخصصی انتخاب نشده بود، عبارت پیش‌فرض متناسب با صفحه + slugParts.push(isVideoPage ? "ویدئو-ها-متخصصین-مد-و-زیبایی" : "استخدام-متخصصین-مد-و-زیبایی"); + } + + if (currentLevel) { + slugParts.push(`سطح-${currentLevel.replace(/\s+/g, '-')}`); + } + + if (cityObj) { + slugParts.push(`در-شهر-${cityObj.name.replace(/\s+/g, '-')}`); + } else if (provinceObj) { + slugParts.push(`در-استان-${provinceObj.name.replace(/\s+/g, '-')}`); + } + + const finalSlug = slugParts.join("-"); + + // ۵. انتقال به URL جدید + // خروجی نهایی برای ویدئوها: /videos/ویدئو-ها-مدل-در-شهر-تهران + router.push(`${basePath}/${encodeURIComponent(finalSlug)}`); + }; + + const clearFilters = () => { + setStateId(""); + setCityId(""); + setRateFilter(""); + setUserLevel(""); + + const basePath = pathname.startsWith("/videos") ? "/videos" : "/"; + router.push(basePath); + }; + + return ( +
+
+
+ {expertiseList.map((item) => ( + + ))} +
+
+ + +
+
+ {showFilterModal && ( + handleFilterChange()} + clearFilters={clearFilters} + /> + )} +
+ ); +} + +export default ModelsFilter; \ No newline at end of file diff --git a/src/components/nav-documents.tsx b/src/components/nav-documents.tsx new file mode 100644 index 0000000..e9ca86e --- /dev/null +++ b/src/components/nav-documents.tsx @@ -0,0 +1,46 @@ +"use client" + +import { + + type Icon, +} from "@tabler/icons-react" + + +import { + SidebarGroup, + SidebarGroupLabel, + SidebarMenu, + + SidebarMenuButton, + SidebarMenuItem, +} from "@/components/ui/sidebar" + +export function NavDocuments({ + items, +}: { + items: { + name: string + url: string + icon: Icon + }[] +}) { + + + return ( + + Documents + + {items.map((item) => ( + + + + + {item.name} + + + + ))} + + + ) +} diff --git a/src/components/nav-main.tsx b/src/components/nav-main.tsx new file mode 100644 index 0000000..fa98ebd --- /dev/null +++ b/src/components/nav-main.tsx @@ -0,0 +1,45 @@ +"use client"; + +import { type Icon } from "@tabler/icons-react"; + + +import { + SidebarGroup, + SidebarGroupContent, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, +} from "@/components/ui/sidebar"; + +export function NavMain({ + items, +}: { + items: { + title: string; + url: string; + icon?: Icon; + }[]; +}) { + return ( + + + + + + + + {items.map((item) => ( + + + + {item.icon && } + {item.title} + + + + ))} + + + + ); +} diff --git a/src/components/nav-secondary.tsx b/src/components/nav-secondary.tsx new file mode 100644 index 0000000..3f3636f --- /dev/null +++ b/src/components/nav-secondary.tsx @@ -0,0 +1,42 @@ +"use client" + +import * as React from "react" +import { type Icon } from "@tabler/icons-react" + +import { + SidebarGroup, + SidebarGroupContent, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, +} from "@/components/ui/sidebar" + +export function NavSecondary({ + items, + ...props +}: { + items: { + title: string + url: string + icon: Icon + }[] +} & React.ComponentPropsWithoutRef) { + return ( + + + + {items.map((item) => ( + + + + + {item.title} + + + + ))} + + + + ) +} diff --git a/src/components/nav-user.tsx b/src/components/nav-user.tsx new file mode 100644 index 0000000..678fdb1 --- /dev/null +++ b/src/components/nav-user.tsx @@ -0,0 +1,76 @@ +"use client"; + +import { + IconCreditCard, + IconDotsVertical, + IconLogout, + IconNotification, + IconUserCircle, +} from "@tabler/icons-react"; + +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + useSidebar, +} from "@/components/ui/sidebar"; + +interface UserDataItem { + emailAddress: string; + avatar?: string; + name?: string; +} + +export function NavUser({ + user, +}: { + user: { + name: string; + emailAddress: string; + avatar: string; + data: UserDataItem; + }; +}) { + const { isMobile } = useSidebar(); + + const firstData = user.data; + + return ( + + + + + + + + AV + +
+ {user.name} + + {firstData?.emailAddress || user.emailAddress} + +
+
+
+
+
+
+ ); +} diff --git a/src/components/posts/PostFeedView.tsx b/src/components/posts/PostFeedView.tsx new file mode 100644 index 0000000..6d94211 --- /dev/null +++ b/src/components/posts/PostFeedView.tsx @@ -0,0 +1,134 @@ +"use client"; + +import React, { useEffect, useRef, useState } from "react"; +import { useRouter, useSearchParams } from "next/navigation"; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { fetchPosts } from "@/api/fetchPosts"; +import { fetchPostById } from "@/api/fetchPostById"; +import { Post } from "@/types/types"; +import MainModelCard from "@/components/models/MainModelCard/MainModelCard"; +import { MutedProvider } from "@/components/models/ModelPage/MainModelCardPost"; +import PageLoader from "@/components/ui/PageLoader"; +import { Skeleton } from "@/components/ui/skeleton"; +import Cookies from "js-cookie"; +import { FiX } from "react-icons/fi"; + +interface PostFeedViewProps { + initialPostId: string; + userId?: string; + showClose?: boolean; + videoOnly?: boolean; +} + +export default function PostFeedView({ + initialPostId, + userId: userIdProp, + showClose = true, + videoOnly = false, +}: PostFeedViewProps) { + const router = useRouter(); + const searchParams = useSearchParams(); + const userIdFromQuery = searchParams.get("userId") || ""; + const token = Cookies.get("token") || ""; + const scrollRef = useRef(null); + const scrolledRef = useRef(false); + + const [resolvedUserId, setResolvedUserId] = useState( + userIdProp || userIdFromQuery || "" + ); + + useEffect(() => { + if (userIdProp || userIdFromQuery) { + setResolvedUserId(userIdProp || userIdFromQuery); + return; + } + fetchPostById(initialPostId).then((post) => { + const uid = post?.userId || post?.user_id; + if (uid) setResolvedUserId(uid); + }); + }, [initialPostId, userIdProp, userIdFromQuery]); + + const { data, isLoading, isError } = useInfiniteQuery({ + queryKey: ["post-feed", resolvedUserId, initialPostId, videoOnly], + queryFn: ({ pageParam = 1 }) => + fetchPosts( + pageParam as number, + 20, + { + _id: resolvedUserId, + ...(videoOnly ? { type: "video" } : {}), + }, + token + ), + initialPageParam: 1, + getNextPageParam: (lastPage, pages) => + lastPage.posts?.length ? pages.length + 1 : undefined, + enabled: !!resolvedUserId || !!token, + }); + + const posts: Post[] = + data?.pages + ?.flatMap((p) => p.posts) + ?.filter( + (p) => + p.status === "accept" && (!videoOnly || p.type === "video") + ) ?? []; + + useEffect(() => { + if (scrolledRef.current || !posts.length || !scrollRef.current) return; + const idx = posts.findIndex((p) => p._id === initialPostId); + const targetIdx = idx >= 0 ? idx : 0; + scrollRef.current.scrollTo({ + top: targetIdx * window.innerHeight, + behavior: "auto", + }); + scrolledRef.current = true; + }, [posts, initialPostId]); + + if (!resolvedUserId && isLoading) { + return ( +
+ +
+ ); + } + + if (isError || posts.length === 0) { + return ( +

پست یافت نشد.

+ ); + } + + return ( + +
+ {showClose && ( + + )} +
+ {posts.map((post) => ( +
+
+ +
+
+ ))} +
+
+
+ ); +} diff --git a/src/components/posts/TagUsersPicker.tsx b/src/components/posts/TagUsersPicker.tsx new file mode 100644 index 0000000..5549c11 --- /dev/null +++ b/src/components/posts/TagUsersPicker.tsx @@ -0,0 +1,132 @@ +"use client"; + +import { useEffect, useState } from "react"; +import Image from "next/image"; +import useAxios from "@/hooks/useAxios"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import { FiUserPlus, FiX } from "react-icons/fi"; +import toast from "react-hot-toast"; + +export interface TaggedUser { + _id: string; + user_name: string; + first_name?: string; + last_name?: string; + profile_image?: string; +} + +interface TagUsersPickerProps { + selected: TaggedUser[]; + onChange: (users: TaggedUser[]) => void; + max?: number; +} + +export default function TagUsersPicker({ + selected, + onChange, + max = 50, +}: TagUsersPickerProps) { + const { request } = useAxios(); + const [open, setOpen] = useState(false); + const [query, setQuery] = useState(""); + const [results, setResults] = useState([]); + + useEffect(() => { + if (!open || query.length < 2) { + setResults([]); + return; + } + const t = setTimeout(async () => { + try { + const res = await request<{ users?: TaggedUser[]; data?: TaggedUser[] }>( + "GET", + `/search-web?q=${encodeURIComponent(query)}&limit=20`, + null, + { noToast: true } + ); + const list = res?.users || res?.data || []; + setResults(list.filter((u) => !selected.some((s) => s._id === u._id))); + } catch { + setResults([]); + } + }, 300); + return () => clearTimeout(t); + }, [query, open, request, selected]); + + const addUser = (u: TaggedUser) => { + if (selected.length >= max) { + toast.error(`حداکثر ${max} نفر`); + return; + } + onChange([...selected, u]); + setQuery(""); + }; + + const removeUser = (id: string) => { + onChange(selected.filter((u) => u._id !== id)); + }; + + return ( +
+ + + {selected.length > 0 && ( +
+ {selected.map((u) => ( + + @{u.user_name} + + + ))} +
+ )} + + {open && ( +
+ setQuery(e.target.value)} + placeholder="جستجوی نام کاربری…" + className="glass-chat-input w-full rounded-full px-3 py-2 text-sm outline-none" + /> +
    + {results.map((u) => ( +
  • + +
  • + ))} +
+
+ )} +
+ ); +} diff --git a/src/components/projects/FilterModal.tsx b/src/components/projects/FilterModal.tsx new file mode 100644 index 0000000..1bdbfec --- /dev/null +++ b/src/components/projects/FilterModal.tsx @@ -0,0 +1,110 @@ +import React from "react"; +import Modal from "../elements/Modal"; +import RoundedButton from "../elements/RoundedButton"; + +interface IFilterProps { + setShowFilterModal: (e: boolean) => void; + setFilterRequestsPrice: (e: string) => void; + setFilterAge: (e: string) => void; + setFilterGender: (e: string) => void; + handleFilterChange: (e?: string) => void; + clearFilters: () => void; + showFilterModal: boolean; + filterRequestsPrice: string; + filterAge: string; + filterGender: string; +} + +const FilterModal = ({ + setShowFilterModal, + showFilterModal, + setFilterRequestsPrice, + setFilterAge, + setFilterGender, + filterRequestsPrice, + filterAge, + filterGender, + handleFilterChange, + clearFilters, +}: IFilterProps) => { + return ( + setShowFilterModal(false)} + height="520px" + > +
+ مرتب سازی +
+ setFilterRequestsPrice("request")} + className={`w-full h-9 ${filterRequestsPrice === "request" ? "bg-[#23bace]" : ""}`} + > + بیشترین پیشنهاد + + setFilterRequestsPrice("price")} + className={`w-full h-9 ${filterRequestsPrice === "price" ? "bg-[#23bace]" : ""}`} + > + بیشترین بودجه + +
+ سن +
+ setFilterAge("all")} + className={`w-full h-9 ${filterAge === "all" ? "bg-[#23bace]" : ""}`} + > + بدون محدودیت + + setFilterAge("old")} + className={`w-full h-9 ${filterAge === "old" ? "bg-[#23bace]" : ""}`} + > + 25-30 + + setFilterAge("18-25")} + className={`w-full h-9 ${filterAge === "18-25" ? "bg-[#23bace]" : ""}`} + > + 18-25 + +
+ جنسیت +
+ setFilterGender("male")} + className={`w-full h-9 ${filterGender === "male" ? "bg-[#23bace]" : ""}`} + > + مرد + + setFilterGender("female")} + className={`w-full h-9 ${filterGender === "female" ? "bg-[#23bace]" : ""}`} + > + زن + +
+ + { + handleFilterChange(); + setShowFilterModal(false); + }} + className="border h-10 w-full rounded-full mt-5" + > + اعمال فیلتر + + + clearFilters()} + className="border h-10 w-full rounded-full mt-5" + > + پاک کردن + +
+
+ ); +}; + +export default FilterModal; diff --git a/src/components/projects/InfiniteProjects.tsx b/src/components/projects/InfiniteProjects.tsx new file mode 100644 index 0000000..65c7694 --- /dev/null +++ b/src/components/projects/InfiniteProjects.tsx @@ -0,0 +1,107 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; + +import { useInfiniteQuery } from "@tanstack/react-query"; +import React, { useEffect, useRef } from "react"; +import { fetchProjects } from "@/api/fetchProjects"; +import MainProjectCard from "./MainProjectCard"; +import { Project } from "@/types/types"; +import { useRouter } from "next/navigation"; + +interface InfiniteProjectsProps { + initialData: any; + token: string; + filters: { + expertise?: string; + most_requests?: string; + most_price?: string; + age?: string; + gender?: string; + }; +} + +export default function InfiniteProjects({ + initialData, + filters, + token, +}: InfiniteProjectsProps) { + const observerRef = useRef(null); + const router = useRouter(); + + // تبدیل فیلترها به رشته برای استفاده در queryKey + const filterString = JSON.stringify({ + expertise: filters.expertise || '', + most_requests: filters.most_requests || '', + most_price: filters.most_price || '', + age: filters.age || '', + gender: filters.gender || '' + }); + + const { + data, + fetchNextPage, + hasNextPage, + isFetchingNextPage, + refetch + } = useInfiniteQuery({ + queryKey: ['projects', filterString], + queryFn: ({ pageParam }) => fetchProjects(pageParam, 10, filters, token), + initialData: { + pages: [initialData], + pageParams: [1], + }, + initialPageParam: 1, + getNextPageParam: (lastPage, allPages) => + lastPage.totalItems > allPages.length * 10 ? allPages.length + 1 : undefined, + staleTime: 10000, // 10 ثانیه + }); + + // بازخوانی داده‌ها هنگام تغییر فیلترها + useEffect(() => { + refetch(); + }, [filterString, refetch]); + + useEffect(() => { + if (!observerRef.current || !hasNextPage) return; + + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting && hasNextPage && !isFetchingNextPage) { + fetchNextPage(); + } + }, + { + threshold: 0.3, + rootMargin: "100px", + } + ); + + const currentRef = observerRef.current; + if (currentRef) observer.observe(currentRef); + + return () => { + if (currentRef) observer.unobserve(currentRef); + }; + }, [hasNextPage, fetchNextPage, isFetchingNextPage]); + + return ( +
+
+ {data?.pages?.map((page, pageIndex) => + page?.projects?.map((item: Project) => ( +
router.push(`/projects/${item?._id}/${item?.title}`)} + className="cursor-pointer" + key={`${item._id}-${pageIndex}`} + > + +
+ )) + )} +
+
+ {isFetchingNextPage &&

در حال بارگذاری...

} +
+
+ ); +} \ No newline at end of file diff --git a/src/components/projects/MainProjectCard.tsx b/src/components/projects/MainProjectCard.tsx new file mode 100644 index 0000000..2183e51 --- /dev/null +++ b/src/components/projects/MainProjectCard.tsx @@ -0,0 +1,166 @@ +import { Project } from "@/types/types"; +import React from "react"; +import RoundedDiv from "../elements/RoundedDiv"; +import Image from "next/image"; +import Link from "next/link"; +import ProjectCreator from "./ProjectPage/ProjectCreator"; + +function MainProjectCard({ + project, + statusType, + color, + full, + borderColor, + textColor, + isSample, + sampleType, +}: { + project: Project; + statusType?: string; + color?: string; + borderColor?: string; + textColor?: string; + full?: boolean; + isSample?: boolean; + sampleType?: string; +}) { + console.log("sss"); + + return ( +
+ {project?.project_type === "force" && ( + + فوری + + )} + {isSample && sampleType == "force" && ( + + فوری + + )} + {statusType && ( + + {statusType} + + )} + +

+ {project?.title} +

+ +
+ {project?.expertise} + {project?.sub_expertise ? ( + <> + {" _ "} + {project?.sub_expertise.length !== 0 && + project?.sub_expertise.length > 1 ? ( + project?.sub_expertise.map((subItem, index) => ( + + {subItem} + {index !== project?.sub_expertise.length - 1 && " _ "} + + )) + ) : ( + {project?.sub_expertise} + )} + + ) : ( + "" + )} + {project?.gender && ( + {project?.gender == "male" ? " آقا" : " خانم"} + )} +
+ {full && } +

+ {project?.description} +

+
+
+ location icon + لوکیشن: شهر + {project?.city && project?.city?.name} +
+
+ clock icon + زمان پیشنهادی: + {project?.offer_time} روز +
+
+ timer icon + رده سنی: + {project?.age == "all" ? "همه" : project?.age} +
+
+ woman icon + جنسیت: + {project?.gender == "male" ? "آقا" : "خانم"} +
+
+
+ + بودجه: {Number(project?.offer_price).toLocaleString()} + + + تعداد پیشنهاد: {project?.requested_users?.length} + +
+
+ ); +} + +export default MainProjectCard; diff --git a/src/components/projects/NewProject/MultiStepForm.tsx b/src/components/projects/NewProject/MultiStepForm.tsx new file mode 100644 index 0000000..59b7b33 --- /dev/null +++ b/src/components/projects/NewProject/MultiStepForm.tsx @@ -0,0 +1,20 @@ +"use client"; + +import { useState } from "react"; +import Step1 from "./Step1"; +import Step2 from "./Step2"; +import Step3 from "./Step3"; + +const MultiStepForm = () => { + const [step, setStep] = useState(1); + + return ( +
+ {step === 1 && setStep(2)} />} + {step === 2 && setStep(3)} />} + {step === 3 && } +
+ ); +}; + +export default MultiStepForm; diff --git a/src/components/projects/NewProject/Step1.tsx b/src/components/projects/NewProject/Step1.tsx new file mode 100644 index 0000000..2cfb218 --- /dev/null +++ b/src/components/projects/NewProject/Step1.tsx @@ -0,0 +1,128 @@ +"use client"; + +import RoundedButton from "@/components/elements/RoundedButton"; +import { useProjectForm } from "@/contexts/ProjectFormContext"; +import useAxios from "@/hooks/useAxios"; +import { IExpertise } from "@/types/types"; +import { useFormik } from "formik"; +import { useEffect, useState } from "react"; +import * as Yup from "yup"; +import GenderSelection from "./step1/GenderSelection"; +import AgeSelection from "./step1/AgeSelection"; +import PublicTypeSelection from "./step1/PublicTypeSelection"; +import LocationSelector from "./step1/LocationSelector"; +import ExpertiseSelector from "./step1/ExpertiseSelector"; + +const validationSchema = Yup.object({ + cityId: Yup.string().required("انتخاب شهر الزامی است"), + stateId: Yup.string().required("انتخاب استان الزامی است"), + publicType: Yup.string().required("انتخاب روابط عمومی الزامی است"), + age: Yup.string().required("انتخاب محدوده سنی الزامی است"), + gender: Yup.string().required("انتخاب جنسیت الزامی است"), + expertise: Yup.string().required("انتخاب تخصص الزامی است"), + subExpertise: Yup.array() + .of(Yup.string().required("حداقل یک زیرمهارت را انتخاب کنید")) + .min(1, "حداقل یک زیرمهارت را انتخاب کنید"), +}); + +const Step1 = ({ nextStep }: { nextStep: () => void }) => { + const { formData, updateForm } = useProjectForm(); + const { request } = useAxios(); + const [expertiseList, setExpertiseList] = useState(null); + const [expertise, setExpertise] = useState(""); + const [subExpertise, setSubExpertise] = useState([]); + + useEffect(() => { + const fetchData = async () => { + try { + const response = await request<{ expertises: IExpertise[] }>( + "GET", + "/expertise" + ); + setExpertiseList(response?.expertises); + } catch (err) { + console.log(err); + } + }; + fetchData(); + }, []); + + const formik = useFormik({ + initialValues: { + cityId: formData.cityId || "", + stateId: formData.stateId || "", + publicType: formData.publicType || "", + expertise: formData.expertise || "", + gender: formData.gender || "", + age: formData.age || "", + subExpertise: formData.subExpertise || [], // آرایه‌ای از رشته‌ها + }, + validationSchema, + onSubmit: (values) => { + updateForm(values); + nextStep(); + }, + }); + + return ( + +
ثبت درخواست
+ + + {formik.touched.expertise && formik.errors.expertise && ( +

{formik.errors.expertise}

+ )} + {formik.touched.subExpertise && formik.errors.subExpertise && ( +

{formik.errors.subExpertise}

+ )} + +
+ formik.setFieldValue("gender", gender)} + setFieldValue={formik.setFieldValue} + /> + {formik.touched.gender && formik.errors.gender && ( +

{formik.errors.gender}

+ )} +
+ formik.setFieldValue("age", age)} + setFieldValue={formik.setFieldValue} + /> + {formik.touched.age && formik.errors.age && ( +

{formik.errors.age}

+ )} +
+ + formik.setFieldValue("publicType", type) + } + setFieldValue={formik.setFieldValue} + /> + {formik.touched.publicType && formik.errors.publicType && ( +

{formik.errors.publicType}

+ )} +
+ + + ثبت و ادامه + + + ); +}; + +export default Step1; diff --git a/src/components/projects/NewProject/Step2.tsx b/src/components/projects/NewProject/Step2.tsx new file mode 100644 index 0000000..b62453c --- /dev/null +++ b/src/components/projects/NewProject/Step2.tsx @@ -0,0 +1,174 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; + +import RoundedButton from "@/components/elements/RoundedButton"; +import { useProjectForm } from "@/contexts/ProjectFormContext"; +import { useFormik } from "formik"; +import * as Yup from "yup"; + +import RoundedInput from "@/components/elements/RoundedInput"; +import { useState } from "react"; +import Modal from "@/components/elements/Modal"; +import useAxios from "@/hooks/useAxios"; +import { useRouter } from "next/navigation"; + +const validationSchema = Yup.object({ + description: Yup.string().required(" وارد کردن توضیحات الزامی است"), + offerPrice: Yup.string().required(" وارد کردن بودجه الزامی است"), + projectTime: Yup.string().required(" وارد کردن زمان پیشنهادی الزامی است"), + projTitle: Yup.string().required(" عنوان پروژه الزامی است"), + numberOfPerson: Yup.string(), +}); + +const Step2 = ({ nextStep }: { nextStep: () => void }) => { + const { formData, updateForm, isEditing } = useProjectForm(); + const [showConfirmModal, setShowConfirmModal] = useState(false); + const { request } = useAxios(); + const router = useRouter(); + + const formik = useFormik({ + initialValues: { + description: formData.description || "", + offerPrice: formData.offerPrice || "", + projectTime: formData.projectTime || "", + projTitle: formData.projTitle || "", + numberOfPerson: formData.numberOfPerson || "", + }, + validationSchema, + onSubmit: async (values) => { + updateForm(values); + if (isEditing) { + try { + await request("POST", "/projects/edit", { + projectId: formData?._id, + title: values?.projTitle, + expertise: formData?.expertise, + sub_expertise: formData?.subExpertise, + gender: formData?.gender, + age: formData?.age, + conversation_projects: formData?.publicType, + province: formData?.stateId, + city: formData?.cityId, + offer_time: values?.projectTime, + offer_price: values?.offerPrice, + description: values?.description, + project_type: formData?.selectedType, + // created_for_user: formData?.userId, + public_status: formData?.userId ? "private" : "public", + number_of_person: + values?.numberOfPerson && values?.numberOfPerson.length !== 0 + ? values?.numberOfPerson + : 1, + }); + localStorage.removeItem("projectForm"); + router.push("/settings/workroom"); + } catch (err: any) { + console.log("Unhandled error:", err?.message); + } + } else { + updateForm(values); + } + setShowConfirmModal(true); + }, + }); + + return ( +
+
ثبت درخواست
+ + {formik.touched.projTitle && formik.errors.projTitle && ( +

{formik.errors.projTitle}

+ )} +
+ + (روز) +
+ + {formik.touched.projectTime && formik.errors.projectTime && ( +

{formik.errors.projectTime}

+ )} + + + {formik.touched.offerPrice && formik.errors.offerPrice && ( +

{formik.errors.offerPrice}

+ )} + + + {formik.touched.description && formik.errors.description && ( +

{formik.errors.description}

+ )} + + ثبت و ادامه + + {showConfirmModal && ( + setShowConfirmModal(false)} + height="280px" + > +
+

+ شما در هر روز فقط برای ۱ نفر می توانید درخواست رایگان ثبت کنید. + تعداد نفرات بیشتر از ۱ نفر مشمول هزینه می باشد. +

+ { + nextStep(); + }} + className="bg-sky-200 py-2 px-5 mt-5 rounded-xl min-w-[120px] text-sky-600 text-center" + > + تایید + +
+
+ )} + + ); +}; + +export default Step2; diff --git a/src/components/projects/NewProject/Step3.tsx b/src/components/projects/NewProject/Step3.tsx new file mode 100644 index 0000000..351c15a --- /dev/null +++ b/src/components/projects/NewProject/Step3.tsx @@ -0,0 +1,129 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; + +import RoundedButton from "@/components/elements/RoundedButton"; +import { useProjectForm } from "@/contexts/ProjectFormContext"; +import { useFormik } from "formik"; +import * as Yup from "yup"; + +import { useEffect, useState } from "react"; +import useAxios from "@/hooks/useAxios"; +import { IProjectType } from "@/types/types"; +import { sampleProject } from "@/constants"; +import MainProjectCard from "../MainProjectCard"; +import RoundedDiv from "@/components/elements/RoundedDiv"; +import { useRouter } from "next/navigation"; + +const validationSchema = Yup.object({ + selectedType: Yup.string().required(" انتخاب کردن نوع پروژه الزامی است"), +}); + +const Step3 = () => { + const router = useRouter(); + const { request } = useAxios(); + const { formData, updateForm } = useProjectForm(); + const [selectedType, setSelectedType] = useState("normal"); + + const [typeList, setTypeList] = useState(null); + const fetchStates = async () => { + try { + const response = await request<{ projectTypes: IProjectType[] }>( + "GET", + "/projects/types" + ); + setTypeList(response?.projectTypes || null); + } catch (err) { + console.log(err); + } + }; + useEffect(() => { + fetchStates(); + }, []); + + const formik = useFormik({ + initialValues: { + selectedType: formData.selectedType || "", + }, + validationSchema, + onSubmit: async (values) => { + updateForm(values); + try { + await request("POST", "/projects/create", { + title: formData?.projTitle, + expertise: formData?.expertise, + sub_expertise: formData?.subExpertise, + gender: formData?.gender, + age: formData?.age, + conversation_projects: formData?.publicType, + province: formData?.stateId, + city: formData?.cityId, + offer_time: formData?.projectTime, + offer_price: formData?.offerPrice, + description: formData?.description, + project_type: selectedType, + // created_for_user: formData?.userId, + public_status: formData?.userId ? "private" : "public", + number_of_person: + formData?.numberOfPerson && + formData?.numberOfPerson.length !== 0 && + Number(formData?.numberOfPerson) < 11 + ? formData?.numberOfPerson + : 1, + }); + localStorage.removeItem("projectForm"); + router.push("/settings/workroom"); + } catch (err: any) { + console.log("Unhandled error:", err?.message); + } + }, + }); + + return ( +
+
ثبت درخواست
+

نوع نمایش درخواست خود برای کاربران را مشخص کنید

+ {typeList?.map((item: IProjectType) => { + return ( +
{ + setSelectedType(item?.name); + formik.setFieldValue("selectedType", item?.name); + }} + className="w-full flex flex-col items-center" + key={item?._id} + > + + + {item?.name === "normal" + ? "نمایش ساده" + : item?.name === "free" + ? "نمایش ساده" + : item?.name === "force" + ? "نمایش با برچسب فوری" + : "نمایش با رنگ پس زمینه متفاوت"} + : + {item?.price !== 0 + ? Number(item?.price).toLocaleString() + "تومان" + : " رایگان"} + +
+ ); + })} + {formik.touched.selectedType && formik.errors.selectedType && ( +

{formik.errors.selectedType}

+ )} + + ثبت درخواست + +
+ ); +}; + +export default Step3; diff --git a/src/components/projects/NewProject/step1/AgeSelection.tsx b/src/components/projects/NewProject/step1/AgeSelection.tsx new file mode 100644 index 0000000..b99cf1f --- /dev/null +++ b/src/components/projects/NewProject/step1/AgeSelection.tsx @@ -0,0 +1,29 @@ +import RoundedButton from "@/components/elements/RoundedButton"; + +interface AgeSelectionProps { + selectedAge: string; + setSelectedAge: (age: string) => void; + setFieldValue: (field: string, value: string) => void; +} + +const AgeSelection = ({ selectedAge, setSelectedAge, setFieldValue }: AgeSelectionProps) => { + return ( +
+ {["18-25", "25-30", "all"].map((age) => ( + { + e.preventDefault(); + setSelectedAge(age); + setFieldValue("age", age); + }} + > + {age === "all" ? "بدون محدودیت" : `${age} سال`} + + ))} +
+ ); +}; + +export default AgeSelection; diff --git a/src/components/projects/NewProject/step1/ExpertiseSelector.tsx b/src/components/projects/NewProject/step1/ExpertiseSelector.tsx new file mode 100644 index 0000000..5a0f59c --- /dev/null +++ b/src/components/projects/NewProject/step1/ExpertiseSelector.tsx @@ -0,0 +1,85 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { IExpertise } from "@/types/types"; +import RoundedButton from "@/components/elements/RoundedButton"; +import { useEffect } from "react"; + +interface ExpertiseSelectorProps { + expertiseList: IExpertise[] | null; + expertise: string; + setExpertise: (expertise: string) => void; + subExpertise: string[]; + setSubExpertise: (subExpertise: string[]) => void; + setFieldValue: (field: string, value: string | string[]) => void; + formik: any; +} + +const ExpertiseSelector = ({ + expertiseList, + expertise, + setExpertise, + subExpertise, + setSubExpertise, + setFieldValue, + formik, +}: ExpertiseSelectorProps) => { + const handleButtonPress = (expertise: string) => { + setExpertise(expertise); + setSubExpertise([]); + setFieldValue("expertise", expertise); + setFieldValue("subExpertise", []); + }; + + const handleSubButtonPress = (sub_expertise: string) => { + const updatedSubExpertise = subExpertise.includes(sub_expertise) + ? subExpertise.filter((item) => item !== sub_expertise) + : [...subExpertise, sub_expertise]; + setSubExpertise(updatedSubExpertise); + setFieldValue("subExpertise", updatedSubExpertise); + }; + + useEffect(() => { + setExpertise(formik?.values?.expertise || ""); + setSubExpertise(formik?.values?.subExpertise || []); + }, [formik?.values?.expertise]); + console.log(formik?.values); + + return ( +
+ {expertiseList?.map((item) => ( + handleButtonPress(item.expertise)} + type="button" + > + {item.expertise} + + ))} + + {expertiseList + ?.find((item) => item.expertise === expertise) + ?.sub_expertise.map((item) => ( + { + handleSubButtonPress(item.name); + }} + type="button" + > + {item.name} + + ))} +
+ ); +}; + +export default ExpertiseSelector; diff --git a/src/components/projects/NewProject/step1/GenderSelection.tsx b/src/components/projects/NewProject/step1/GenderSelection.tsx new file mode 100644 index 0000000..f55d65f --- /dev/null +++ b/src/components/projects/NewProject/step1/GenderSelection.tsx @@ -0,0 +1,47 @@ +import RoundedButton from "@/components/elements/RoundedButton"; +import Image from "next/image"; + +interface GenderSelectionProps { + selectedGender: string; + setSelectedGender: (gender: string) => void; + setFieldValue: (field: string, value: string) => void; +} + +const GenderSelection = ({ + selectedGender, + setSelectedGender, + setFieldValue, +}: GenderSelectionProps) => { + return ( +
+ { + e.preventDefault(); + setSelectedGender("male"); + setFieldValue("gender", "male"); + }} + > + آقا + gender icon + + { + e.preventDefault(); + setSelectedGender("female"); + setFieldValue("gender", "female"); + }} + > + خانم + gender icon + +
+ ); +}; + +export default GenderSelection; diff --git a/src/components/projects/NewProject/step1/LocationSelector.tsx b/src/components/projects/NewProject/step1/LocationSelector.tsx new file mode 100644 index 0000000..c78d541 --- /dev/null +++ b/src/components/projects/NewProject/step1/LocationSelector.tsx @@ -0,0 +1,109 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { ICity, IProvince } from "@/types/types"; +import SelectBox from "@/components/elements/SelectBox"; +import { useState, useEffect } from "react"; +import useAxios from "@/hooks/useAxios"; + +interface LocationSelectorProps { + formik: any; +} + +const LocationSelector: React.FC = ({ formik }) => { + const { request } = useAxios(); + const [allStates, setAllStates] = useState(null); + const [cities, setCities] = useState(null); + + const fetchStates = async () => { + try { + const response = await request<{ provinces: IProvince[] }>( + "GET", + "/provinces" + ); + setAllStates(response?.provinces || null); + } catch (err) { + console.log(err); + } + }; + + const fetchCities = async (provinceId: string) => { + try { + const response = await request<{ cities: ICity[] }>( + "GET", + `/cities/${provinceId}` + ); + setCities(response?.cities || []); + } catch (err) { + console.log(err); + } + }; + + useEffect(() => { + fetchStates(); + }, []); + + useEffect(() => { + if (formik.values.stateId) { + fetchCities(formik.values.stateId); + } + }, [formik?.values?.stateId]); + + const handleProvinceChange = (e: React.ChangeEvent) => { + const selectedProvinceId = e.target.value; + formik.setFieldValue("stateId", selectedProvinceId); + fetchCities(selectedProvinceId); // Fetch cities for the selected province + }; + + return ( + <> + + + {allStates?.map((item: IProvince) => ( + + ))} + + {formik.touched.stateId && formik.errors.stateId && ( + + {formik.errors.stateId} + + )} + + formik.setFieldValue("cityId", e.target.value)} + > + + {cities?.map((city: ICity) => ( + + ))} + + {formik.touched.cityId && formik.errors.cityId && ( + + {formik.errors.cityId} + + )} + + ); +}; + +export default LocationSelector; diff --git a/src/components/projects/NewProject/step1/PublicTypeSelection.tsx b/src/components/projects/NewProject/step1/PublicTypeSelection.tsx new file mode 100644 index 0000000..2bfd18a --- /dev/null +++ b/src/components/projects/NewProject/step1/PublicTypeSelection.tsx @@ -0,0 +1,35 @@ +import RoundedButton from "@/components/elements/RoundedButton"; + +interface PublicTypeSelectionProps { + selectedPublicType: string; + setSelectedPublicType: (type: string) => void; + setFieldValue: (field: string, value: string) => void; +} + +const PublicTypeSelection = ({ + selectedPublicType, + setSelectedPublicType, + setFieldValue, +}: PublicTypeSelectionProps) => { + return ( +
+ {["true", "false"].map((type) => ( + { + e.preventDefault(); + setSelectedPublicType(type); + setFieldValue("publicType", type); + }} + > + {type === "true" ? "روابط عمومی بالا" : "بدون محدودیت"} + + ))} +
+ ); +}; + +export default PublicTypeSelection; diff --git a/src/components/projects/ProjectPage/ProjectCreator.tsx b/src/components/projects/ProjectPage/ProjectCreator.tsx new file mode 100644 index 0000000..9729182 --- /dev/null +++ b/src/components/projects/ProjectPage/ProjectCreator.tsx @@ -0,0 +1,58 @@ +import { IProjectCreator } from "@/types/types"; +import React from "react"; +import Image from "next/image"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; +import Link from "next/link"; + +function ProjectCreator({ creator }: { creator: IProjectCreator }) { + return ( + + {creator?.profile_image && ( + {creator?.user_name} + )} +
+ + {creator?.user_type && creator?.user_type == "employer" + ? "کارفرما" + : "مدل"} + + + {creator?.first_name && + creator?.first_name + " " + creator?.last_name} + +
+ {creator?.user_name} + {creator?.is_verified === "verified" ? ( + {"verify + ) : creator?.is_verified === "pending" ? ( + {"not-verify + ) : ( + "" + )} +
+
+ + ); +} + +export default ProjectCreator; diff --git a/src/components/projects/ProjectPage/ProjectRequestForm.tsx b/src/components/projects/ProjectPage/ProjectRequestForm.tsx new file mode 100644 index 0000000..8c02f32 --- /dev/null +++ b/src/components/projects/ProjectPage/ProjectRequestForm.tsx @@ -0,0 +1,102 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use client"; +import * as yup from "yup"; +import { useFormik } from "formik"; + +import RoundedInput from "@/components/elements/RoundedInput"; +import React, { useEffect, useState } from "react"; +import useAxios from "@/hooks/useAxios"; +import RoundedButton from "@/components/elements/RoundedButton"; +import { useRouter } from "next/navigation"; + +// Validation schema using Yup +const schema = yup.object().shape({ + offerPrice: yup.string().required(" وارد کردن مبلغ پیشنهادی الزامی است"), + projectTime: yup.string().required(" وارد کردن زمان پیشنهادی الزامی است"), +}); + +function ProjectRequestForm({ projectId }: { projectId: string }) { + const router = useRouter(); + const { request } = useAxios(); + const [usertype, setUsertype] = useState(null); + + useEffect(() => { + if (typeof window !== "undefined") { + setUsertype(localStorage.getItem("usertype")); + } + }, []); + const formik = useFormik({ + initialValues: { + offerPrice: "", + projectTime: "", + }, + validationSchema: schema, + onSubmit: async (values) => { + try { + await request("POST", "/projects/request", { + project_id: projectId, + request_time: values.projectTime, + offer_price: values.offerPrice, + }); + router.push("/settings/workroom"); + } catch (err: any) { + console.log("Unhandled error:", err?.message); + } + }, + }); + + return ( +
+ {usertype == "user" ? ( + <> + + {formik.touched.projectTime && formik.errors.projectTime && ( + + {formik.errors.projectTime} + + )} + + {formik.touched.offerPrice && formik.errors.offerPrice && ( + + {formik.errors.offerPrice} + + )} + + ارسال + + + ) : ( + "" + )} + + ); +} + +export default ProjectRequestForm; diff --git a/src/components/projects/ProjectPage/ProjectRequests.tsx b/src/components/projects/ProjectPage/ProjectRequests.tsx new file mode 100644 index 0000000..291b9bf --- /dev/null +++ b/src/components/projects/ProjectPage/ProjectRequests.tsx @@ -0,0 +1,35 @@ +import UserInfo from "@/components/main/UserInfo"; +import { IProjectRequest } from "@/types/types"; +import Link from "next/link"; +import React from "react"; + +function ProjectRequests({ + projectRequests, +}: { + projectRequests: IProjectRequest[]; +}) { + return ( + <> + {projectRequests + ? projectRequests.map((item: IProjectRequest) => { + return ( + +
+ +
+ + ); + }) + : ""} + + ); +} + +export default ProjectRequests; diff --git a/src/components/projects/ProjectsFilter.tsx b/src/components/projects/ProjectsFilter.tsx new file mode 100644 index 0000000..1017e00 --- /dev/null +++ b/src/components/projects/ProjectsFilter.tsx @@ -0,0 +1,132 @@ +"use client"; +import Image from "next/image"; +import { useRouter, useSearchParams } from "next/navigation"; +import React, { useEffect, useState } from "react"; +import FilterModal from "./FilterModal"; + +const expertiseList = [ + { name: "مدلینگ", color: "#B89FFF" }, + { name: "زیبایی", color: "#23bace" }, + { name: "عکاسی", color: "#dace63" }, +]; + +interface ProjectsFilterProps { + expertise: string; +} + +function ProjectsFilter({ expertise }: ProjectsFilterProps) { + const router = useRouter(); + const searchParams = useSearchParams(); + const [showFilterModal, setShowFilterModal] = useState(false); + const [filterRequestsPrice, setFilterRequestsPrice] = useState(""); + const [filterAge, setFilterAge] = useState(""); + const [filterGender, setFilterGender] = useState(""); + + // مقداردهی اولیه از URL + useEffect(() => { + setFilterRequestsPrice( + searchParams.get("most_requests") + ? "request" + : searchParams.get("most_price") + ? "price" + : "" + ); + setFilterAge(searchParams.get("age") || ""); + setFilterGender(searchParams.get("gender") || ""); + }, [searchParams]); + + const handleFilterChange = (filter?: string) => { + const currentQuery = new URLSearchParams(window.location.search); + + if (filter) { + currentQuery.set("expertise", filter); + } + + // فقط یکی از `most_requests` یا `most_price` در URL بماند + currentQuery.delete("most_requests"); + currentQuery.delete("most_price"); + + if (filterRequestsPrice) { + currentQuery.set( + filterRequestsPrice === "request" ? "most_requests" : "most_price", + "true" + ); + } + + if (filterAge) currentQuery.set("age", filterAge); + if (filterGender) currentQuery.set("gender", filterGender); + + router.push(`/projects?${currentQuery.toString()}`); + }; + + const clearFilters = () => { + setFilterRequestsPrice(""); + setFilterAge(""); + setFilterGender(""); + + const currentQuery = new URLSearchParams(window.location.search); + currentQuery.delete("most_requests"); + currentQuery.delete("most_price"); + currentQuery.delete("age"); + currentQuery.delete("gender"); + + router.push(`/projects?${currentQuery.toString()}`); + }; + + return ( +
+
+
+ {expertiseList.map((item) => ( + + ))} +
+
+ + +
+
+ {showFilterModal && ( + + )} +
+ ); +} + +export default ProjectsFilter; diff --git a/src/components/projects/Workroom/ProjectRequestsAction.tsx b/src/components/projects/Workroom/ProjectRequestsAction.tsx new file mode 100644 index 0000000..121622b --- /dev/null +++ b/src/components/projects/Workroom/ProjectRequestsAction.tsx @@ -0,0 +1,147 @@ +"use client"; + +import Modal from "@/components/elements/Modal"; +import RoundedButton from "@/components/elements/RoundedButton"; +import RoundedDiv from "@/components/elements/RoundedDiv"; +import UserInfo from "@/components/main/UserInfo"; +import useAxios from "@/hooks/useAxios"; +import { IProjectRequest } from "@/types/types"; +import Image from "next/image"; +import { useRouter } from "next/navigation"; +import React, { useState } from "react"; + +function ProjectRequestsAction({ + projectRequests, + projectId, + status, +}: { + projectRequests: IProjectRequest[]; + projectId: string; + status: string; +}) { + const { request } = useAxios(); + const router = useRouter(); + const [showConfirmModal, setShowConfirmModal] = useState(false); + const [itemToAccept, setItemToAccept] = useState(); + const acceptHandler = async () => { + try { + await request<{ type?: string }>( + "POST", + "/projects/payment-request-step-one/web", + { + requestId: itemToAccept?._id, // Pass advertisingId to initiate payment + projectId, + } + ); + router.refresh(); + } catch (error: unknown) { + console.log(error); + } + }; + return ( + <> + {projectRequests + ? projectRequests.map((item: IProjectRequest) => { + return ( +
{ + if (status == "accepted") { + setItemToAccept(item); + setShowConfirmModal(true); + } + }} + > + + +
+ + مبلغ پیشنهادی: {Number(item?.price).toLocaleString()} تومان + + زمان پیشنهادی: {item?.time} روز +
+
+ <> + + {item?.user?.user_score + ? item?.user?.user_score + : "0"} + + {"verify + +
+
+ <> + {item?.user?.rate ? item?.user?.rate : "0"} + {"verify + +
+
+
+
+ ); + }) + : ""} + {showConfirmModal && ( + setShowConfirmModal(false)} + height="430px" + > + {itemToAccept && ( +
+ + + مبلغ پیشنهادی: {Number(itemToAccept?.price).toLocaleString()}{" "} + تومان + + + زمان پیشنهادی: {itemToAccept?.time} روز + + { + acceptHandler(); + setShowConfirmModal(false); + }} + className="w-full p-2 mt-5 text-sm text-[#0C8002] !border-[#0C8002]" + > + می پذیرم + +
+ )} +
+ )} + + ); +} + +export default ProjectRequestsAction; diff --git a/src/components/projects/Workroom/ProjectWorkroomActions.tsx b/src/components/projects/Workroom/ProjectWorkroomActions.tsx new file mode 100644 index 0000000..c292c98 --- /dev/null +++ b/src/components/projects/Workroom/ProjectWorkroomActions.tsx @@ -0,0 +1,79 @@ +"use client"; + +import RoundedButton from "@/components/elements/RoundedButton"; +import useAxios from "@/hooks/useAxios"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import React from "react"; +import ProjectWorkroomRate from "./ProjectWorkroomRate"; +import { SelectedUser } from "@/types/types"; + +function ProjectWorkroomActions({ + projectId, + type, + status, + selected_user, +}: { + projectId: string; + type: string; + status: string; + selected_user: string | null | SelectedUser; +}) { + const router = useRouter(); + const { request } = useAxios(); + + const payHandler = async () => { + try { + const response = await request<{ authority?: string; type?: string }>( + "POST", + "/projects/initiate-payment-web", + { + item_name: type, + projectId: projectId, + } + ); + if (response.type === "free") { + router.push("/settings/workroom"); + } else { + const authority = response.authority; // Get the payment authority + const paymentUrl = `https://www.zarinpal.com/pg/StartPay/${authority}`; // Construct payment URL + router.push(paymentUrl); + } + } catch (error: unknown) { + console.log(error); + } + }; + + return ( +
+
+ {(status == "pre_payment" || status == "paid") && ( + + + ویرایش + + + )} + {status == "ongoing" && selected_user && ( + + )} + {status == "pre_payment" && ( + + پرداخت + + )} +
+
+ ); +} + +export default ProjectWorkroomActions; diff --git a/src/components/projects/Workroom/ProjectWorkroomRate.tsx b/src/components/projects/Workroom/ProjectWorkroomRate.tsx new file mode 100644 index 0000000..9acd904 --- /dev/null +++ b/src/components/projects/Workroom/ProjectWorkroomRate.tsx @@ -0,0 +1,97 @@ +"use client"; + +import React, { useState } from "react"; +import Rate from "rc-rate"; +import "rc-rate/assets/index.css"; +import useAxios from "@/hooks/useAxios"; +import RoundedButton from "@/components/elements/RoundedButton"; +import toast from "react-hot-toast"; +import { useRouter } from "next/navigation"; +import { SelectedUser } from "@/types/types"; + +function ProjectWorkroomRate({ + projectId, + selected_user, +}: { + projectId: string; + selected_user: string | SelectedUser; +}) { + const { request } = useAxios(); + const router = useRouter(); + const [rating, setRating] = useState(0); + const [commentText, setCommentText] = useState(""); + const doneHandler = async () => { + if (!commentText) { + toast.error("ثبت نظر الزامی است."); + return; + } + if (!rating) { + toast.error("ثبت امتیاز الزامی است."); + return; + } + try { + await request("POST", "/projects/done/web", { + project_id: projectId, + comment: commentText, + rate: rating, + user_id: selected_user, + }); + router.push("/settings/workroom"); + } catch (error: unknown) { + console.log(error); + } + }; + const cancleHandler = async () => { + if (!commentText) { + toast.error("ثبت نظر الزامی است."); + return; + } + if (!rating) { + toast.error("ثبت امتیاز الزامی است."); + return; + } + try { + await request("POST", "/projects/cancle", { + project_id: projectId, + comment: commentText, + rate: rating, + user_id: selected_user, + }); + router.push("/settings/workroom"); + } catch (error: unknown) { + console.log(error); + } + }; + return ( +
+ + + ); +}; + +export default AddressFields; diff --git a/src/components/settings/my-billboards/Profile/AvatarUploader.tsx b/src/components/settings/my-billboards/Profile/AvatarUploader.tsx new file mode 100644 index 0000000..0ebc8fd --- /dev/null +++ b/src/components/settings/my-billboards/Profile/AvatarUploader.tsx @@ -0,0 +1,69 @@ +// components/AvatarUploader.tsx +import React from "react"; +import Image from "next/image"; +import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; + +interface AvatarUploaderProps { + avatar: string | null; + onSelectImage: (event: React.ChangeEvent) => void; + onRemoveImage: () => void; +} + +const AvatarUploader: React.FC = ({ + avatar, + onSelectImage, + onRemoveImage, +}) => { + return ( +
+ لوگو +
+ {avatar ? ( + <> + Avatar + + + ) : ( + + )} +
+ +
+ ); +}; + +export default AvatarUploader; diff --git a/src/components/settings/my-billboards/Profile/ContactInfoFields.tsx b/src/components/settings/my-billboards/Profile/ContactInfoFields.tsx new file mode 100644 index 0000000..cc45b27 --- /dev/null +++ b/src/components/settings/my-billboards/Profile/ContactInfoFields.tsx @@ -0,0 +1,50 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// components/ContactInfoFields.tsx +import React from "react"; +import RoundedInput from "@/components/elements/RoundedInput"; + +interface ContactInfoFieldsProps { + formik: any; +} + +const ContactInfoFields: React.FC = ({ formik }) => { + return ( + <> + + + + + + + ); +}; + +export default ContactInfoFields; diff --git a/src/components/settings/my-billboards/Profile/ProfileBasicFields.tsx b/src/components/settings/my-billboards/Profile/ProfileBasicFields.tsx new file mode 100644 index 0000000..62c1f9c --- /dev/null +++ b/src/components/settings/my-billboards/Profile/ProfileBasicFields.tsx @@ -0,0 +1,50 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// components/ProfileBasicFields.tsx +import React from "react"; +import RoundedInput from "@/components/elements/RoundedInput"; +import SelectBox from "@/components/elements/SelectBox"; +import { IAdvertisingCategory } from "@/types/types"; + +interface ProfileBasicFieldsProps { + formik: any; + categories: IAdvertisingCategory[]; +} + +const ProfileBasicFields: React.FC = ({ + formik, + categories, +}) => { + return ( + <> + + + formik.setFieldValue("categoryId", e.target.value) + } + > + + {categories.map((item: IAdvertisingCategory) => ( + + ))} + + + + ); +}; + +export default ProfileBasicFields; diff --git a/src/components/settings/offers/CommentModal.tsx b/src/components/settings/offers/CommentModal.tsx new file mode 100644 index 0000000..027939f --- /dev/null +++ b/src/components/settings/offers/CommentModal.tsx @@ -0,0 +1,63 @@ +import React, { useState } from "react"; +import Rate from "rc-rate"; +import "rc-rate/assets/index.css"; +import Modal from "@/components/elements/Modal"; +import useAxios from "@/hooks/useAxios"; +import { IOffers } from "@/types/types"; +import RoundedButton from "@/components/elements/RoundedButton"; +import toast from "react-hot-toast"; + +type CommentModalProps = { + isOpen: boolean; + onClose: () => void; + item: IOffers | null; +}; + +function CommentModal({ isOpen, onClose, item }: CommentModalProps) { + const { request } = useAxios(); + const [rating, setRating] = useState(0); + const [commentText, setCommentText] = useState(""); + const submitComment = async () => { + if (!commentText) { + toast.error("متن نظر الزامی است."); + return; + } + if (!rating) { + toast.error("امتیاز الزامی است."); + return; + } + try { + await request("POST", "/offers/comment", { + offerId: item ? item?._id : "", + comment: commentText, + rate: rating, + user_id: item ? item?.receiver?._id : "", + }); + } catch (error: unknown) { + console.log(error); + } + }; + return ( + +
+ ثبت نظر + setRating(value)} + count={5} + style={{ fontSize: "28px" }} + /> +