diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..7580753
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,21 @@
+version: 2
+updates:
+ - package-ecosystem: npm
+ directory: /backend
+ schedule:
+ interval: weekly
+
+ - package-ecosystem: npm
+ directory: /frontend
+ schedule:
+ interval: weekly
+
+ - package-ecosystem: npm
+ directory: /mobile
+ schedule:
+ interval: weekly
+
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: weekly
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 580ac7e..f8d49c9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,29 +7,50 @@ on:
branches: [main]
jobs:
- build:
+ backend:
runs-on: ubuntu-latest
-
defaults:
run:
working-directory: backend
steps:
- - name: Checkout code
- uses: actions/checkout@v3
+ - uses: actions/checkout@v3
- - name: Setup Node.js
- uses: actions/setup-node@v3
+ - uses: actions/setup-node@v3
with:
node-version: 18
- cache: 'npm'
+ cache: npm
cache-dependency-path: backend/package-lock.json
- name: Install dependencies
run: npm ci
- - name: Syntax Check
- run: node --check server.js
+ - name: Lint
+ run: npm run lint
+
+ - name: Run tests
+ run: npm test
- name: Build Docker image
- run: docker build -t zappify-backend .
\ No newline at end of file
+ run: docker build -t zappify-backend .
+
+ frontend:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: frontend
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ cache: npm
+ cache-dependency-path: frontend/package-lock.json
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Lint
+ run: npm run lint
diff --git a/README.md b/README.md
index 5b4704f..6c3f86e 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Built with a modern MERN stack on the backend and React + React Native on the fr
## Live Demo
- **Website:** [zappify-sepia.vercel.app](https://zappify-sepia.vercel.app)
-- **Phone Preview:** [zappify-sepia.vercel.app/preview](https://zappify-sepia.vercel.app/preview)
+- **Download APK:** https://expo.dev/accounts/devendra.mi/projects/zappify/builds/24237286-1ff7-4219-ac7a-6c103ff28d00
---
@@ -37,6 +37,7 @@ Built with a modern MERN stack on the backend and React + React Native on the fr



+
### Infrastructure

@@ -50,12 +51,12 @@ Built with a modern MERN stack on the backend and React + React Native on the fr
```
+-------------------------------------------------------------------+
| |
-| +-------------+ +-------------+ +-------------+ |
-| | Front-end | | Back-end | | Database | |
-| | ReactJS |<---->| NodeJS |<---->| MongoDB | |
-| |UI Components| | ExpressJS | | Collections | |
-| | API calls | |API endpoints| | Documents | |
-| +-------------+ +-------------+ +-------------+ |
+| +-------------+ +-------------+ +-------------+ |
+| | Front-end | | Back-end | | Database | |
+| | ReactJS |<---->| NodeJS |<---->| MongoDB | |
+| |UI Components| | ExpressJS | | Collections | |
+| | API calls | |API endpoints| | Documents | |
+| +-------------+ +-------------+ +-------------+ |
| |
+-------------------------------------------------------------------+
```
@@ -101,6 +102,17 @@ Orders {
---
+## Payment Testing
+
+Razorpay is integrated in test mode. Use these credentials to test payments:
+
+| Method | Details |
+|---|---|
+| Card | 5267 3181 8797 5449 / Expiry: 08/26 / CVV: 123 / OTP: 1234 |
+| UPI | success@razorpay |
+
+---
+
## What This Project Does
Zappify is built as a real-world e-commerce application that covers the complete shopping journey:
@@ -112,7 +124,6 @@ Zappify is built as a real-world e-commerce application that covers the complete
- Goes through a 3-step checkout (Bag → Address → Payment)
- Tracks their order with a live timeline
- Can cancel an order with a reason
-- All of this works on both web and Android mobile app
---
@@ -127,13 +138,15 @@ Zappify is built as a real-world e-commerce application that covers the complete
- Add to cart with size validation
- Wishlist toggle on product cards and detail page
- 3-step checkout - Bag to Address to Payment (COD / UPI / Card)
+- Razorpay payment gateway integration (UPI, Card, Netbanking, Wallet)
+- Payment signature verification on backend
- Order history with tracking timeline
- Order cancellation with reason selection form
- Google OAuth 2.0 login
- Normal email/password sign up and sign in
- User-specific order history per account
-- Persistent login via localStorage / AsyncStorage
-- Full Android mobile app via Expo + EAS Build
+- Persistent login via localStorage
+- Progressive Web App (PWA) ready
### For Admins
- Secure JWT-protected API routes
@@ -168,6 +181,8 @@ PORT=5001
MONGO_URI=your_mongodb_uri
JWT_SECRET=your_secret_key
NODE_ENV=development
+RAZORPAY_KEY_ID=your_razorpay_key_id
+RAZORPAY_KEY_SECRET=your_razorpay_key_secret
```
```bash
@@ -203,7 +218,6 @@ Zappify/
│ ├── components/
│ ├── data/products.js
│ ├── App.jsx
-│ ├── Preview.jsx
│ ├── main.jsx
│ └── index.css
├── mobile/
@@ -234,6 +248,18 @@ Zappify/
| GET | /api/products | Get all products | No |
| GET | /api/products/:id | Get product by ID | No |
| POST | /api/products | Create product | Admin |
+| POST | /api/payment/create-order | Create Razorpay order | No |
+| POST | /api/payment/verify | Verify payment signature | No |
+
+---
+
+## Frontend Environment Variables
+
+Create `frontend/.env`:
+```env
+VITE_API_URL=http://localhost:5001
+VITE_RAZORPAY_KEY_ID=your_razorpay_key_id
+```
---
diff --git a/backend/.env.example b/backend/.env.example
index df39aa3..a23d76a 100644
--- a/backend/.env.example
+++ b/backend/.env.example
@@ -2,3 +2,5 @@ PORT=5001
MONGO_URI=your_mongodb_atlas_uri_here
JWT_SECRET=your_super_secret_key_here
NODE_ENV=development
+RAZORPAY_KEY_ID=rzp_test_xxxxxxxxxxxxxx
+RAZORPAY_KEY_SECRET=your_key_secret_here
diff --git a/backend/config/db.js b/backend/config/db.js
index d2b4f99..e9607fa 100644
--- a/backend/config/db.js
+++ b/backend/config/db.js
@@ -1,14 +1,11 @@
const mongoose = require('mongoose');
-const dotenv = require('dotenv');
-
-dotenv.config();
const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI);
- console.log(`Connection established with MongoDB: ${conn.connection.host}`);
+ console.log(`Connected to MongoDB: ${conn.connection.host}`);
} catch (error) {
- console.error(`Something went wrong: ${error.message}`);
+ console.error(`DB Error: ${error.message}`);
process.exit(1);
}
};
diff --git a/backend/controllers/userController.js b/backend/controllers/userController.js
index c2febf0..2098f52 100644
--- a/backend/controllers/userController.js
+++ b/backend/controllers/userController.js
@@ -1,5 +1,6 @@
const jwt = require('jsonwebtoken');
const User = require('../models/User');
+const { validateEmail } = require('../utils/validate');
const generateToken = (id) => {
return jwt.sign({ id }, process.env.JWT_SECRET, {
@@ -28,7 +29,7 @@ const authUser = async (req, res) => {
const registerUser = async (req, res) => {
const { name, email, password } = req.body;
- if (!email.includes('@') || !email.includes('.')) {
+ if (!validateEmail(email)) {
return res.status(400).json({ message: 'Please enter a valid email' });
}
diff --git a/backend/eslint.config.js b/backend/eslint.config.js
new file mode 100644
index 0000000..383ff5e
--- /dev/null
+++ b/backend/eslint.config.js
@@ -0,0 +1,11 @@
+const js = require('@eslint/js');
+
+module.exports = [
+ js.configs.recommended,
+ {
+ rules: {
+ 'no-unused-vars': 'warn',
+ 'no-console': 'off',
+ },
+ },
+];
diff --git a/backend/middlewares/authMiddleware.js b/backend/middlewares/authMiddleware.js
index 599456f..84cc397 100644
--- a/backend/middlewares/authMiddleware.js
+++ b/backend/middlewares/authMiddleware.js
@@ -12,7 +12,6 @@ const protect = async (req, res, next) => {
req.user = await User.findById(decoded.id).select('-password');
next();
} catch (error) {
- console.error(error);
res.status(401).json({ message: 'Token failed, not authorized' });
}
}
diff --git a/backend/package-lock.json b/backend/package-lock.json
index 2f421bb..918c93e 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -16,317 +16,2636 @@
"helmet": "^8.1.0",
"jsonwebtoken": "^9.0.3",
"mongoose": "^9.3.3",
- "morgan": "^1.10.1"
+ "morgan": "^1.10.1",
+ "razorpay": "^2.9.6"
},
"devDependencies": {
- "nodemon": "^3.1.14"
+ "eslint": "^10.2.0",
+ "jest": "^30.3.0",
+ "nodemon": "^3.1.14",
+ "supertest": "^7.2.2"
}
},
- "node_modules/@mongodb-js/saslprep": {
- "version": "1.4.6",
- "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.6.tgz",
- "integrity": "sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==",
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "sparse-bitfield": "^3.0.3"
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "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==",
- "license": "MIT"
- },
- "node_modules/@types/whatwg-url": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz",
- "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==",
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "@types/webidl-conversions": "*"
+ "engines": {
+ "node": ">=6.9.0"
}
},
- "node_modules/accepts": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
- "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "node_modules/@babel/core": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
- "mime-types": "^3.0.0",
- "negotiator": "^1.0.0"
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@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": ">= 0.6"
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
}
},
- "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==",
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
+ "bin": {
+ "semver": "bin/semver.js"
}
},
- "node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "node_modules/@babel/generator": {
+ "version": "7.29.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
"engines": {
- "node": "18 || 20 || >=22"
+ "node": ">=6.9.0"
}
},
- "node_modules/basic-auth": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
- "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "safe-buffer": "5.1.2"
+ "@babel/compat-data": "^7.28.6",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
},
"engines": {
- "node": ">= 0.8"
+ "node": ">=6.9.0"
}
},
- "node_modules/basic-auth/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/bcryptjs": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz",
- "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==",
- "license": "BSD-3-Clause",
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
"bin": {
- "bcrypt": "bin/bcrypt"
+ "semver": "bin/semver.js"
}
},
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "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==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=6.9.0"
}
},
- "node_modules/body-parser": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
- "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "bytes": "^3.1.2",
- "content-type": "^1.0.5",
- "debug": "^4.4.3",
- "http-errors": "^2.0.0",
- "iconv-lite": "^0.7.0",
- "on-finished": "^2.4.1",
- "qs": "^6.14.1",
- "raw-body": "^3.0.1",
- "type-is": "^2.0.1"
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
},
"engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "node": ">=6.9.0"
}
},
- "node_modules/brace-expansion": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
- "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "balanced-match": "^4.0.2"
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.6"
},
"engines": {
- "node": "18 || 20 || >=22"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
"engines": {
- "node": ">=8"
+ "node": ">=6.9.0"
}
},
- "node_modules/bson": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz",
- "integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==",
- "license": "Apache-2.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==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=20.19.0"
+ "node": ">=6.9.0"
}
},
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
- "license": "BSD-3-Clause"
+ "node_modules/@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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
},
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "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==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.8"
+ "node": ">=6.9.0"
}
},
- "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==",
+ "node_modules/@babel/helpers": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
+ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": ">=6.9.0"
}
},
- "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==",
+ "node_modules/@babel/parser": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
+ "@babel/types": "^7.29.0"
},
- "engines": {
- "node": ">= 0.4"
+ "bin": {
+ "parser": "bin/babel-parser.js"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": ">=6.0.0"
}
},
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "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/"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
- "optionalDependencies": {
- "fsevents": "~2.3.2"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/content-disposition": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
- "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
"license": "MIT",
- "engines": {
- "node": ">=18"
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "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==",
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 0.6"
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
"engines": {
- "node": ">= 0.6"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/cookie-signature": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
- "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
+ "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
"engines": {
- "node": ">=6.6.0"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/cors": {
- "version": "2.8.6",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
- "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "object-assign": "^4",
- "vary": "^1"
+ "@babel/helper-plugin-utils": "^7.10.4"
},
- "engines": {
- "node": ">= 0.10"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
+ "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
- "node": ">=6.0"
+ "node": ">=6.9.0"
},
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/depd": {
- "version": "2.0.0",
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
+ "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "dev": true,
+ "license": "MIT",
+ "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==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz",
+ "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.1",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz",
+ "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
+ "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.23.4",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.4.tgz",
+ "integrity": "sha512-lf19F24LSMfF8weXvW5QEtnLqW70u7kgit5e9PSx0MsHAFclGd1T9ynvWEMDT1w5J4Qt54tomGeAhdoAku1Xow==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^3.0.4",
+ "debug": "^4.3.1",
+ "minimatch": "^10.2.4"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.4.tgz",
+ "integrity": "sha512-jJhqiY3wPMlWWO3370M86CPJ7pt8GmEwSLglMfQhjXal07RCvhmU0as4IuUEW5SJeunfItiEetHmSxCCe9lDBg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^1.2.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.0.tgz",
+ "integrity": "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.4.tgz",
+ "integrity": "sha512-55lO/7+Yp0ISKRP0PsPtNTeNGapXaO085aELZmWCVc5SH3jfrqpuU6YgOdIxMS99ZHkQN1cXKE+cdIqwww9ptw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.0.tgz",
+ "integrity": "sha512-ejvBr8MQCbVsWNZnCwDXjUKq40MDmHalq7cJ6e9s/qzTUFIIo/afzt1Vui9T97FM/V/pN4YsFVoed5NIa96RDg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^1.2.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.3.0.tgz",
+ "integrity": "sha512-PAwCvFJ4696XP2qZj+LAn1BWjZaJ6RjG6c7/lkMaUJnkyMS34ucuIsfqYvfskVNvUI27R/u4P1HMYFnlVXG/Ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "jest-message-util": "30.3.0",
+ "jest-util": "30.3.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.3.0.tgz",
+ "integrity": "sha512-U5mVPsBxLSO6xYbf+tgkymLx+iAhvZX43/xI1+ej2ZOPnPdkdO1CzDmFKh2mZBn2s4XZixszHeQnzp1gm/DIxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "30.3.0",
+ "@jest/pattern": "30.0.1",
+ "@jest/reporters": "30.3.0",
+ "@jest/test-result": "30.3.0",
+ "@jest/transform": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "ansi-escapes": "^4.3.2",
+ "chalk": "^4.1.2",
+ "ci-info": "^4.2.0",
+ "exit-x": "^0.2.2",
+ "graceful-fs": "^4.2.11",
+ "jest-changed-files": "30.3.0",
+ "jest-config": "30.3.0",
+ "jest-haste-map": "30.3.0",
+ "jest-message-util": "30.3.0",
+ "jest-regex-util": "30.0.1",
+ "jest-resolve": "30.3.0",
+ "jest-resolve-dependencies": "30.3.0",
+ "jest-runner": "30.3.0",
+ "jest-runtime": "30.3.0",
+ "jest-snapshot": "30.3.0",
+ "jest-util": "30.3.0",
+ "jest-validate": "30.3.0",
+ "jest-watcher": "30.3.0",
+ "pretty-format": "30.3.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/diff-sequences": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.3.0.tgz",
+ "integrity": "sha512-cG51MVnLq1ecVUaQ3fr6YuuAOitHK1S4WUJHnsPFE/quQr33ADUx1FfrTCpMCRxvy0Yr9BThKpDjSlcTi91tMA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.3.0.tgz",
+ "integrity": "sha512-SlLSF4Be735yQXyh2+mctBOzNDx5s5uLv88/j8Qn1wH679PDcwy67+YdADn8NJnGjzlXtN62asGH/T4vWOkfaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/fake-timers": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "jest-mock": "30.3.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.3.0.tgz",
+ "integrity": "sha512-76Nlh4xJxk2D/9URCn3wFi98d2hb19uWE1idLsTt2ywhvdOldbw3S570hBgn25P4ICUZ/cBjybrBex2g17IDbg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "30.3.0",
+ "jest-snapshot": "30.3.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.3.0.tgz",
+ "integrity": "sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/get-type": "30.1.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.3.0.tgz",
+ "integrity": "sha512-WUQDs8SOP9URStX1DzhD425CqbN/HxUYCTwVrT8sTVBfMvFqYt/s61EK5T05qnHu0po6RitXIvP9otZxYDzTGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "30.3.0",
+ "@sinonjs/fake-timers": "^15.0.0",
+ "@types/node": "*",
+ "jest-message-util": "30.3.0",
+ "jest-mock": "30.3.0",
+ "jest-util": "30.3.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/get-type": {
+ "version": "30.1.0",
+ "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz",
+ "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.3.0.tgz",
+ "integrity": "sha512-+owLCBBdfpgL3HU+BD5etr1SvbXpSitJK0is1kiYjJxAAJggYMRQz5hSdd5pq1sSggfxPbw2ld71pt4x5wwViA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "30.3.0",
+ "@jest/expect": "30.3.0",
+ "@jest/types": "30.3.0",
+ "jest-mock": "30.3.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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==",
+ "dev": true,
+ "license": "MIT",
+ "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": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.3.0.tgz",
+ "integrity": "sha512-a09z89S+PkQnL055bVj8+pe2Caed2PBOaczHcXCykW5ngxX9EWx/1uAwncxc/HiU0oZqfwseMjyhxgRjS49qPw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "30.3.0",
+ "@jest/test-result": "30.3.0",
+ "@jest/transform": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "collect-v8-coverage": "^1.0.2",
+ "exit-x": "^0.2.2",
+ "glob": "^10.5.0",
+ "graceful-fs": "^4.2.11",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^5.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "30.3.0",
+ "jest-util": "30.3.0",
+ "jest-worker": "30.3.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.2",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "30.0.5",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
+ "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.34.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/snapshot-utils": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.3.0.tgz",
+ "integrity": "sha512-ORbRN9sf5PP82v3FXNSwmO1OTDR2vzR2YTaR+E3VkSBZ8zadQE6IqYdYEeFH1NIkeB2HIGdF02dapb6K0Mj05g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "30.3.0",
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "natural-compare": "^1.4.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "30.0.1",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz",
+ "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "callsites": "^3.1.0",
+ "graceful-fs": "^4.2.11"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.3.0.tgz",
+ "integrity": "sha512-e/52nJGuD74AKTSe0P4y5wFRlaXP0qmrS17rqOMHeSwm278VyNyXE3gFO/4DTGF9w+65ra3lo3VKj0LBrzmgdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/istanbul-lib-coverage": "^2.0.6",
+ "collect-v8-coverage": "^1.0.2"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.3.0.tgz",
+ "integrity": "sha512-dgbWy9b8QDlQeRZcv7LNF+/jFiiYHTKho1xirauZ7kVwY7avjFF6uTT0RqlgudB5OuIPagFdVtfFMosjVbk1eA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "30.3.0",
+ "graceful-fs": "^4.2.11",
+ "jest-haste-map": "30.3.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.3.0.tgz",
+ "integrity": "sha512-TLKY33fSLVd/lKB2YI1pH69ijyUblO/BQvCj566YvnwuzoTNr648iE0j22vRvVNk2HsPwByPxATg3MleS3gf5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.27.4",
+ "@jest/types": "30.3.0",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "babel-plugin-istanbul": "^7.0.1",
+ "chalk": "^4.1.2",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.11",
+ "jest-haste-map": "30.3.0",
+ "jest-regex-util": "30.0.1",
+ "jest-util": "30.3.0",
+ "pirates": "^4.0.7",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^5.0.1"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.3.0.tgz",
+ "integrity": "sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==",
+ "dev": true,
+ "license": "MIT",
+ "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/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@mongodb-js/saslprep": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.6.tgz",
+ "integrity": "sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==",
+ "license": "MIT",
+ "dependencies": {
+ "sparse-bitfield": "^3.0.3"
+ }
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "0.2.12",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
+ "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@tybys/wasm-util": "^0.10.0"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@paralleldrive/cuid2": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
+ "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@noble/hashes": "^1.1.5"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@pkgr/core": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
+ "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/pkgr"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.34.49",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.49.tgz",
+ "integrity": "sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.3.0.tgz",
+ "integrity": "sha512-m2xozxSfCIxjDdvbhIWazlP2i2aha/iUmbl94alpsIbd3iLTfeXgfBVbwyWogB6l++istyGZqamgA/EcqYf+Bg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.1"
+ }
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
+ "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/esrecurse": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
+ "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
+ "dev": true,
+ "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,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "25.5.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz",
+ "integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.18.0"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/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==",
+ "license": "MIT"
+ },
+ "node_modules/@types/whatwg-url": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz",
+ "integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/webidl-conversions": "*"
+ }
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
+ "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@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==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@unrs/resolver-binding-android-arm-eabi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
+ "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-android-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
+ "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
+ "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
+ "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
+ "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
+ "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
+ "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
+ "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
+ "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
+ "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
+ "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
+ "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
+ "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
+ "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
+ "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
+ "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^0.2.11"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
+ "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
+ "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
+ "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": 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,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
+ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/axios": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz",
+ "integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.11",
+ "form-data": "^4.0.5",
+ "proxy-from-env": "^2.1.0"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.3.0.tgz",
+ "integrity": "sha512-gRpauEU2KRrCox5Z296aeVHR4jQ98BCnu0IO332D/xpHNOsIH/bgSRk9k6GbKIbBw8vFeN6ctuu6tV8WOyVfYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "30.3.0",
+ "@types/babel__core": "^7.20.5",
+ "babel-plugin-istanbul": "^7.0.1",
+ "babel-preset-jest": "30.3.0",
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.11.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz",
+ "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "workspaces": [
+ "test/babel-8"
+ ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-instrument": "^6.0.2",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.3.0.tgz",
+ "integrity": "sha512-+TRkByhsws6sfPjVaitzadk1I0F5sPvOVUH5tyTSzhePpsGIVrdeunHSw/C36QeocS95OOk8lunc4rlu5Anwsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/babel__core": "^7.20.5"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
+ "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.3.0.tgz",
+ "integrity": "sha512-6ZcUbWHC+dMz2vfzdNwi87Z1gQsLNK2uLuK1Q89R11xdvejcivlYYwDlEv0FHX3VwEXpbBQ9uufB/MUNpZGfhQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "30.3.0",
+ "babel-preset-current-node-syntax": "^1.2.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.11.0 || ^8.0.0-beta.1"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.15",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.15.tgz",
+ "integrity": "sha512-1nfKCq9wuAZFTkA2ey/3OXXx7GzFjLdkTiFVNwlJ9WqdI706CZRIhEqjuwanjMIja+84jDLa9rcyZDPDiVkASQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/basic-auth": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/basic-auth/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/bcryptjs": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz",
+ "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==",
+ "license": "BSD-3-Clause",
+ "bin": {
+ "bcrypt": "bin/bcrypt"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
+ "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^1.0.5",
+ "debug": "^4.4.3",
+ "http-errors": "^2.0.0",
+ "iconv-lite": "^0.7.0",
+ "on-finished": "^2.4.1",
+ "qs": "^6.14.1",
+ "raw-body": "^3.0.1",
+ "type-is": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "peer": true,
+ "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/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/bson": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-7.2.0.tgz",
+ "integrity": "sha512-YCEo7KjMlbNlyHhz7zAZNDpIpQbd+wOEHJYezv0nMYTn4x31eIUM2yomNNubclAt63dObUzKHWsBLJ9QcZNSnQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=20.19.0"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001785",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001785.tgz",
+ "integrity": "sha512-blhOL/WNR+Km1RI/LCVAvA73xplXA7ZbjzI4YkMK9pa6T/P3F2GxjNpEkyw5repTw9IvkyrjyHpwjnhZ5FOvYQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/chalk/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz",
+ "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz",
+ "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
+ "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/component-emitter": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
+ "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/content-disposition": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
+ "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
+ "node_modules/cookiejar": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
+ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cors": {
+ "version": "2.8.6",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz",
+ "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz",
+ "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/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",
@@ -334,435 +2653,2014 @@
"node": ">= 0.8"
}
},
- "node_modules/dotenv": {
- "version": "17.3.1",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
- "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
- "license": "BSD-2-Clause",
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dezalgo": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
+ "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "asap": "^2.0.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "17.3.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
+ "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.331",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.331.tgz",
+ "integrity": "sha512-IbxXrsTlD3hRodkLnbxAPP4OuJYdWCeM3IOdT+CpcMoIwIoDfCmRpEtSPfwBXxVkg9xmBeY7Lz2Eo2TDn/HC3Q==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.0.tgz",
+ "integrity": "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.2",
+ "@eslint/config-array": "^0.23.4",
+ "@eslint/config-helpers": "^0.5.4",
+ "@eslint/core": "^1.2.0",
+ "@eslint/plugin-kit": "^0.7.0",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^9.1.2",
+ "eslint-visitor-keys": "^5.0.1",
+ "espree": "^11.2.0",
+ "esquery": "^1.7.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",
+ "minimatch": "^10.2.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
+ "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@types/esrecurse": "^4.3.1",
+ "@types/estree": "^1.0.8",
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
+ "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.16.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^5.0.1"
+ },
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/execa/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/exit-x": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz",
+ "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-30.3.0.tgz",
+ "integrity": "sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/expect-utils": "30.3.0",
+ "@jest/get-type": "30.1.0",
+ "jest-matcher-utils": "30.3.0",
+ "jest-message-util": "30.3.0",
+ "jest-mock": "30.3.0",
+ "jest-util": "30.3.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.1",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "finalhandler": "^2.1.0",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "merge-descriptors": "^2.0.0",
+ "mime-types": "^3.0.0",
+ "on-finished": "^2.4.1",
+ "once": "^1.4.0",
+ "parseurl": "^1.3.3",
+ "proxy-addr": "^2.0.7",
+ "qs": "^6.14.0",
+ "range-parser": "^1.2.1",
+ "router": "^2.2.0",
+ "send": "^1.1.0",
+ "serve-static": "^2.2.0",
+ "statuses": "^2.0.1",
+ "type-is": "^2.0.1",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "on-finished": "^2.4.1",
+ "parseurl": "^1.3.3",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
+ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.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"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "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/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/formidable": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz",
+ "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@paralleldrive/cuid2": "^2.2.2",
+ "dezalgo": "^1.0.4",
+ "once": "^1.4.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "url": "https://ko-fi.com/tunnckoCore/commissions"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/glob/node_modules/brace-expansion": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz",
+ "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.9",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
+ "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/helmet": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz",
+ "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+ "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "license": "MIT"
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-report/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
+ "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.23",
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
+ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jest": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-30.3.0.tgz",
+ "integrity": "sha512-AkXIIFcaazymvey2i/+F94XRnM6TsVLZDhBMLsd1Sf/W0wzsvvpjeyUrCZD6HGG4SDYPgDJDBKeiJTBb10WzMg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "30.3.0",
+ "@jest/types": "30.3.0",
+ "import-local": "^3.2.0",
+ "jest-cli": "30.3.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
"engines": {
- "node": ">=12"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
},
- "funding": {
- "url": "https://dotenvx.com"
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
- "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==",
+ "node_modules/jest-changed-files": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.3.0.tgz",
+ "integrity": "sha512-B/7Cny6cV5At6M25EWDgf9S617lHivamL8vl6KEpJqkStauzcG4e+WPfDgMMF+H4FVH4A2PLRyvgDJan4441QA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
+ "execa": "^5.1.1",
+ "jest-util": "30.3.0",
+ "p-limit": "^3.1.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "license": "Apache-2.0",
+ "node_modules/jest-circus": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.3.0.tgz",
+ "integrity": "sha512-PyXq5szeSfR/4f1lYqCmmQjh0vqDkURUYi9N6whnHjlRz4IUQfMcXkGLeEoiJtxtyPqgUaUUfyQlApXWBSN1RA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "safe-buffer": "^5.0.1"
+ "@jest/environment": "30.3.0",
+ "@jest/expect": "30.3.0",
+ "@jest/test-result": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "co": "^4.6.0",
+ "dedent": "^1.6.0",
+ "is-generator-fn": "^2.1.0",
+ "jest-each": "30.3.0",
+ "jest-matcher-utils": "30.3.0",
+ "jest-message-util": "30.3.0",
+ "jest-runtime": "30.3.0",
+ "jest-snapshot": "30.3.0",
+ "jest-util": "30.3.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "30.3.0",
+ "pure-rand": "^7.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.6"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
- },
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "node_modules/jest-cli": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.3.0.tgz",
+ "integrity": "sha512-l6Tqx+j1fDXJEW5bqYykDQQ7mQg+9mhWXtnj+tQZrTWYHyHoi6Be8HPumDSA+UiX2/2buEgjA58iJzdj146uCw==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/core": "30.3.0",
+ "@jest/test-result": "30.3.0",
+ "@jest/types": "30.3.0",
+ "chalk": "^4.1.2",
+ "exit-x": "^0.2.2",
+ "import-local": "^3.2.0",
+ "jest-config": "30.3.0",
+ "jest-util": "30.3.0",
+ "jest-validate": "30.3.0",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
"engines": {
- "node": ">= 0.8"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
- "node_modules/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==",
+ "node_modules/jest-config": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.3.0.tgz",
+ "integrity": "sha512-WPMAkMAtNDY9P/oKObtsRG/6KTrhtgPJoBTmk20uDn4Uy6/3EJnnaZJre/FMT1KVRx8cve1r7/FlMIOfRVWL4w==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.27.4",
+ "@jest/get-type": "30.1.0",
+ "@jest/pattern": "30.0.1",
+ "@jest/test-sequencer": "30.3.0",
+ "@jest/types": "30.3.0",
+ "babel-jest": "30.3.0",
+ "chalk": "^4.1.2",
+ "ci-info": "^4.2.0",
+ "deepmerge": "^4.3.1",
+ "glob": "^10.5.0",
+ "graceful-fs": "^4.2.11",
+ "jest-circus": "30.3.0",
+ "jest-docblock": "30.2.0",
+ "jest-environment-node": "30.3.0",
+ "jest-regex-util": "30.0.1",
+ "jest-resolve": "30.3.0",
+ "jest-runner": "30.3.0",
+ "jest-util": "30.3.0",
+ "jest-validate": "30.3.0",
+ "parse-json": "^5.2.0",
+ "pretty-format": "30.3.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
"engines": {
- "node": ">= 0.4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "esbuild-register": ">=3.4.0",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "esbuild-register": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
}
},
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "node_modules/jest-diff": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.3.0.tgz",
+ "integrity": "sha512-n3q4PDQjS4LrKxfWB3Z5KNk1XjXtZTBwQp71OP0Jo03Z6V60x++K5L8k6ZrW8MY8pOFylZvHM0zsjS1RqlHJZQ==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/diff-sequences": "30.3.0",
+ "@jest/get-type": "30.1.0",
+ "chalk": "^4.1.2",
+ "pretty-format": "30.3.0"
+ },
"engines": {
- "node": ">= 0.4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "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==",
+ "node_modules/jest-docblock": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.2.0.tgz",
+ "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "es-errors": "^1.3.0"
+ "detect-newline": "^3.1.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "license": "MIT"
+ "node_modules/jest-each": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.3.0.tgz",
+ "integrity": "sha512-V8eMndg/aZ+3LnCJgSm13IxS5XSBM22QSZc9BtPK8Dek6pm+hfUNfwBdvsB3d342bo1q7wnSkC38zjX259qZNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/get-type": "30.1.0",
+ "@jest/types": "30.3.0",
+ "chalk": "^4.1.2",
+ "jest-util": "30.3.0",
+ "pretty-format": "30.3.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
},
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "node_modules/jest-environment-node": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.3.0.tgz",
+ "integrity": "sha512-4i6HItw/JSiJVsC5q0hnKIe/hbYfZLVG9YJ/0pU9Hz2n/9qZe3Rhn5s5CUZA5ORZlcdT/vmAXRMyONXJwPrmYQ==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/environment": "30.3.0",
+ "@jest/fake-timers": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "jest-mock": "30.3.0",
+ "jest-util": "30.3.0",
+ "jest-validate": "30.3.0"
+ },
"engines": {
- "node": ">= 0.6"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/express": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
- "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "node_modules/jest-haste-map": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.3.0.tgz",
+ "integrity": "sha512-mMi2oqG4KRU0R9QEtscl87JzMXfUhbKaFqOxmjb2CKcbHcUGFrJCBWHmnTiUqi6JcnzoBlO4rWfpdl2k/RfLCA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "accepts": "^2.0.0",
- "body-parser": "^2.2.1",
- "content-disposition": "^1.0.0",
- "content-type": "^1.0.5",
- "cookie": "^0.7.1",
- "cookie-signature": "^1.2.1",
- "debug": "^4.4.0",
- "depd": "^2.0.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "finalhandler": "^2.1.0",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.0",
- "merge-descriptors": "^2.0.0",
- "mime-types": "^3.0.0",
- "on-finished": "^2.4.1",
- "once": "^1.4.0",
- "parseurl": "^1.3.3",
- "proxy-addr": "^2.0.7",
- "qs": "^6.14.0",
- "range-parser": "^1.2.1",
- "router": "^2.2.0",
- "send": "^1.1.0",
- "serve-static": "^2.2.0",
- "statuses": "^2.0.1",
- "type-is": "^2.0.1",
- "vary": "^1.1.2"
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "anymatch": "^3.1.3",
+ "fb-watchman": "^2.0.2",
+ "graceful-fs": "^4.2.11",
+ "jest-regex-util": "30.0.1",
+ "jest-util": "30.3.0",
+ "jest-worker": "30.3.0",
+ "picomatch": "^4.0.3",
+ "walker": "^1.0.8"
},
"engines": {
- "node": ">= 18"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.3"
+ }
+ },
+ "node_modules/jest-haste-map/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
},
"funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "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==",
+ "node_modules/jest-leak-detector": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.3.0.tgz",
+ "integrity": "sha512-cuKmUUGIjfXZAiGJ7TbEMx0bcqNdPPI6P1V+7aF+m/FUJqFDxkFR4JqkTu8ZOiU5AaX/x0hZ20KaaIPXQzbMGQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "to-regex-range": "^5.0.1"
+ "@jest/get-type": "30.1.0",
+ "pretty-format": "30.3.0"
},
"engines": {
- "node": ">=8"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/finalhandler": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
- "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "node_modules/jest-matcher-utils": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.3.0.tgz",
+ "integrity": "sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "debug": "^4.4.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "on-finished": "^2.4.1",
- "parseurl": "^1.3.3",
- "statuses": "^2.0.1"
+ "@jest/get-type": "30.1.0",
+ "chalk": "^4.1.2",
+ "jest-diff": "30.3.0",
+ "pretty-format": "30.3.0"
},
"engines": {
- "node": ">= 18.0.0"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.3.0.tgz",
+ "integrity": "sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@jest/types": "30.3.0",
+ "@types/stack-utils": "^2.0.3",
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "picomatch": "^4.0.3",
+ "pretty-format": "30.3.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.6"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "node_modules/jest-message-util/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.6"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
- "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "node_modules/jest-mock": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.3.0.tgz",
+ "integrity": "sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "jest-util": "30.3.0"
+ },
"engines": {
- "node": ">= 0.8"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
"dev": true,
- "hasInstallScript": true,
"license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
"engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
}
},
- "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==",
+ "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==",
+ "dev": true,
"license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "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==",
+ "node_modules/jest-resolve": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.3.0.tgz",
+ "integrity": "sha512-NRtTAHQlpd15F9rUR36jqwelbrDV/dY4vzNte3S2kxCKUJRYNd5/6nTSbYiak1VX5g8IoFF23Uj5TURkUW8O5g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "jest-haste-map": "30.3.0",
+ "jest-pnp-resolver": "^1.2.3",
+ "jest-util": "30.3.0",
+ "jest-validate": "30.3.0",
+ "slash": "^3.0.0",
+ "unrs-resolver": "^1.7.11"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.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==",
+ "node_modules/jest-resolve-dependencies": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.3.0.tgz",
+ "integrity": "sha512-9ev8s3YN6Hsyz9LV75XUwkCVFlwPbaFn6Wp75qnI0wzAINYWY8Fb3+6y59Rwd3QaS3kKXffHXsZMziMavfz/nw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
+ "jest-regex-util": "30.0.1",
+ "jest-snapshot": "30.3.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "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==",
+ "node_modules/jest-runner": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.3.0.tgz",
+ "integrity": "sha512-gDv6C9LGKWDPLia9TSzZwf4h3kMQCqyTpq+95PODnTRDO0g9os48XIYYkS6D236vjpBir2fF63YmJFtqkS5Duw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "30.3.0",
+ "@jest/environment": "30.3.0",
+ "@jest/test-result": "30.3.0",
+ "@jest/transform": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "emittery": "^0.13.1",
+ "exit-x": "^0.2.2",
+ "graceful-fs": "^4.2.11",
+ "jest-docblock": "30.2.0",
+ "jest-environment-node": "30.3.0",
+ "jest-haste-map": "30.3.0",
+ "jest-leak-detector": "30.3.0",
+ "jest-message-util": "30.3.0",
+ "jest-resolve": "30.3.0",
+ "jest-runtime": "30.3.0",
+ "jest-util": "30.3.0",
+ "jest-watcher": "30.3.0",
+ "jest-worker": "30.3.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.3.0.tgz",
+ "integrity": "sha512-CgC+hIBJbuh78HEffkhNKcbXAytQViplcl8xupqeIWyKQF50kCQA8J7GeJCkjisC6hpnC9Muf8jV5RdtdFbGng==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"dependencies": {
- "is-glob": "^4.0.1"
+ "@jest/environment": "30.3.0",
+ "@jest/fake-timers": "30.3.0",
+ "@jest/globals": "30.3.0",
+ "@jest/source-map": "30.0.1",
+ "@jest/test-result": "30.3.0",
+ "@jest/transform": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "cjs-module-lexer": "^2.1.0",
+ "collect-v8-coverage": "^1.0.2",
+ "glob": "^10.5.0",
+ "graceful-fs": "^4.2.11",
+ "jest-haste-map": "30.3.0",
+ "jest-message-util": "30.3.0",
+ "jest-mock": "30.3.0",
+ "jest-regex-util": "30.0.1",
+ "jest-resolve": "30.3.0",
+ "jest-snapshot": "30.3.0",
+ "jest-util": "30.3.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
},
"engines": {
- "node": ">= 6"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "node_modules/jest-snapshot": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.3.0.tgz",
+ "integrity": "sha512-f14c7atpb4O2DeNhwcvS810Y63wEn8O1HqK/luJ4F6M4NjvxmAKQwBUWjbExUtMxWJQ0wVgmCKymeJK6NZMnfQ==",
+ "dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 0.4"
+ "dependencies": {
+ "@babel/core": "^7.27.4",
+ "@babel/generator": "^7.27.5",
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "@babel/plugin-syntax-typescript": "^7.27.1",
+ "@babel/types": "^7.27.3",
+ "@jest/expect-utils": "30.3.0",
+ "@jest/get-type": "30.1.0",
+ "@jest/snapshot-utils": "30.3.0",
+ "@jest/transform": "30.3.0",
+ "@jest/types": "30.3.0",
+ "babel-preset-current-node-syntax": "^1.2.0",
+ "chalk": "^4.1.2",
+ "expect": "30.3.0",
+ "graceful-fs": "^4.2.11",
+ "jest-diff": "30.3.0",
+ "jest-matcher-utils": "30.3.0",
+ "jest-message-util": "30.3.0",
+ "jest-util": "30.3.0",
+ "pretty-format": "30.3.0",
+ "semver": "^7.7.2",
+ "synckit": "^0.11.8"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "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==",
+ "node_modules/jest-util": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.3.0.tgz",
+ "integrity": "sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "ci-info": "^4.2.0",
+ "graceful-fs": "^4.2.11",
+ "picomatch": "^4.0.3"
+ },
"engines": {
- "node": ">=4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "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==",
+ "node_modules/jest-util/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">= 0.4"
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "node_modules/jest-validate": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.3.0.tgz",
+ "integrity": "sha512-I/xzC8h5G+SHCb2P2gWkJYrNiTbeL47KvKeW5EzplkyxzBRBw1ssSHlI/jXec0ukH2q7x2zAWQm7015iusg62Q==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "function-bind": "^1.1.2"
+ "@jest/get-type": "30.1.0",
+ "@jest/types": "30.3.0",
+ "camelcase": "^6.3.0",
+ "chalk": "^4.1.2",
+ "leven": "^3.1.0",
+ "pretty-format": "30.3.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/helmet": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz",
- "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==",
+ "node_modules/jest-validate/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
"license": "MIT",
"engines": {
- "node": ">=18.0.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "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==",
+ "node_modules/jest-watcher": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.3.0.tgz",
+ "integrity": "sha512-PJ1d9ThtTR8aMiBWUdcownq9mDdLXsQzJayTk4kmaBRHKvwNQn+ANveuhEBUyNI2hR1TVhvQ8D5kHubbzBHR/w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
+ "@jest/test-result": "30.3.0",
+ "@jest/types": "30.3.0",
+ "@types/node": "*",
+ "ansi-escapes": "^4.3.2",
+ "chalk": "^4.1.2",
+ "emittery": "^0.13.1",
+ "jest-util": "30.3.0",
+ "string-length": "^4.0.2"
},
"engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/iconv-lite": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
- "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+ "node_modules/jest-worker": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.3.0.tgz",
+ "integrity": "sha512-DrCKkaQwHexjRUFTmPzs7sHQe0TSj9nvDALKGdwmK5mW9v7j90BudWirKAJHt3QQ9Dhrg1F7DogPzhChppkJpQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
+ "@types/node": "*",
+ "@ungap/structured-clone": "^1.3.0",
+ "jest-util": "30.3.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.1.1"
},
"engines": {
- "node": ">=0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "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/jest-worker/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
- "license": "ISC"
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"license": "MIT",
"engines": {
- "node": ">= 0.10"
+ "node": ">=8"
}
},
- "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==",
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "binary-extensions": "^2.0.0"
+ "has-flag": "^4.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
+ "license": "MIT"
},
- "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==",
+ "node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-extglob": "^2.1.1"
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
},
- "engines": {
- "node": ">=0.10.0"
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "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==",
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
"engines": {
- "node": ">=0.12.0"
+ "node": ">=6"
}
},
- "node_modules/is-promise": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
- "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
"license": "MIT"
},
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/jsonwebtoken": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
@@ -815,6 +4713,63 @@
"node": ">=18.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,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/lodash.includes": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -857,6 +4812,42 @@
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
"license": "MIT"
},
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -893,6 +4884,36 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
@@ -918,6 +4939,16 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/minimatch": {
"version": "10.2.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
@@ -934,6 +4965,16 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/minipass": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
+ "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
"node_modules/mongodb": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.1.1.tgz",
@@ -1072,13 +5113,36 @@
"integrity": "sha512-b2KQNsmgtkscfeDgkYMcWGn9vZI9YoXh802VDEwE6qc50zxBFQ0Oo8ROkawbPAsXCY1/Z1yp0MagqsZStPWJjw==",
"license": "MIT",
"engines": {
- "node": ">=20.19.0"
+ "node": ">=20.19.0"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/napi-postinstall": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
+ "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "napi-postinstall": "lib/cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/napi-postinstall"
}
},
- "node_modules/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/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
"license": "MIT"
},
"node_modules/negotiator": {
@@ -1090,6 +5154,20 @@
"node": ">= 0.6"
}
},
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.37",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz",
+ "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/nodemon": {
"version": "3.1.14",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz",
@@ -1129,6 +5207,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -1180,6 +5271,108 @@
"wrappy": "1"
}
},
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -1189,6 +5382,60 @@
"node": ">= 0.8"
}
},
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/path-to-regexp": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.0.tgz",
@@ -1199,6 +5446,13 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/picomatch": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
@@ -1212,6 +5466,123 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "30.3.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.3.0.tgz",
+ "integrity": "sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==",
+ "dev": true,
+ "license": "MIT",
+ "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/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -1225,6 +5596,15 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
@@ -1241,6 +5621,23 @@
"node": ">=6"
}
},
+ "node_modules/pure-rand": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz",
+ "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/qs": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
@@ -1262,35 +5659,84 @@
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
- "node": ">= 0.6"
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/razorpay": {
+ "version": "2.9.6",
+ "resolved": "https://registry.npmjs.org/razorpay/-/razorpay-2.9.6.tgz",
+ "integrity": "sha512-zsHAQzd6e1Cc6BNoCNZQaf65ElL6O6yw0wulxmoG5VQDr363fZC90Mp1V5EktVzG45yPyNomNXWlf4cQ3622gQ==",
+ "license": "MIT",
+ "dependencies": {
+ "axios": "^1.6.8"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/raw-body": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
- "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "bytes": "~3.1.2",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.7.0",
- "unpipe": "~1.0.0"
+ "resolve-from": "^5.0.0"
},
"engines": {
- "node": ">= 0.10"
+ "node": ">=8"
}
},
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "picomatch": "^2.2.1"
- },
"engines": {
- "node": ">=8.10.0"
+ "node": ">=8"
}
},
"node_modules/router": {
@@ -1398,6 +5844,29 @@
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
@@ -1476,50 +5945,425 @@
"integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==",
"license": "MIT"
},
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/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==",
"dev": true,
- "license": "MIT",
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/sparse-bitfield": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
+ "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
+ "license": "MIT",
+ "dependencies": {
+ "memory-pager": "^1.0.2"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-length/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-length/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
+ "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.2.2"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/superagent": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz",
+ "integrity": "sha512-B+4Ik7ROgVKrQsXTV0Jwp2u+PXYLSlqtDAhYnkkD+zn3yg8s/zjA2MeGayPoY/KICrbitwneDHrjSotxKL+0XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "component-emitter": "^1.3.1",
+ "cookiejar": "^2.1.4",
+ "debug": "^4.3.7",
+ "fast-safe-stringify": "^2.1.1",
+ "form-data": "^4.0.5",
+ "formidable": "^3.5.4",
+ "methods": "^1.1.2",
+ "mime": "2.6.0",
+ "qs": "^6.14.1"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/supertest": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.2.2.tgz",
+ "integrity": "sha512-oK8WG9diS3DlhdUkcFn4tkNIiIbBx9lI2ClF8K+b2/m8Eyv47LSawxUzZQSNKUrVb2KsqeTDCcjAAVPYaSLVTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cookie-signature": "^1.2.2",
+ "methods": "^1.1.2",
+ "superagent": "^10.3.0"
+ },
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/synckit": {
+ "version": "0.11.12",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz",
+ "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@pkgr/core": "^0.2.9"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/synckit"
+ }
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "semver": "^7.5.3"
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
},
"engines": {
- "node": ">=10"
+ "node": ">=8"
}
},
- "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==",
+ "node_modules/test-exclude/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/test-exclude/node_modules/brace-expansion": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "memory-pager": "^1.0.2"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "node_modules/statuses": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
- "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
- "license": "MIT",
+ "node_modules/test-exclude/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
"engines": {
- "node": ">= 0.8"
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "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==",
+ "node_modules/test-exclude/node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "has-flag": "^3.0.0"
+ "brace-expansion": "^1.1.7"
},
"engines": {
- "node": ">=4"
+ "node": "*"
}
},
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -1564,6 +6408,50 @@
"node": ">=18"
}
},
+ "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==",
+ "dev": true,
+ "license": "0BSD",
+ "optional": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
@@ -1585,6 +6473,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/undici-types": {
+ "version": "7.18.2",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
+ "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
@@ -1594,6 +6489,97 @@
"node": ">= 0.8"
}
},
+ "node_modules/unrs-resolver": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
+ "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "napi-postinstall": "^0.3.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unrs-resolver"
+ },
+ "optionalDependencies": {
+ "@unrs/resolver-binding-android-arm-eabi": "1.11.1",
+ "@unrs/resolver-binding-android-arm64": "1.11.1",
+ "@unrs/resolver-binding-darwin-arm64": "1.11.1",
+ "@unrs/resolver-binding-darwin-x64": "1.11.1",
+ "@unrs/resolver-binding-freebsd-x64": "1.11.1",
+ "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1",
+ "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1",
+ "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-arm64-musl": "1.11.1",
+ "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1",
+ "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-x64-gnu": "1.11.1",
+ "@unrs/resolver-binding-linux-x64-musl": "1.11.1",
+ "@unrs/resolver-binding-wasm32-wasi": "1.11.1",
+ "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1",
+ "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1",
+ "@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -1603,6 +6589,16 @@
"node": ">= 0.8"
}
},
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@@ -1625,11 +6621,250 @@
"node": ">=18"
}
},
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
+ },
+ "node_modules/write-file-atomic": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
+ "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/yargs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
}
}
diff --git a/backend/package.json b/backend/package.json
index bf29d77..6008bbb 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -6,7 +6,8 @@
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "jest --forceExit",
+ "lint": "eslint ."
},
"repository": {
"type": "git",
@@ -16,6 +17,10 @@
"author": "",
"license": "ISC",
"type": "commonjs",
+ "jest": {
+ "testEnvironment": "node",
+ "testMatch": ["**/tests/**/*.test.js"]
+ },
"bugs": {
"url": "https://github.com/Mishra-coder/Zappify/issues"
},
@@ -28,9 +33,13 @@
"helmet": "^8.1.0",
"jsonwebtoken": "^9.0.3",
"mongoose": "^9.3.3",
- "morgan": "^1.10.1"
+ "morgan": "^1.10.1",
+ "razorpay": "^2.9.6"
},
"devDependencies": {
- "nodemon": "^3.1.14"
+ "eslint": "^10.2.0",
+ "jest": "^30.3.0",
+ "nodemon": "^3.1.14",
+ "supertest": "^7.2.2"
}
}
diff --git a/backend/routes/paymentRoutes.js b/backend/routes/paymentRoutes.js
new file mode 100644
index 0000000..b731775
--- /dev/null
+++ b/backend/routes/paymentRoutes.js
@@ -0,0 +1,40 @@
+const express = require('express');
+const router = express.Router();
+const Razorpay = require('razorpay');
+const crypto = require('crypto');
+
+const razorpay = new Razorpay({
+ key_id: process.env.RAZORPAY_KEY_ID,
+ key_secret: process.env.RAZORPAY_KEY_SECRET,
+});
+
+router.post('/create-order', async (req, res) => {
+ try {
+ const { amount } = req.body;
+ const order = await razorpay.orders.create({
+ amount: amount * 100,
+ currency: 'INR',
+ receipt: 'receipt_' + Date.now(),
+ });
+ res.json({ orderId: order.id, amount: order.amount, currency: order.currency });
+ } catch (err) {
+ res.status(500).json({ message: 'Failed to create order', error: err.message });
+ }
+});
+
+router.post('/verify', (req, res) => {
+ const { razorpay_order_id, razorpay_payment_id, razorpay_signature } = req.body;
+ const body = razorpay_order_id + '|' + razorpay_payment_id;
+ const expectedSignature = crypto
+ .createHmac('sha256', process.env.RAZORPAY_KEY_SECRET)
+ .update(body)
+ .digest('hex');
+
+ if (expectedSignature === razorpay_signature) {
+ res.json({ success: true, paymentId: razorpay_payment_id });
+ } else {
+ res.status(400).json({ success: false, message: 'Invalid signature' });
+ }
+});
+
+module.exports = router;
diff --git a/backend/server.js b/backend/server.js
index 3dba782..54913b8 100644
--- a/backend/server.js
+++ b/backend/server.js
@@ -1,13 +1,12 @@
+require('dotenv').config();
const express = require('express');
-const dotenv = require('dotenv');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const connectDB = require('./config/db');
const userRoutes = require('./routes/userRoutes');
const productRoutes = require('./routes/productRoutes');
-
-dotenv.config();
+const paymentRoutes = require('./routes/paymentRoutes');
connectDB();
@@ -23,6 +22,7 @@ if (process.env.NODE_ENV === 'development') {
app.use('/api/users', userRoutes);
app.use('/api/products', productRoutes);
+app.use('/api/payment', paymentRoutes);
app.get('/', (req, res) => {
res.send("API is running...");
@@ -38,6 +38,4 @@ app.use((err, req, res, next) => {
const PORT = process.env.PORT || 5001;
-app.listen(PORT, () => {
- console.log(`Server started on port ${PORT}`);
-});
+app.listen(PORT);
diff --git a/backend/tests/integration/api.test.js b/backend/tests/integration/api.test.js
new file mode 100644
index 0000000..0e63cbf
--- /dev/null
+++ b/backend/tests/integration/api.test.js
@@ -0,0 +1,26 @@
+const request = require('supertest');
+const express = require('express');
+
+jest.mock('../../models/Product', () => ({
+ find: jest.fn().mockResolvedValue([]),
+ findById: jest.fn().mockResolvedValue(null),
+}));
+
+const productRoutes = require('../../routes/productRoutes');
+
+const app = express();
+app.use(express.json());
+app.use('/api/products', productRoutes);
+
+describe('Product API', () => {
+ test('GET /api/products should return an array', async () => {
+ const res = await request(app).get('/api/products');
+ expect(res.status).toBe(200);
+ expect(Array.isArray(res.body)).toBe(true);
+ });
+
+ test('GET /api/products/:id with wrong id should give 404', async () => {
+ const res = await request(app).get('/api/products/507f1f77bcf86cd799439011');
+ expect(res.status).toBe(404);
+ });
+});
diff --git a/backend/tests/unit/userController.test.js b/backend/tests/unit/userController.test.js
new file mode 100644
index 0000000..681109d
--- /dev/null
+++ b/backend/tests/unit/userController.test.js
@@ -0,0 +1,19 @@
+const { validateEmail } = require('../../utils/validate');
+
+describe('validateEmail', () => {
+ test('normal email should work', () => {
+ expect(validateEmail('devendra@gmail.com')).toBe(true);
+ });
+
+ test('no @ means invalid', () => {
+ expect(validateEmail('devendragmail.com')).toBe(false);
+ });
+
+ test('no dot after @ means invalid', () => {
+ expect(validateEmail('devendra@gmailcom')).toBe(false);
+ });
+
+ test('empty string should fail', () => {
+ expect(validateEmail('')).toBe(false);
+ });
+});
diff --git a/backend/utils/validate.js b/backend/utils/validate.js
new file mode 100644
index 0000000..4c80b83
--- /dev/null
+++ b/backend/utils/validate.js
@@ -0,0 +1,11 @@
+const validateEmail = (email) => {
+ if (!email) return false;
+ const atIndex = email.indexOf('@');
+ const dotIndex = email.lastIndexOf('.');
+ if (atIndex < 1) return false;
+ if (dotIndex < atIndex + 2) return false;
+ if (dotIndex === email.length - 1) return false;
+ return true;
+};
+
+module.exports = { validateEmail };
diff --git a/frontend/index.html b/frontend/index.html
index a116dd2..bbcb7e4 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -5,6 +5,11 @@
Zappify Shoes
+
+
+
+
+
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index c0ad6ab..fa2c9e3 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -13,7 +13,8 @@
"jwt-decode": "^4.0.0",
"lucide-react": "^1.7.0",
"react": "^19.2.4",
- "react-dom": "^19.2.4"
+ "react-dom": "^19.2.4",
+ "react-router-dom": "^7.14.0"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
@@ -1123,6 +1124,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cookie": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
+ "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2304,6 +2318,44 @@
"react": "^19.2.4"
}
},
+ "node_modules/react-router": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.14.0.tgz",
+ "integrity": "sha512-m/xR9N4LQLmAS0ZhkY2nkPA1N7gQ5TUVa5n8TgANuDTARbn1gt+zLPXEm7W0XDTbrQ2AJSJKhoa6yx1D8BcpxQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.14.0.tgz",
+ "integrity": "sha512-2G3ajSVSZMEtmTjIklRWlNvo8wICEpLihfD/0YMDxbWK2UyP5EGfnoIn9AIQGnF3G/FX0MRbHXdFcD+rL1ZreQ==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.14.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -2371,6 +2423,12 @@
"semver": "bin/semver.js"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
+ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 9bb8331..503b542 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -15,7 +15,8 @@
"jwt-decode": "^4.0.0",
"lucide-react": "^1.7.0",
"react": "^19.2.4",
- "react-dom": "^19.2.4"
+ "react-dom": "^19.2.4",
+ "react-router-dom": "^7.14.0"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
diff --git a/frontend/public/hero-nike.png b/frontend/public/hero-nike.png
new file mode 100644
index 0000000..b5444b8
Binary files /dev/null and b/frontend/public/hero-nike.png differ
diff --git a/frontend/public/logo.png b/frontend/public/logo.png
new file mode 100644
index 0000000..64a1df6
Binary files /dev/null and b/frontend/public/logo.png differ
diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json
new file mode 100644
index 0000000..18b349a
--- /dev/null
+++ b/frontend/public/manifest.json
@@ -0,0 +1,24 @@
+{
+ "name": "Zappify Shoes",
+ "short_name": "Zappify",
+ "description": "Premium Shoe Store Experience.",
+ "start_url": "/",
+ "display": "standalone",
+ "background_color": "#FF3D00",
+ "theme_color": "#FF3D00",
+ "orientation": "portrait",
+ "icons": [
+ {
+ "src": "/logo.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any maskable"
+ },
+ {
+ "src": "/logo.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "any maskable"
+ }
+ ]
+}
diff --git a/frontend/public/shoes/Air Jordan 1 Low SE.jpg b/frontend/public/shoes/Air Jordan 1 Low SE.jpg
new file mode 100644
index 0000000..2fdf962
Binary files /dev/null and b/frontend/public/shoes/Air Jordan 1 Low SE.jpg differ
diff --git a/frontend/public/shoes/Air Jordan 1 Mid.jpg b/frontend/public/shoes/Air Jordan 1 Mid.jpg
new file mode 100644
index 0000000..cd98828
Binary files /dev/null and b/frontend/public/shoes/Air Jordan 1 Mid.jpg differ
diff --git a/frontend/public/shoes/LeBron Witness IX EP.jpg b/frontend/public/shoes/LeBron Witness IX EP.jpg
new file mode 100644
index 0000000..2de46fd
Binary files /dev/null and b/frontend/public/shoes/LeBron Witness IX EP.jpg differ
diff --git a/frontend/public/shoes/Nike Air Max 270.jpg b/frontend/public/shoes/Nike Air Max 270.jpg
new file mode 100644
index 0000000..a270adb
Binary files /dev/null and b/frontend/public/shoes/Nike Air Max 270.jpg differ
diff --git a/frontend/public/shoes/Nike Air Max Alpha Trainer 6.jpg b/frontend/public/shoes/Nike Air Max Alpha Trainer 6.jpg
new file mode 100644
index 0000000..3748134
Binary files /dev/null and b/frontend/public/shoes/Nike Air Max Alpha Trainer 6.jpg differ
diff --git a/frontend/public/shoes/Nike Air Max Dn Roam.jpg b/frontend/public/shoes/Nike Air Max Dn Roam.jpg
new file mode 100644
index 0000000..f4dec56
Binary files /dev/null and b/frontend/public/shoes/Nike Air Max Dn Roam.jpg differ
diff --git a/frontend/public/shoes/Nike Air Max Excee.jpg b/frontend/public/shoes/Nike Air Max Excee.jpg
new file mode 100644
index 0000000..3f951fd
Binary files /dev/null and b/frontend/public/shoes/Nike Air Max Excee.jpg differ
diff --git a/frontend/public/shoes/Nike Ava Rover.jpg b/frontend/public/shoes/Nike Ava Rover.jpg
new file mode 100644
index 0000000..72d7dc9
Binary files /dev/null and b/frontend/public/shoes/Nike Ava Rover.jpg differ
diff --git a/frontend/public/shoes/Nike Downshifter 14.jpg b/frontend/public/shoes/Nike Downshifter 14.jpg
new file mode 100644
index 0000000..05f6713
Binary files /dev/null and b/frontend/public/shoes/Nike Downshifter 14.jpg differ
diff --git a/frontend/public/shoes/Nike Free Metcon 6.jpg b/frontend/public/shoes/Nike Free Metcon 6.jpg
new file mode 100644
index 0000000..0eadd04
Binary files /dev/null and b/frontend/public/shoes/Nike Free Metcon 6.jpg differ
diff --git a/frontend/public/shoes/Nike Journey Run.jpg b/frontend/public/shoes/Nike Journey Run.jpg
new file mode 100644
index 0000000..9b2d1e6
Binary files /dev/null and b/frontend/public/shoes/Nike Journey Run.jpg differ
diff --git a/frontend/public/shoes/Nike Killshot 2 Leather Premium.jpg b/frontend/public/shoes/Nike Killshot 2 Leather Premium.jpg
new file mode 100644
index 0000000..5ab6884
Binary files /dev/null and b/frontend/public/shoes/Nike Killshot 2 Leather Premium.jpg differ
diff --git a/frontend/public/shoes/Nike Killshot 2 Leather.jpg b/frontend/public/shoes/Nike Killshot 2 Leather.jpg
new file mode 100644
index 0000000..9070846
Binary files /dev/null and b/frontend/public/shoes/Nike Killshot 2 Leather.jpg differ
diff --git a/frontend/public/shoes/Nike P-6000.jpg b/frontend/public/shoes/Nike P-6000.jpg
new file mode 100644
index 0000000..3188e76
Binary files /dev/null and b/frontend/public/shoes/Nike P-6000.jpg differ
diff --git a/frontend/public/shoes/Nike Promina.jpg b/frontend/public/shoes/Nike Promina.jpg
new file mode 100644
index 0000000..b4ff48f
Binary files /dev/null and b/frontend/public/shoes/Nike Promina.jpg differ
diff --git a/frontend/public/shoes/Nike Quest 6.jpg b/frontend/public/shoes/Nike Quest 6.jpg
new file mode 100644
index 0000000..dd1fcb3
Binary files /dev/null and b/frontend/public/shoes/Nike Quest 6.jpg differ
diff --git a/frontend/public/shoes/Nike Revolution 8 EasyOn.jpg b/frontend/public/shoes/Nike Revolution 8 EasyOn.jpg
new file mode 100644
index 0000000..0edbc56
Binary files /dev/null and b/frontend/public/shoes/Nike Revolution 8 EasyOn.jpg differ
diff --git a/frontend/public/shoes/Nike Run Defy.jpg b/frontend/public/shoes/Nike Run Defy.jpg
new file mode 100644
index 0000000..d492a3f
Binary files /dev/null and b/frontend/public/shoes/Nike Run Defy.jpg differ
diff --git a/frontend/public/shoes/Nike SB Zoom Blazer Low Pro GT.jpg b/frontend/public/shoes/Nike SB Zoom Blazer Low Pro GT.jpg
new file mode 100644
index 0000000..122981a
Binary files /dev/null and b/frontend/public/shoes/Nike SB Zoom Blazer Low Pro GT.jpg differ
diff --git a/frontend/public/shoes/Nike Winflo 11.jpg b/frontend/public/shoes/Nike Winflo 11.jpg
new file mode 100644
index 0000000..b98fe28
Binary files /dev/null and b/frontend/public/shoes/Nike Winflo 11.jpg differ
diff --git a/frontend/public/shoes/shoe1.png b/frontend/public/shoes/shoe1.png
new file mode 100644
index 0000000..c391d5c
Binary files /dev/null and b/frontend/public/shoes/shoe1.png differ
diff --git a/frontend/public/shoes/shoe10.png b/frontend/public/shoes/shoe10.png
new file mode 100644
index 0000000..2cf3e0b
Binary files /dev/null and b/frontend/public/shoes/shoe10.png differ
diff --git a/frontend/public/shoes/shoe11.png b/frontend/public/shoes/shoe11.png
new file mode 100644
index 0000000..1903d18
Binary files /dev/null and b/frontend/public/shoes/shoe11.png differ
diff --git a/frontend/public/shoes/shoe12.png b/frontend/public/shoes/shoe12.png
new file mode 100644
index 0000000..3db262a
Binary files /dev/null and b/frontend/public/shoes/shoe12.png differ
diff --git a/frontend/public/shoes/shoe2.png b/frontend/public/shoes/shoe2.png
new file mode 100644
index 0000000..19c9406
Binary files /dev/null and b/frontend/public/shoes/shoe2.png differ
diff --git a/frontend/public/shoes/shoe3.png b/frontend/public/shoes/shoe3.png
new file mode 100644
index 0000000..d8869e8
Binary files /dev/null and b/frontend/public/shoes/shoe3.png differ
diff --git a/frontend/public/shoes/shoe4.png b/frontend/public/shoes/shoe4.png
new file mode 100644
index 0000000..7830d44
Binary files /dev/null and b/frontend/public/shoes/shoe4.png differ
diff --git a/frontend/public/shoes/shoe5.png b/frontend/public/shoes/shoe5.png
new file mode 100644
index 0000000..0cc3332
Binary files /dev/null and b/frontend/public/shoes/shoe5.png differ
diff --git a/frontend/public/shoes/shoe6.png b/frontend/public/shoes/shoe6.png
new file mode 100644
index 0000000..57ba82e
Binary files /dev/null and b/frontend/public/shoes/shoe6.png differ
diff --git a/frontend/public/shoes/shoe7.png b/frontend/public/shoes/shoe7.png
new file mode 100644
index 0000000..a097028
Binary files /dev/null and b/frontend/public/shoes/shoe7.png differ
diff --git a/frontend/public/shoes/shoe8.png b/frontend/public/shoes/shoe8.png
new file mode 100644
index 0000000..5629155
Binary files /dev/null and b/frontend/public/shoes/shoe8.png differ
diff --git a/frontend/public/shoes/shoe9.png b/frontend/public/shoes/shoe9.png
new file mode 100644
index 0000000..b037da1
Binary files /dev/null and b/frontend/public/shoes/shoe9.png differ
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 318fb59..03c61af 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,24 +1,25 @@
import { useState, useMemo } from 'react'
import Header from './components/Header'
+import Sidebar from './components/Sidebar'
import ProductGrid from './components/ProductGrid'
import ProductDetail from './components/ProductDetail'
import { ALL_PRODUCTS } from './data/products'
import { motion, AnimatePresence } from 'framer-motion'
-import { X, ShoppingBag, Heart, User, Trash2 } from 'lucide-react'
+import { X, ShoppingBag, Heart, Trash2 } from 'lucide-react'
import { useGoogleLogin } from '@react-oauth/google'
import Checkout from './components/Checkout'
import AccountModal from './components/AccountModal'
-const CATEGORIES = ['All', 'Men Low Top Sneakers', 'Men High Top Sneakers', 'Men Mid Top Sneakers', 'Men Clogs', 'Men Slip-ons'];
-
function App() {
const [selectedCategories, setSelectedCategories] = useState([]);
const [selectedProduct, setSelectedProduct] = useState(null);
const [activeOverlay, setActiveOverlay] = useState(null);
const [searchQuery, setSearchQuery] = useState('');
+ const [activeNav, setActiveNav] = useState('ALL');
const [sneakersView, setSneakersView] = useState(false);
const [showCheckout, setShowCheckout] = useState(false);
const [showAccount, setShowAccount] = useState(false);
+ const [showNikeBanner, setShowNikeBanner] = useState(false);
const [cartItems, setCartItems] = useState(() => {
try { return JSON.parse(localStorage.getItem('zappify_cart')) || []; } catch { return []; }
@@ -55,10 +56,23 @@ function App() {
setPlacedOrders([]);
};
+ const toggleFilter = (item, type) => {
+ if (type === 'category') {
+ if (selectedCategories.includes(item)) {
+ setSelectedCategories(selectedCategories.filter(i => i !== item));
+ } else {
+ setSelectedCategories([...selectedCategories, item]);
+ }
+ }
+ };
+
const handleNavigate = (destination) => {
setSelectedProduct(null);
setSelectedCategories([]);
+ setShowNikeBanner(false);
setSneakersView(destination === 'SNEAKERS');
+ if (destination !== 'home') setActiveNav(destination);
+ else setActiveNav('ALL');
};
const addToCart = (product, size) => {
@@ -93,145 +107,200 @@ function App() {
const isWishlisted = (id) => wishlistItems.some(i => i.id === id);
const filteredProducts = useMemo(() => {
- return ALL_PRODUCTS.filter(product => {
- const sneakerMatch = sneakersView ? product.id >= 30 && product.id <= 44 : true;
- const categoryMatch = selectedCategories.length === 0 || selectedCategories.includes(product.category);
- const searchMatch = searchQuery.trim() === '' ||
- product.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
- product.brand.toLowerCase().includes(searchQuery.toLowerCase()) ||
- product.category.toLowerCase().includes(searchQuery.toLowerCase());
- return sneakerMatch && categoryMatch && searchMatch;
- });
- }, [selectedCategories, sneakersView, searchQuery]);
+ const searchMatch = (product) =>
+ searchQuery.trim() === '' ||
+ product.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ product.brand.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ product.category.toLowerCase().includes(searchQuery.toLowerCase());
+
+ const categoryMatch = (product) =>
+ selectedCategories.length === 0 || selectedCategories.includes(product.category);
+
+ if (showNikeBanner) {
+ return ALL_PRODUCTS.filter(p => p.brand === 'NIKE' && !p.gender && searchMatch(p));
+ }
+
+ if (activeNav === 'MEN') {
+ const menProducts = ALL_PRODUCTS.filter(p =>
+ p.gender === 'MEN' && searchMatch(p) && categoryMatch(p)
+ );
+ const nikeOriginal = ALL_PRODUCTS.filter(p =>
+ !p.gender && searchMatch(p) && categoryMatch(p)
+ );
+ return [...menProducts, ...nikeOriginal];
+ }
+
+ if (activeNav === 'SNEAKERS' || sneakersView) {
+ return ALL_PRODUCTS.filter(p =>
+ p.brand === 'NIKE' && !p.gender && searchMatch(p) && categoryMatch(p)
+ );
+ }
+
+ return ALL_PRODUCTS.filter(p =>
+ searchMatch(p) && categoryMatch(p)
+ );
+ }, [selectedCategories, sneakersView, searchQuery, activeNav, showNikeBanner]);
+
return (
-
-
sum + i.qty, 0)}
- wishlistCount={wishlistItems.length}
- loggedInUser={loggedInUser}
- onOpenAccount={() => setShowAccount(true)}
- searchQuery={searchQuery}
- onSearch={setSearchQuery}
- />
-
-
-
-
- {!selectedProduct ? (
-
-
- {CATEGORIES.map(cat => (
-
cat === 'All'
- ? setSelectedCategories([])
- : setSelectedCategories(prev => prev.includes(cat) ? prev.filter(c => c !== cat) : [...prev, cat])
- }
+
+
+ sum + i.qty, 0)}
+ wishlistCount={wishlistItems.length}
+ activeNav={activeNav}
+ loggedInUser={loggedInUser}
+ onOpenAccount={() => setShowAccount(true)}
+ searchQuery={searchQuery}
+ onSearch={(q) => { setSearchQuery(q); if (!q) setShowNikeBanner(false); }}
+ />
+
+
+
+
+
+ {!selectedProduct ? (
+
- {cat}
-
- ))}
-
-
-
- ) : (
-
- setSelectedProduct(null)}
- onAddToCart={addToCart}
- onToggleWishlist={toggleWishlist}
- isWishlisted={isWishlisted(selectedProduct.id)}
- />
-
+
+
+
+ {!searchQuery && !selectedCategories.length && (
+
{
+ setShowNikeBanner(true);
+ setSearchQuery('Nike');
+ }} />
+ )}
+ {showNikeBanner && (
+
+
+
SPRING COLLECTION 2026
+
20 Iconic Nike Shoes
+
Handpicked for you — the finest kicks from Nike's latest lineup.
+
+
20 Products
+
+
7 Categories
+
+
2026 Collection
+
+
{ setShowNikeBanner(false); setSearchQuery(''); }}>← Back to All
+
+
+
+
+
+ )}
+ { setSelectedProduct(product); window.scrollTo({ top: 0, behavior: 'smooth' }); }}
+ onToggleWishlist={toggleWishlist}
+ isWishlisted={isWishlisted}
+ />
+
+
+
+ ) : (
+
+ setSelectedProduct(null)}
+ onAddToCart={addToCart}
+ onToggleWishlist={toggleWishlist}
+ isWishlisted={isWishlisted(selectedProduct.id)}
+ />
+
+ )}
+
+
+
+
+
+
+
+
+
© 2026 Zappify Shoe Store. All rights reserved.
+
+
+
+
+
+ {activeOverlay && (
+ setActiveOverlay(null)}
+ cartItems={cartItems}
+ wishlistItems={wishlistItems}
+ onRemoveFromCart={removeFromCart}
+ onToggleWishlist={toggleWishlist}
+ onLoginSuccess={handleLogin}
+ onCheckout={() => { setActiveOverlay(null); setShowCheckout(true); }}
+ loggedInUser={loggedInUser}
+ onSwitchOverlay={setActiveOverlay}
+ />
)}
-
-
-
-
-
-
© 2026 Zappify Shoe Store. All rights reserved.
-
-
-
-
-
- {activeOverlay && (
- setActiveOverlay(null)}
- cartItems={cartItems}
- wishlistItems={wishlistItems}
- onRemoveFromCart={removeFromCart}
- onToggleWishlist={toggleWishlist}
- onLoginSuccess={handleLogin}
- onCheckout={() => { setActiveOverlay(null); setShowCheckout(true); }}
- loggedInUser={loggedInUser}
- onSwitchOverlay={setActiveOverlay}
- />
- )}
-
-
- {showCheckout && (
- setShowCheckout(false)}
- onRemoveFromCart={removeFromCart}
- onOrderPlaced={(items) => {
- const newOrders = items.map(item => ({
- ...item,
- orderId: Math.floor(10000000 + Math.random() * 90000000).toString(),
- placedAt: new Date().toISOString(),
- status: 'Placed',
- }));
- const updated = [...placedOrders, ...newOrders];
- setPlacedOrders(updated);
- localStorage.setItem(userOrdersKey(loggedInUser), JSON.stringify(updated));
- setCartItems([]);
- localStorage.removeItem('zappify_cart');
- }}
- />
- )}
+ {showCheckout && (
+ setShowCheckout(false)}
+ onRemoveFromCart={removeFromCart}
+ onOrderPlaced={(items) => {
+ const newOrders = items.map(item => ({
+ ...item,
+ orderId: Math.floor(10000000 + Math.random() * 90000000).toString(),
+ placedAt: new Date().toISOString(),
+ status: 'Placed',
+ }));
+ const updated = [...placedOrders, ...newOrders];
+ setPlacedOrders(updated);
+ localStorage.setItem(userOrdersKey(loggedInUser), JSON.stringify(updated));
+ setCartItems([]);
+ localStorage.removeItem('zappify_cart');
+ }}
+ />
+ )}
- {showAccount && loggedInUser && (
- setShowAccount(false)}
- onLogout={() => { handleLogout(); setShowAccount(false); }}
- onCancelOrder={(orderId) => {
- const updated = placedOrders.map(o => o.orderId === orderId ? { ...o, status: 'Cancelled' } : o);
- setPlacedOrders(updated);
- localStorage.setItem(userOrdersKey(loggedInUser), JSON.stringify(updated));
- }}
- />
- )}
-
+ {showAccount && loggedInUser && (
+ setShowAccount(false)}
+ onLogout={() => { handleLogout(); setShowAccount(false); }}
+ onCancelOrder={(orderId) => {
+ const updated = placedOrders.map(o => o.orderId === orderId ? { ...o, status: 'Cancelled' } : o);
+ setPlacedOrders(updated);
+ localStorage.setItem(userOrdersKey(loggedInUser), JSON.stringify(updated));
+ }}
+ />
+ )}
+
+
);
}
@@ -268,7 +337,7 @@ const Overlay = ({ type, onClose, cartItems, wishlistItems, onRemoveFromCart, on
const user = {
name: formData.name,
email: formData.email,
- picture: `https://ui-avatars.com/api/?name=${encodeURIComponent(formData.name)}&background=e85d04&color=fff`,
+ picture: `https://ui-avatars.com/api/?name=${encodeURIComponent(formData.name)}&background=E85D04&color=fff`,
};
onLoginSuccess(user);
onClose();
@@ -363,15 +432,19 @@ const Overlay = ({ type, onClose, cartItems, wishlistItems, onRemoveFromCart, on
) : (
-
-
-
+
+
+
+
+
+
ZAPPIFY
+
Premium Footwear
+
Step into the future
+
-
-
+
{isSignUp ? 'Create Account' : 'Welcome Back'}
{isSignUp ? 'Join Zappify today' : 'Login to your Zappify account'}
-
{isSignUp &&
setFormData({ ...formData, name: e.target.value })} />}
setFormData({ ...formData, email: e.target.value })} />
@@ -379,13 +452,12 @@ const Overlay = ({ type, onClose, cartItems, wishlistItems, onRemoveFromCart, on
{isSignUp &&
setFormData({ ...formData, confirm: e.target.value })} />}
{error &&
{error}
}
{isSignUp ? 'CREATE ACCOUNT' : 'SIGN IN'}
-
OR CONTINUE WITH
-
googleLogin()}>
-
- {isSignUp ? 'Sign up with Google' : 'Sign in with Google'}
+ OR
+ googleLogin()}>
+
+ {isSignUp ? 'Sign up with Google' : 'Sign in with Google'}
-
{isSignUp ? 'Already have an account? ' : "Don't have an account? "}
setIsSignUp(!isSignUp)}>{isSignUp ? 'Sign In' : 'Sign Up'}
@@ -397,4 +469,53 @@ const Overlay = ({ type, onClose, cartItems, wishlistItems, onRemoveFromCart, on
);
};
+const HeroBanner = ({ onExplore }) => (
+
+
+
+ SPRING COLLECTION 2026
+
+
+ Experience The Future Of Streetwear
+
+
+ Unmatched comfort. Uncompromising style. Crafted for those who move.
+
+
+ EXPLORE NOW
+
+
+
+
+
+
+);
+
export default App;
diff --git a/frontend/src/Preview.jsx b/frontend/src/Preview.jsx
deleted file mode 100644
index 6409606..0000000
--- a/frontend/src/Preview.jsx
+++ /dev/null
@@ -1,117 +0,0 @@
-import React from 'react';
-
-export default function Preview() {
- return (
-
-
-
-
- Z appify
-
-
Premium Shoe Store
-
-
-
- );
-}
-
-const styles = {
- page: {
- minHeight: '100vh',
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'center',
- background: 'linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%)',
- fontFamily: 'sans-serif',
- padding: '40px 20px',
- flexDirection: 'column',
- },
- bg: {
- position: 'fixed',
- inset: 0,
- background: 'radial-gradient(ellipse at 20% 50%, rgba(232,93,4,0.15) 0%, transparent 60%), radial-gradient(ellipse at 80% 20%, rgba(100,100,255,0.1) 0%, transparent 60%)',
- pointerEvents: 'none',
- },
- content: {
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- gap: '12px',
- position: 'relative',
- zIndex: 1,
- },
- brand: {
- fontSize: '36px',
- fontWeight: '900',
- color: '#fff',
- letterSpacing: '-1px',
- },
- brandZ: {
- color: '#e85d04',
- },
- tagline: {
- color: 'rgba(255,255,255,0.5)',
- fontSize: '14px',
- margin: 0,
- letterSpacing: '2px',
- textTransform: 'uppercase',
- },
- phoneWrap: {
- marginTop: '20px',
- filter: 'drop-shadow(0 40px 80px rgba(0,0,0,0.6))',
- },
- phone: {
- width: '375px',
- height: '780px',
- background: '#111',
- borderRadius: '50px',
- padding: '12px',
- border: '2px solid rgba(255,255,255,0.1)',
- position: 'relative',
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- },
- notch: {
- width: '120px',
- height: '28px',
- background: '#111',
- borderRadius: '0 0 20px 20px',
- position: 'absolute',
- top: '12px',
- left: '50%',
- transform: 'translateX(-50%)',
- zIndex: 10,
- },
- screen: {
- flex: 1,
- width: '100%',
- borderRadius: '40px',
- overflow: 'hidden',
- background: '#fff',
- },
- iframe: {
- width: '100%',
- height: '100%',
- border: 'none',
- },
- homeBar: {
- width: '120px',
- height: '4px',
- background: 'rgba(255,255,255,0.3)',
- borderRadius: '2px',
- marginTop: '8px',
- },
-};
diff --git a/frontend/src/components/AccountModal.jsx b/frontend/src/components/AccountModal.jsx
index d0651af..04faeb1 100644
--- a/frontend/src/components/AccountModal.jsx
+++ b/frontend/src/components/AccountModal.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { X, Package, LogOut, ArrowLeft, ChevronRight } from 'lucide-react';
@@ -13,10 +13,7 @@ const CANCEL_REASONS = [
const TRACKING_STEPS = ['Order Placed', 'Shipped', 'In-Transit', 'Out For Delivery', 'Delivered'];
-const formatDate = (dateStr) => {
- const d = new Date(dateStr);
- return d.toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' });
-};
+const formatDate = (dateStr) => new Date(dateStr).toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' });
const getEstDelivery = (dateStr) => {
const d = new Date(dateStr);
@@ -25,7 +22,7 @@ const getEstDelivery = (dateStr) => {
};
const AccountModal = ({ user, onClose, onLogout, orders, onCancelOrder }) => {
- const [view, setView] = useState('main'); // main | detail | cancel | cancelled
+ const [view, setView] = useState('main');
const [selectedOrder, setSelectedOrder] = useState(null);
const [cancelReason, setCancelReason] = useState('');
const [remarks, setRemarks] = useState('');
@@ -67,12 +64,10 @@ const AccountModal = ({ user, onClose, onLogout, orders, onCancelOrder }) => {
-
- {/* ── MAIN VIEW ── */}
{view === 'main' && (
<>
-
+
{user.name}
{user.email}
@@ -115,7 +110,6 @@ const AccountModal = ({ user, onClose, onLogout, orders, onCancelOrder }) => {
>
)}
- {/* ── ORDER DETAIL VIEW ── */}
{view === 'detail' && selectedOrder && (
@@ -136,7 +130,6 @@ const AccountModal = ({ user, onClose, onLogout, orders, onCancelOrder }) => {
- {/* Tracking */}
{selectedOrder.status !== 'Cancelled' ? (
{TRACKING_STEPS.map((step, i) => (
@@ -159,7 +152,6 @@ const AccountModal = ({ user, onClose, onLogout, orders, onCancelOrder }) => {
)}
- {/* ── CANCEL VIEW ── */}
{view === 'cancel' && selectedOrder && (
@@ -194,10 +186,8 @@ const AccountModal = ({ user, onClose, onLogout, orders, onCancelOrder }) => {
)}
-
- {/* Confirmation Popup */}
{showConfirmPopup && (
diff --git a/frontend/src/components/Checkout.jsx b/frontend/src/components/Checkout.jsx
index c2054cc..a12912c 100644
--- a/frontend/src/components/Checkout.jsx
+++ b/frontend/src/components/Checkout.jsx
@@ -1,10 +1,10 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
-import { X, ChevronRight, MapPin, CreditCard, ShoppingBag, Check } from 'lucide-react';
+import { X, ChevronRight, MapPin, CreditCard, Check } from 'lucide-react';
const STEPS = ['MY BAG', 'ADDRESS', 'PAYMENT'];
-const Checkout = ({ cartItems, onClose, onRemoveFromCart, onOrderPlaced }) => {
+const Checkout = ({ cartItems, onClose, onOrderPlaced }) => {
const [step, setStep] = useState(0);
const [address, setAddress] = useState({ name: '', phone: '', pincode: '', city: '', state: '', street: '' });
const [paymentMethod, setPaymentMethod] = useState('cod');
@@ -14,20 +14,74 @@ const Checkout = ({ cartItems, onClose, onRemoveFromCart, onOrderPlaced }) => {
const gst = Math.round(cartTotal * 0.05);
const shipping = cartTotal > 999 ? 0 : 99;
- const handlePlaceOrder = () => {
- if (onOrderPlaced) onOrderPlaced(cartItems);
- setOrderPlaced(true);
+ const loadRazorpayScript = () =>
+ new Promise((resolve) => {
+ if (document.getElementById('razorpay-script')) return resolve(true);
+ const script = document.createElement('script');
+ script.id = 'razorpay-script';
+ script.src = 'https://checkout.razorpay.com/v1/checkout.js';
+ script.onload = () => resolve(true);
+ script.onerror = () => resolve(false);
+ document.body.appendChild(script);
+ });
+
+ const handlePlaceOrder = async () => {
+ if (paymentMethod === 'cod') {
+ if (onOrderPlaced) onOrderPlaced(cartItems);
+ setOrderPlaced(true);
+ return;
+ }
+
+ const totalAmount = cartTotal + shipping;
+ const loaded = await loadRazorpayScript();
+ if (!loaded) { alert('Razorpay failed to load. Check your internet.'); return; }
+
+ try {
+ const res = await fetch(`${import.meta.env.VITE_API_URL}/api/payment/create-order`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ amount: totalAmount }),
+ });
+ const data = await res.json();
+
+ const options = {
+ key: import.meta.env.VITE_RAZORPAY_KEY_ID,
+ amount: data.amount,
+ currency: data.currency,
+ name: 'Zappify',
+ description: 'Shoe Purchase',
+ order_id: data.orderId,
+ handler: async (response) => {
+ const verifyRes = await fetch(`${import.meta.env.VITE_API_URL}/api/payment/verify`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(response),
+ });
+ const verifyData = await verifyRes.json();
+ if (verifyData.success) {
+ if (onOrderPlaced) onOrderPlaced(cartItems);
+ setOrderPlaced(true);
+ } else {
+ alert('Payment verification failed. Contact support.');
+ }
+ },
+ prefill: { name: address.name, contact: address.phone },
+ theme: { color: '#FF3D00' },
+ };
+
+ const rzp = new window.Razorpay(options);
+ rzp.open();
+ } catch (err) {
+ console.error('Razorpay error:', err);
+ alert(`Error: ${err.message || 'Something went wrong. Is backend running on port 5001?'}`);
+ }
};
if (orderPlaced) {
return (
-
+
Order Placed!
Your order has been placed successfully. You'll receive a confirmation soon.
@@ -40,36 +94,26 @@ const Checkout = ({ cartItems, onClose, onRemoveFromCart, onOrderPlaced }) => {
return (
-
- {/* Header */}
+
CHECKOUT
- {/* Steps */}
{STEPS.map((s, i) => (
-
+
{i < STEPS.length - 1 &&
}
-
+
))}
- {/* Step Content */}
-
- {/* STEP 1: MY BAG */}
{step === 0 && (
@@ -103,7 +147,6 @@ const Checkout = ({ cartItems, onClose, onRemoveFromCart, onOrderPlaced }) => {
)}
- {/* STEP 2: ADDRESS */}
{step === 1 && (
@@ -121,23 +164,19 @@ const Checkout = ({ cartItems, onClose, onRemoveFromCart, onOrderPlaced }) => {
setStep(0)}>BACK
- {
- if (!address.name || !address.phone || !address.street || !address.city || !address.pincode) {
- alert('Please fill all required fields');
- return;
- }
- setStep(2);
- }}
- >
+ {
+ if (!address.name || !address.phone || !address.street || !address.city || !address.pincode) {
+ alert('Please fill all required fields');
+ return;
+ }
+ setStep(2);
+ }}>
PROCEED TO PAYMENT
)}
- {/* STEP 3: PAYMENT */}
{step === 2 && (
@@ -154,7 +193,6 @@ const Checkout = ({ cartItems, onClose, onRemoveFromCart, onOrderPlaced }) => {
))}
-
ORDER SUMMARY
Cart Total ₹ {cartTotal.toLocaleString('en-IN')}
@@ -164,13 +202,10 @@ const Checkout = ({ cartItems, onClose, onRemoveFromCart, onOrderPlaced }) => {
setStep(1)}>BACK
-
- PLACE ORDER
-
+ PLACE ORDER
)}
-
diff --git a/frontend/src/components/Header.jsx b/frontend/src/components/Header.jsx
index 687145d..a4c6271 100644
--- a/frontend/src/components/Header.jsx
+++ b/frontend/src/components/Header.jsx
@@ -1,28 +1,26 @@
-import React, { useState } from 'react';
-import { Search, ShoppingCart, Heart, User, Menu, X } from 'lucide-react';
+import { useState } from 'react';
+import { Search, ShoppingBag, Heart, User, X } from 'lucide-react';
-const Header = ({ onOpenOverlay, onNavigate, cartCount, wishlistCount, activeNav, loggedInUser, onLogout, onOpenAccount, searchQuery, onSearch }) => {
- const [isSearchFocused, setIsSearchFocused] = useState(false);
+const Header = ({ onOpenOverlay, onNavigate, cartCount, wishlistCount, activeNav, loggedInUser, onOpenAccount, searchQuery, onSearch }) => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
- const [showUserMenu, setShowUserMenu] = useState(false);
return (
-
+
-
-
setIsMobileMenuOpen(!isMobileMenuOpen)}
- >
- {isMobileMenuOpen ? : }
-
-
onNavigate('home')} style={{ cursor: 'pointer' }}>
- Z appify
-
+
onNavigate('home')} style={{ cursor: 'pointer' }}>
+ Z appify
+
+ { onNavigate('home'); setIsMobileMenuOpen(false); }}
+ >
+ ALL
+
+
-
+
onSearch(e.target.value)}
- onFocus={() => setIsSearchFocused(true)}
- onBlur={() => setIsSearchFocused(false)}
/>
{searchQuery && (
- onSearch('')}>✕
+ onSearch('')}>
)}
+
onOpenOverlay('wishlist')}>
+
+ {wishlistCount > 0 && {wishlistCount} }
+
+
onOpenOverlay('cart')}>
+
+ {cartCount > 0 && {cartCount} }
+
{loggedInUser ? (
-
+
) : (
@@ -68,14 +76,6 @@ const Header = ({ onOpenOverlay, onNavigate, cartCount, wishlistCount, activeNav
)}
-
onOpenOverlay('wishlist')}>
-
- {wishlistCount > 0 && {wishlistCount} }
-
-
onOpenOverlay('cart')}>
-
- {cartCount > 0 && {cartCount} }
-
diff --git a/frontend/src/components/ProductCard.jsx b/frontend/src/components/ProductCard.jsx
index e413e33..ae62a7b 100644
--- a/frontend/src/components/ProductCard.jsx
+++ b/frontend/src/components/ProductCard.jsx
@@ -1,4 +1,3 @@
-import React from 'react';
import { Heart, TrendingUp } from 'lucide-react';
import { motion } from 'framer-motion';
diff --git a/frontend/src/components/ProductDetail.jsx b/frontend/src/components/ProductDetail.jsx
index b9d65d6..45f9529 100644
--- a/frontend/src/components/ProductDetail.jsx
+++ b/frontend/src/components/ProductDetail.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { ArrowLeft, ShoppingBag, Heart, Share2, ShieldCheck, X } from 'lucide-react';
@@ -17,10 +17,7 @@ const ProductDetail = ({ product, onBack, onAddToCart, onToggleWishlist, isWishl
const sizes = ['7', '8', '9', '10', '11'];
const handleAddToCart = () => {
- if (!selectedSize) {
- alert('Please select a size first');
- return;
- }
+ if (!selectedSize) { alert('Please select a size first'); return; }
onAddToCart(product, selectedSize);
alert(`${product.name} (UK ${selectedSize}) added to cart!`);
};
@@ -46,7 +43,6 @@ const ProductDetail = ({ product, onBack, onAddToCart, onToggleWishlist, isWishl
{product.brand}
{product.name}
{product.category}
-
₹ {product.price.toLocaleString('en-IN')}
diff --git a/frontend/src/components/ProductGrid.jsx b/frontend/src/components/ProductGrid.jsx
index e04dab5..c7cecf8 100644
--- a/frontend/src/components/ProductGrid.jsx
+++ b/frontend/src/components/ProductGrid.jsx
@@ -1,21 +1,8 @@
-import React from 'react';
import ProductCard from './ProductCard';
-const ProductGrid = ({ products, onProductClick, sortOption, onSortChange, onToggleWishlist, isWishlisted }) => {
+const ProductGrid = ({ products, onProductClick, onToggleWishlist, isWishlisted }) => {
return (
-
-
-
- onSortChange(e.target.value)}>
- Select Sorting Options
- Price: Low to High
- Price: High to Low
- New Arrivals
-
-
-
-
{products.map((product) => (
No products found match the selected filters.
- Try adjusting your categories or themes.
+ Try adjusting your categories.
)}
diff --git a/frontend/src/components/Sidebar.jsx b/frontend/src/components/Sidebar.jsx
index 32d81a7..d7281f6 100644
--- a/frontend/src/components/Sidebar.jsx
+++ b/frontend/src/components/Sidebar.jsx
@@ -1,24 +1,18 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
import { ChevronDown, Filter } from 'lucide-react';
const categories = [
- 'Men Low Top Sneakers',
- 'Men High Top Sneakers',
- 'Men Mid Top Sneakers',
- 'Men Mules',
- 'Men Clogs'
+ 'Running',
+ 'Lifestyle',
+ 'Basketball',
+ 'Training & Gym',
+ 'Jordan',
+ 'Skateboarding',
+ 'Walking',
];
-const themes = [
- 'Urban Tech',
- 'Retro Classic',
- 'Cyber Sport',
- 'Minimalist'
-];
-
-const Sidebar = ({ selectedCategories, selectedThemes, onToggleFilter }) => {
+const Sidebar = ({ selectedCategories, onToggleFilter }) => {
const [isCategoriesOpen, setIsCategoriesOpen] = useState(true);
- const [isThemesOpen, setIsThemesOpen] = useState(true);
return (
@@ -28,14 +22,14 @@ const Sidebar = ({ selectedCategories, selectedThemes, onToggleFilter }) => {
-
setIsCategoriesOpen(!isCategoriesOpen)}
>
CATEGORIES
-
{isCategoriesOpen && (
@@ -43,8 +37,8 @@ const Sidebar = ({ selectedCategories, selectedThemes, onToggleFilter }) => {
{categories.map((cat, i) => (
- onToggleFilter(cat, 'category')}
/>
@@ -56,38 +50,7 @@ const Sidebar = ({ selectedCategories, selectedThemes, onToggleFilter }) => {
)}
-
-
-
setIsThemesOpen(!isThemesOpen)}
- >
-
THEMES
-
-
- {isThemesOpen && (
-
- )}
-
-
-
+
);
};
diff --git a/frontend/src/data/products.js b/frontend/src/data/products.js
index 3b4c1ee..cff34d9 100644
--- a/frontend/src/data/products.js
+++ b/frontend/src/data/products.js
@@ -1,488 +1,603 @@
export const ALL_PRODUCTS = [
+ {
+ id: 105,
+ name: "Nike Journey Run",
+ brand: "NIKE",
+ category: "Running",
+ price: 6796,
+ image: "/shoes/Nike Journey Run.jpg",
+ description:
+ "Perfect for daily jogs, these shoes offer a smooth ride and great cushioning for every mile.",
+ },
+ {
+ id: 106,
+ name: "Nike Revolution 8 EasyOn",
+ brand: "NIKE",
+ category: "Running",
+ price: 4295,
+ image: "/shoes/Nike Revolution 8 EasyOn.jpg",
+ description:
+ "Designed for convenience with an EasyOn entry system, making it simple to get out and start running.",
+ },
+ {
+ id: 107,
+ name: "Nike Air Max Alpha Trainer 6",
+ brand: "NIKE",
+ category: "Training & Gym",
+ price: 8495,
+ image: "/shoes/Nike Air Max Alpha Trainer 6.jpg",
+ description:
+ "Stability meets style in this trainer, perfect for heavy lifts and explosive gym movements.",
+ },
+ {
+ id: 108,
+ name: "Nike Winflo 11",
+ brand: "NIKE",
+ category: "Running",
+ price: 6956,
+ image: "/shoes/Nike Winflo 11.jpg",
+ description:
+ "A reliable road runner with updated cushioning that provides a balanced and energetic feel.",
+ },
+ {
+ id: 109,
+ name: "Nike Quest 6",
+ brand: "NIKE",
+ category: "Running",
+ price: 7095,
+ image: "/shoes/Nike Quest 6.jpg",
+ description:
+ "Built for the long road ahead, offering a breathable mesh upper and durable traction.",
+ },
+ {
+ id: 110,
+ name: "Nike Killshot 2 Leather Premium",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 9195,
+ image: "/shoes/Nike Killshot 2 Leather Premium.jpg",
+ description:
+ "Inspired by classic tennis shoes, this leather premium edition brings a retro look to your street style.",
+ },
+ {
+ id: 111,
+ name: "LeBron Witness IX EP",
+ brand: "NIKE",
+ category: "Basketball",
+ price: 6956,
+ image: "/shoes/LeBron Witness IX EP.jpg",
+ description:
+ "Unleash your inner athlete with LeBron's signature performance and lockdown support on the court.",
+ },
+ {
+ id: 112,
+ name: "Nike Air Max Excee",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 7495,
+ image: "/shoes/Nike Air Max Excee.jpg",
+ description:
+ "Featuring a visible Air unit, these sneakers blend iconic design with modern everyday comfort.",
+ },
+ {
+ id: 113,
+ name: "Nike Downshifter 14",
+ brand: "NIKE",
+ category: "Running",
+ price: 4895,
+ image: "/shoes/Nike Downshifter 14.jpg",
+ description:
+ "An entry-level runner that doesn't compromise on support, ideal for beginners starting their journey.",
+ },
+ {
+ id: 114,
+ name: "Nike Air Max Dn Roam",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 16995,
+ image: "/shoes/Nike Air Max Dn Roam.jpg",
+ description:
+ "High-end style meets revolutionary Air technology in this bold, futuristic lifestyle sneaker.",
+ },
+ {
+ id: 115,
+ name: "Nike SB Zoom Blazer Low Pro GT",
+ brand: "NIKE",
+ category: "Skateboarding",
+ price: 6795,
+ image: "/shoes/Nike SB Zoom Blazer Low Pro GT.jpg",
+ description:
+ "Engineered for skaters, this low-profile shoe offers exceptional boardfeel and durability.",
+ },
+ {
+ id: 116,
+ name: "Air Jordan 1 Low SE",
+ brand: "NIKE",
+ category: "Jordan",
+ price: 11495,
+ image: "/shoes/Air Jordan 1 Low SE.jpg",
+ description:
+ "The timeless AJ1 look in a low-top silhouette, featuring premium materials and iconic colorways.",
+ },
+ {
+ id: 117,
+ name: "Nike Killshot 2 Leather",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 7995,
+ image: "/shoes/Nike Killshot 2 Leather.jpg",
+ description:
+ "A versatile wardrobe staple that pairs perfectly with jeans, offering a clean and polished finish.",
+ },
+ {
+ id: 118,
+ name: "Nike Run Defy",
+ brand: "NIKE",
+ category: "Running",
+ price: 3196,
+ image: "/shoes/Nike Run Defy.jpg",
+ description:
+ "Budget-friendly performance shoe that delivers comfort for short runs and daily wear.",
+ },
+ {
+ id: 119,
+ name: "Nike Promina",
+ brand: "NIKE",
+ category: "Walking",
+ price: 3996,
+ image: "/shoes/Nike Promina.jpg",
+ description:
+ "Specifically designed for walking, ensuring all-day comfort with a soft, cushioned midsole.",
+ },
+ {
+ id: 120,
+ name: "Nike P-6000",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 9695,
+ image: "/shoes/Nike P-6000.jpg",
+ description:
+ "A mash-up of past Pegasus sneakers, this model offers a ventilated, breathable and comfortable Y2K vibe.",
+ },
+ {
+ id: 121,
+ name: "Nike Ava Rover",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 11895,
+ image: "/shoes/Nike Ava Rover.jpg",
+ description:
+ "A bold and unique silhouette that stands out in any crowd, perfect for fashion-forward enthusiasts.",
+ },
+ {
+ id: 122,
+ name: "Nike Free Metcon 6",
+ brand: "NIKE",
+ category: "Training & Gym",
+ price: 10795,
+ image: "/shoes/Nike Free Metcon 6.jpg",
+ description:
+ "Combines the flexibility of Nike Free with the stability of Metcon for a truly all-in-one workout shoe.",
+ },
+ {
+ id: 123,
+ name: "Air Jordan 1 Mid",
+ brand: "NIKE",
+ category: "Jordan",
+ price: 11495,
+ image: "/shoes/Air Jordan 1 Mid.jpg",
+ description:
+ "The classic mid-top legend remains a favorite, delivering heritage style and premium comfort.",
+ },
+ {
+ id: 124,
+ name: "Nike Air Max 270",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 13995,
+ image: "/shoes/Nike Air Max 270.jpg",
+ description:
+ "Boasting Nike's tallest heel bag yet, these sneakers offer a super-soft ride that feels as good as it looks.",
+ },
{
- id: 1,
- name: 'The Incredible Hulk',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Cyber Sport',
- price: 3799,
- image: '/shoes/shoe31.jpg',
- isTrending: true,
- description: 'Smash your limits with The Incredible Hulk High Tops. Featuring heavy-duty impact cushioning and gamma-green accents.'
- },
- {
- id: 2,
- name: 'Spider-Man: Spider Verse',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Cyber Sport',
- price: 3999,
- image: '/shoes/shoe2.jpg',
- isTrending: true,
- description: 'Step into the multiverse. These low-tops feature web-reactive textures, striking contrast colors, and an agile profile.'
- },
- {
- id: 3,
- name: 'Urban Blaze: Hawkins',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Urban Tech',
- price: 2599,
- image: '/shoes/shoe3.jpg',
- isTrending: false,
- description: 'Classic Hawkins energy. A vibrant design combining retro aesthetics with modern urban traction technology.'
- },
- {
- id: 4,
- name: 'Rovers: Batman',
- brand: 'ZAPPIFY',
- category: 'Men Slip-ons',
- theme: 'Minimalist',
- price: 3499,
- image: '/shoes/shoe4.jpg',
- isTrending: true,
- description: 'Lounge like a Dark Knight. Premium dark synthetic leather construction designed for ultimate comfort and stealth.'
- },
- {
- id: 5,
- name: 'Urban Blaze: Blue Moon',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Retro Classic',
- price: 2599,
- image: '/shoes/shoe5.jpg',
- isTrending: false,
- description: 'A striking blue moon aesthetic. Features reinforced stitching and maximum breathability for everyday street wear.'
- },
- {
- id: 6,
- name: 'Deadpool: 2.0',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Urban Tech',
- price: 2599,
- image: '/shoes/shoe6.jpg',
- isTrending: true,
- description: 'Maximum effort for your feet. Deep red canvas panels mixed with anti-abrasion overlays for the merc on the move.'
- },
- {
- id: 7,
- name: 'Urban Blaze: Cappuccino',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Minimalist',
- price: 2599,
- image: '/shoes/shoe7.jpg',
- isTrending: false,
- description: 'Rich earth tones and creamy accents. A laid-back silhouette built on top of a highly responsive foam midsole.'
- },
- {
- id: 8,
- name: 'Milano: Walnut',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Retro Classic',
- price: 2599,
- image: '/shoes/shoe8.jpg',
- isTrending: false,
- description: 'Sleek Italian-inspired lines. The Milano Walnut blends casual elegance with a durable, long-lasting rubber cupsole.'
- },
- {
- id: 9,
- name: 'Star Wars: Mandalorian',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Cyber Sport',
- price: 3199,
- image: '/shoes/shoe9.jpg',
- isTrending: true,
- description: 'This is the way. Featuring heavy-duty Beskar-inspired metallic finishes and a rugged terrain grip.'
- },
- {
- id: 10,
- name: 'Hydros: The Dark Knight',
- brand: 'ZAPPIFY',
- category: 'Men Clogs',
- theme: 'Minimalist',
- price: 1499,
- image: '/shoes/shoe10.jpg',
- isTrending: true,
- description: 'Waterproof, ultra-light, and effortlessly stealthy. The ultimate companion for quick missions or total relaxation.'
- },
- {
- id: 11,
- name: 'Captain America: First Avenger',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Retro Classic',
- price: 3699,
- image: '/shoes/shoe2.jpg',
- isTrending: true,
- description: 'The shield of the streets. Vintage combat styling paired with highly durable shock-absorbent outsoles.'
- },
- {
- id: 12,
- name: 'Black Panther: Wakanda Forever',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Urban Tech',
- price: 3899,
- image: '/shoes/shoe4.jpg',
- isTrending: true,
- description: 'Sleek, powerful, agile. Built with ultra-responsive vibranium-inspired bounce technology for unmatched speed.'
- },
- {
- id: 13,
- name: 'Venom: Maximum Carnage',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Cyber Sport',
- price: 3499,
- image: '/shoes/shoe3.jpg',
- isTrending: false,
- description: 'Unleash your inner symbiote. Aggressive tread patterns and dark red webbing make this sneaker a force of nature.'
- },
- {
- id: 14,
- name: 'Iron Man: Mark LXXXV',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Cyber Sport',
- price: 4299,
- image: '/shoes/shoe6.jpg',
- isTrending: true,
- description: 'I am Iron Man. Premium nano-tech styling with high-gloss metallic red and gold accents.'
- },
- {
- id: 15,
- name: 'Urban Blaze: Cappuccino',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Urban Tech',
- price: 2599,
- image: '/shoes/shoe15.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 16,
- name: 'Milano: Walnut',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Cyber Sport',
- price: 2599,
- image: '/shoes/shoe16.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 17,
- name: 'Star Wars: Mandalorian',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Urban Tech',
- price: 3199,
- image: '/shoes/shoe17.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 18,
- name: 'Hydros: The Dark Knight',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Minimalist',
- price: 1499,
- image: '/shoes/shoe18.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 19,
- name: 'Velocity: Silver',
- brand: 'ZAPPIFY',
- category: 'Men Slip-ons',
- theme: 'Cyber Sport',
- price: 2599,
- image: '/shoes/shoe19.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 20,
- name: 'Urban Blaze: Black',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Minimalist',
- price: 2599,
- image: '/shoes/shoe20.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 21,
- name: 'Urban Blaze: Mafia',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Cyber Sport',
- price: 2599,
- image: '/shoes/shoe21.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 22,
- name: 'Urban Blaze: Green Lab',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Urban Tech',
- price: 1999,
- image: '/shoes/shoe22.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 23,
- name: 'Black Panther: Warrior',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Urban Tech',
- price: 3499,
- image: '/shoes/shoe23.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 24,
- name: 'Velocity: Scarlet',
- brand: 'ZAPPIFY',
- category: 'Men Slip-ons',
- theme: 'Cyber Sport',
- price: 2599,
- image: '/shoes/shoe24.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 25,
- name: 'Kanso V2: Beige',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Retro Classic',
- price: 2599,
- image: '/shoes/shoe25.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 26,
- name: 'Kanso ZE: Black',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Urban Tech',
- price: 2599,
- image: '/shoes/shoe26.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 27,
- name: 'Fumes: Toxic',
- brand: 'ZAPPIFY',
- category: 'Men Slip-ons',
- theme: 'Cyber Sport',
- price: 17992249450,
- image: '/shoes/shoe27.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 28,
- name: 'UBZ Ascend: Mocha',
- brand: 'ZAPPIFY',
- category: 'Men Slip-ons',
- theme: 'Urban Tech',
- price: 3599,
- image: '/shoes/shoe28.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 29,
- name: 'MACH 1',
- brand: 'ZAPPIFY',
- category: 'Men Slip-ons',
- theme: 'Retro Classic',
- price: 3499,
- image: '/shoes/shoe29.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 30,
- name: 'Naruto Shippuden: Sasuke',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Urban Tech',
- price: 32993599300,
- image: '/shoes/shoe30.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 31,
- name: 'Kanso V2: Sapphire',
- brand: 'ZAPPIFY',
- category: 'Men Clogs',
- theme: 'Urban Tech',
- price: 2599,
- image: '/shoes/shoe31.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 32,
- name: 'UBZ Ascend: Oasis',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Cyber Sport',
- price: 3499,
- image: '/shoes/shoe32.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 33,
- name: 'MACH 3',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Retro Classic',
- price: 3499,
- image: '/shoes/shoe33.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 34,
- name: 'Daredevil: Hell\'s Knight',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Cyber Sport',
- price: 3799,
- image: '/shoes/shoe34.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 35,
- name: 'Top Gun: Maverick Kicks',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Cyber Sport',
- price: 259936991100,
- image: '/shoes/shoe35.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 36,
- name: 'Mortal Kombat: Scorpion',
- brand: 'ZAPPIFY',
- category: 'Men Slip-ons',
- theme: 'Retro Classic',
- price: 3499,
- image: '/shoes/shoe36.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 37,
- name: 'Urban Blaze: Butter',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Urban Tech',
- price: 2599,
- image: '/shoes/shoe37.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 38,
- name: 'Kanso V2: Emerald',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Cyber Sport',
- price: 2599,
- image: '/shoes/shoe38.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 39,
- name: 'Souled: Outlast',
- brand: 'ZAPPIFY',
- category: 'Men Clogs',
- theme: 'Retro Classic',
- price: 2499,
- image: '/shoes/shoe39.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 40,
- name: 'Mortal Kombat: Sub Zero',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Urban Tech',
- price: 3499,
- image: '/shoes/shoe40.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 41,
- name: 'Rovers: Black Panther',
- brand: 'ZAPPIFY',
- category: 'Men Mid Top Sneakers',
- theme: 'Urban Tech',
- price: 3499,
- image: '/shoes/shoe41.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 42,
- name: 'Rovers: Deadpool',
- brand: 'ZAPPIFY',
- category: 'Men High Top Sneakers',
- theme: 'Urban Tech',
- price: 3499,
- image: '/shoes/shoe42.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 43,
- name: 'Trailz: Ember',
- brand: 'ZAPPIFY',
- category: 'Men Clogs',
- theme: 'Cyber Sport',
- price: 25992999400,
- image: '/shoes/shoe43.jpg',
- isTrending: true,
- description: 'Exclusive release from The Souled Store collection.'
- },
- {
- id: 44,
- name: 'UBZ Ascend: Black',
- brand: 'ZAPPIFY',
- category: 'Men Low Top Sneakers',
- theme: 'Retro Classic',
- price: 3299,
- image: '/shoes/shoe44.jpg',
- isTrending: false,
- description: 'Exclusive release from The Souled Store collection.'
- }
+ id: 201,
+ name: "Men's Street Runner Pro",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 7495,
+ image: "/shoes/shoe1.jpg",
+ description: "Lightweight and responsive, built for men who push the pace on every run.",
+ },
+ {
+ id: 202,
+ name: "Men's Urban Glide",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 8295,
+ image: "/shoes/shoe2.jpg",
+ description: "Sleek silhouette with premium cushioning, perfect for city streets.",
+ },
+ {
+ id: 203,
+ name: "Men's Court Dominator",
+ brand: "NIKE",
+ category: "Basketball",
+ gender: "MEN",
+ price: 9995,
+ image: "/shoes/shoe3.jpg",
+ description: "Ankle support and grip engineered for explosive court performance.",
+ },
+ {
+ id: 204,
+ name: "Men's Trail Blazer",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 8795,
+ image: "/shoes/shoe4.jpg",
+ description: "Rugged outsole and cushioned midsole for off-road adventures.",
+ },
+ {
+ id: 205,
+ name: "Men's Classic Low",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 6495,
+ image: "/shoes/shoe5.jpg",
+ description: "Timeless low-top design that pairs with any outfit effortlessly.",
+ },
+ {
+ id: 206,
+ name: "Men's Power Lift",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 9295,
+ image: "/shoes/shoe6.jpg",
+ description: "Flat, stable base designed for heavy lifts and gym sessions.",
+ },
+ {
+ id: 207,
+ name: "Men's Skate Edge",
+ brand: "NIKE",
+ category: "Skateboarding",
+ gender: "MEN",
+ price: 7195,
+ image: "/shoes/shoe7.jpg",
+ description: "Durable canvas upper with vulcanized sole for superior boardfeel.",
+ },
+ {
+ id: 208,
+ name: "Men's Air Cushion Max",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 12495,
+ image: "/shoes/shoe8.jpg",
+ description: "Max Air unit delivers all-day comfort with a bold, modern look.",
+ },
+ {
+ id: 209,
+ name: "Men's Sprint Elite",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 10995,
+ image: "/shoes/shoe9.jpg",
+ description: "Carbon-fiber inspired plate for explosive speed on race day.",
+ },
+ {
+ id: 210,
+ name: "Men's Retro High",
+ brand: "NIKE",
+ category: "Jordan",
+ gender: "MEN",
+ price: 13495,
+ image: "/shoes/shoe10.jpg",
+ description: "Heritage high-top silhouette with modern comfort upgrades.",
+ },
+ {
+ id: 211,
+ name: "Men's Flex Trainer",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 7895,
+ image: "/shoes/shoe15.jpg",
+ description: "Flexible grooves and breathable mesh for dynamic training sessions.",
+ },
+ {
+ id: 212,
+ name: "Men's Walk Comfort",
+ brand: "NIKE",
+ category: "Walking",
+ gender: "MEN",
+ price: 5495,
+ image: "/shoes/shoe16.jpg",
+ description: "Plush foam midsole and wide toe box for all-day walking comfort.",
+ },
+ {
+ id: 213,
+ name: "Men's Hoop Legend",
+ brand: "NIKE",
+ category: "Basketball",
+ gender: "MEN",
+ price: 11295,
+ image: "/shoes/shoe17.jpg",
+ description: "Zoom Air cushioning and herringbone traction for elite court play.",
+ },
+ {
+ id: 214,
+ name: "Men's Everyday Runner",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 5995,
+ image: "/shoes/shoe18.jpg",
+ description: "Reliable daily trainer with responsive foam and breathable upper.",
+ },
+ {
+ id: 215,
+ name: "Men's Street Classic",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 8995,
+ image: "/shoes/shoe19.jpg",
+ description: "Clean lines and premium leather for a polished street look.",
+ },
+ {
+ id: 216,
+ name: "Men's Zoom Speed",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 9495,
+ image: "/shoes/shoe20.jpg",
+ description: "Zoom Air unit in the forefoot for a snappy, fast-paced ride.",
+ },
+ {
+ id: 217,
+ name: "Men's Board King",
+ brand: "NIKE",
+ category: "Skateboarding",
+ gender: "MEN",
+ price: 6995,
+ image: "/shoes/shoe21.jpg",
+ description: "Reinforced toe cap and padded collar for skate park sessions.",
+ },
+ {
+ id: 218,
+ name: "Men's Gym Beast",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 10295,
+ image: "/shoes/shoe22.jpg",
+ description: "Wide platform and locked-down fit for heavy compound movements.",
+ },
+ {
+ id: 219,
+ name: "Men's Air Retro 90",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 11995,
+ image: "/shoes/shoe23.jpg",
+ description: "90s-inspired design with modern Air cushioning for everyday wear.",
+ },
+ {
+ id: 220,
+ name: "Men's Jordan Legacy",
+ brand: "NIKE",
+ category: "Jordan",
+ gender: "MEN",
+ price: 14995,
+ image: "/shoes/shoe24.jpg",
+ description: "Iconic Jordan DNA with premium materials and heritage colorways.",
+ },
+ {
+ id: 221,
+ name: "Men's Long Run",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 8195,
+ image: "/shoes/shoe25.jpg",
+ description: "Extra cushioning and energy return for marathon-distance training.",
+ },
+ {
+ id: 222,
+ name: "Men's Low Rider",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 7295,
+ image: "/shoes/shoe26.jpg",
+ description: "Low-profile design with suede overlays for a premium casual look.",
+ },
+ {
+ id: 223,
+ name: "Men's Dunk Force",
+ brand: "NIKE",
+ category: "Basketball",
+ gender: "MEN",
+ price: 10495,
+ image: "/shoes/shoe27.jpg",
+ description: "Dunk-inspired silhouette with modern cushioning for on and off court.",
+ },
+ {
+ id: 224,
+ name: "Men's Cross Trainer",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 8695,
+ image: "/shoes/shoe28.jpg",
+ description: "Versatile trainer built for HIIT, agility drills, and gym work.",
+ },
+ {
+ id: 225,
+ name: "Men's Hike Ready",
+ brand: "NIKE",
+ category: "Walking",
+ gender: "MEN",
+ price: 9195,
+ image: "/shoes/shoe29.jpg",
+ description: "Grippy outsole and waterproof upper for light trail and urban hikes.",
+ },
+ {
+ id: 226,
+ name: "Men's Pegasus Next",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 11495,
+ image: "/shoes/shoe30.jpg",
+ description: "Next-gen Pegasus with React foam and wider fit for long-distance comfort.",
+ },
+ {
+ id: 227,
+ name: "Men's Skate Pro",
+ brand: "NIKE",
+ category: "Skateboarding",
+ gender: "MEN",
+ price: 7595,
+ image: "/shoes/shoe31.jpg",
+ description: "Pro-level skate shoe with Zoom Air for impact protection.",
+ },
+ {
+ id: 228,
+ name: "Men's Air Force Classic",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 10995,
+ image: "/shoes/shoe32.jpg",
+ description: "The all-time classic AF1 silhouette in a fresh men's colorway.",
+ },
+ {
+ id: 229,
+ name: "Men's React Infinity",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 13995,
+ image: "/shoes/shoe33.jpg",
+ description: "React foam and wide base designed to reduce injury risk on long runs.",
+ },
+ {
+ id: 230,
+ name: "Men's Jordan Flight",
+ brand: "NIKE",
+ category: "Jordan",
+ gender: "MEN",
+ price: 12995,
+ image: "/shoes/shoe34.jpg",
+ description: "Flight-inspired Jordan with lightweight upper and responsive cushioning.",
+ },
+ {
+ id: 231,
+ name: "Men's Metcon Power",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 11295,
+ image: "/shoes/shoe35.jpg",
+ description: "Metcon stability meets Free flexibility for the ultimate cross-training shoe.",
+ },
+ {
+ id: 232,
+ name: "Men's Blazer Mid",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 9495,
+ image: "/shoes/shoe36.jpg",
+ description: "Mid-top Blazer with vintage basketball DNA and everyday wearability.",
+ },
+ {
+ id: 233,
+ name: "Men's Vomero Plush",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 14495,
+ image: "/shoes/shoe37.jpg",
+ description: "Maximum cushioning Vomero for plush, comfortable long-distance runs.",
+ },
+ {
+ id: 234,
+ name: "Men's Court Vision",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 7995,
+ image: "/shoes/shoe38.jpg",
+ description: "Court-inspired low-top with clean leather upper for everyday style.",
+ },
+ {
+ id: 235,
+ name: "Men's Invincible 3",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 16995,
+ image: "/shoes/shoe39.jpg",
+ description: "Nike's most cushioned running shoe for recovery and easy-day runs.",
+ },
+ {
+ id: 236,
+ name: "Men's Alphafly Next",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 19995,
+ image: "/shoes/shoe40.jpg",
+ description: "Elite race-day shoe with ZoomX foam and carbon fiber plate.",
+ },
+ {
+ id: 237,
+ name: "Men's Dri-FIT Trainer",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 8495,
+ image: "/shoes/shoe41.jpg",
+ description: "Breathable Dri-FIT upper keeps feet cool during intense workouts.",
+ },
+ {
+ id: 238,
+ name: "Men's SB Nyjah",
+ brand: "NIKE",
+ category: "Skateboarding",
+ gender: "MEN",
+ price: 8995,
+ image: "/shoes/shoe42.jpg",
+ description: "Nyjah Huston's signature skate shoe with Zoom Air and durable build.",
+ },
+ {
+ id: 239,
+ name: "Men's Air Max 97",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 15995,
+ image: "/shoes/shoe43.jpg",
+ description: "Full-length Air unit and bullet-train inspired design for iconic style.",
+ },
+ {
+ id: 240,
+ name: "Men's Zoom Rival",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 6295,
+ image: "/shoes/shoe44.jpg",
+ description: "Track-inspired road runner with Zoom Air for competitive training.",
+ },
];
-
diff --git a/frontend/src/index.css b/frontend/src/index.css
index f071271..cc1c179 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -4,8 +4,6 @@
--brand-red: #FF3D00;
--brand-red-light: #FF5722;
--brand-red-dark: #D83100;
-
-
--deep-slate: #0F172A;
--slate-800: #1E293B;
--slate-700: #334155;
@@ -15,18 +13,13 @@
--slate-100: #F1F5F9;
--background: #F8FAFC;
--surface: #FFFFFF;
-
-
--glass-bg: rgba(255, 255, 255, 0.75);
--glass-border: rgba(255, 255, 255, 0.4);
--glass-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.07);
-
-
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
-
--transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--radius-sm: 8px;
--radius-md: 12px;
@@ -71,7 +64,6 @@ ul {
list-style: none;
}
-/* Glass Utility */
.glass {
background: var(--glass-bg);
backdrop-filter: blur(8px);
@@ -80,14 +72,12 @@ ul {
box-shadow: var(--glass-shadow);
}
-/* Container Utility */
.container {
max-width: 1400px;
margin: 0 auto;
padding: 0 2rem;
}
-/* Red Button Style */
.btn-primary {
background: var(--brand-red);
color: white;
@@ -106,7 +96,6 @@ ul {
box-shadow: 0 6px 20px rgba(255, 61, 0, 0.23);
}
-/* Responsive Grid */
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
@@ -118,699 +107,835 @@ ul {
.container {
padding: 0 1rem;
}
-
.product-grid {
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
gap: 1rem;
}
}
-
-/* --- Extracted Component Styles --- */
-
-/* Extracted from App.jsx */
.zappify-app {
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- background: var(--background);
- }
- .app-main { flex: 1; }
- .main-layout { width: 100%; position: relative; padding: 2rem 0; }
- .layout-split { display: flex; width: 100%; }
- .container-broad { max-width: 1600px; margin: 0 auto; padding: 0 2rem; width: 100%; }
- .zappify-footer { padding: 2rem 0; background: var(--slate-100); border-top: 1px solid var(--slate-200); margin-top: 2rem; }
- .footer-bottom { text-align: center; font-size: 0.85rem; color: var(--slate-600); font-weight: 500; }
- .grid-view { width: 100%; }
- .detail-view { width: 100%; padding: 2rem 0; }
- @media (max-width: 1024px) {
- .layout-split { flex-direction: column; }
- .container-broad { padding: 0 1rem; }
- }
-
-/* Extracted from App.jsx */
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ background: var(--background);
+}
+.app-main { flex: 1; }
+.main-layout { width: 100%; position: relative; padding: 2rem 0; }
+.layout-split { display: flex; width: 100%; }
+.container-broad { max-width: 1600px; margin: 0 auto; padding: 0 2rem; width: 100%; }
+.zappify-footer { padding: 2rem 0; background: var(--slate-100); border-top: 1px solid var(--slate-200); margin-top: 2rem; }
+.footer-bottom { text-align: center; font-size: 0.85rem; color: var(--slate-600); font-weight: 500; }
+.grid-view { width: 100%; }
+.detail-view { width: 100%; padding: 2rem 0; }
+@media (max-width: 600px) {
+ .layout-split { flex-direction: column; }
+ .container-broad { padding: 0 1rem; }
+}
+
.overlay-system {
- position: fixed;
- inset: 0;
- z-index: 2000;
- display: flex;
- justify-content: center;
- align-items: center;
- }
-
- .backdrop {
- position: absolute;
- inset: 0;
- background: rgba(15, 23, 42, 0.6);
- backdrop-filter: blur(4px);
- }
-
- .drawer {
- position: absolute;
- right: 0;
- top: 0;
- bottom: 0;
- width: 450px;
- background: white;
- box-shadow: -10px 0 30px rgba(0,0,0,0.1);
- display: flex;
- flex-direction: column;
- }
-
- .modal {
- position: relative;
- width: 420px;
- background: white;
- border-radius: var(--radius-lg);
- padding: 2.5rem;
- box-shadow: 0 20px 50px rgba(0,0,0,0.2);
- }
-
- .overlay-header, .modal-header {
- padding: 1.5rem 2rem;
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-bottom: 1px solid var(--slate-100);
- }
-
- .modal-header { border: none; padding: 0; justify-content: flex-end; }
-
- .overlay-header h3 {
- font-size: 1.1rem;
- letter-spacing: 2px;
- font-weight: 800;
- color: var(--deep-slate);
- }
-
- .close-btn {
- color: var(--slate-400);
- transition: 0.2s;
- background: none;
- border: none;
- cursor: pointer;
- }
-
- .close-btn:hover { color: var(--brand-red); }
-
- .overlay-content {
- padding: 0;
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- align-items: stretch;
- overflow-y: auto;
- }
-
- .overlay-content .empty-state {
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- padding: 2rem;
- }
-
- .empty-state {
- text-align: center;
- color: var(--slate-400);
- }
-
- .empty-state p { margin: 1.5rem 0 2rem; font-weight: 600; }
-
- .login-modal { text-align: center; }
- .user-icon-large { color: var(--brand-red); margin-bottom: 1rem; }
- .login-modal h2 { font-size: 2rem; color: var(--deep-slate); font-weight: 800; letter-spacing: -1px; }
- .login-modal p { color: var(--slate-500); margin-bottom: 2.5rem; font-weight: 500; }
-
- .auth-form { display: flex; flex-direction: column; gap: 1rem; }
- .auth-form input {
- height: 50px;
- border-radius: var(--radius-md);
- border: 1px solid var(--slate-200);
- padding: 0 1.5rem;
- font-size: 1rem;
- outline: none;
- transition: 0.3s;
- }
-
- .auth-form input:focus { border-color: var(--brand-red); }
- .auth-btn { height: 50px; justify-content: center; margin-top: 1rem; }
-
- .separator {
- margin: 1.5rem 0;
- border-bottom: 1px solid var(--slate-100);
- position: relative;
- }
-
- .separator span {
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- background: white;
- padding: 0 1rem;
- font-size: 0.75rem;
- color: var(--slate-400);
- font-weight: 700;
- }
-
- .google-btn { height: 50px; justify-content: center; }
-
- .auth-footer { margin-top: 2rem; border-top: 1px solid var(--slate-100); padding-top: 1.5rem; font-size: 0.9rem; }
- .auth-footer span { color: var(--brand-red); font-weight: 700; cursor: pointer; text-decoration: underline; }
-
- @media (max-width: 480px) {
- .drawer { width: 100%; }
- .modal { width: 90%; padding: 1.5rem; }
- }
-
-/* Extracted from components/Header.jsx */
+ position: fixed;
+ inset: 0;
+ z-index: 2000;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.backdrop {
+ position: absolute;
+ inset: 0;
+ background: rgba(15, 23, 42, 0.6);
+ backdrop-filter: blur(4px);
+}
+
+.drawer {
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 450px;
+ background: white;
+ box-shadow: -10px 0 30px rgba(0,0,0,0.1);
+ display: flex;
+ flex-direction: column;
+}
+
+.modal {
+ position: relative;
+ width: 420px;
+ background: white;
+ border-radius: var(--radius-lg);
+ padding: 2.5rem;
+ box-shadow: 0 20px 50px rgba(0,0,0,0.2);
+}
+
+.overlay-header, .modal-header {
+ padding: 1.5rem 2rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid var(--slate-100);
+}
+
+.modal-header { border: none; padding: 0; justify-content: flex-end; }
+
+.overlay-header h3 {
+ font-size: 1.1rem;
+ letter-spacing: 2px;
+ font-weight: 800;
+ color: var(--deep-slate);
+}
+
+.close-btn {
+ color: var(--slate-400);
+ transition: 0.2s;
+ background: none;
+ border: none;
+ cursor: pointer;
+}
+
+.close-btn:hover { color: var(--brand-red); }
+
+.overlay-content {
+ padding: 0;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: stretch;
+ overflow-y: auto;
+}
+
+.overlay-content .empty-state {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 2rem;
+}
+
+.empty-state {
+ text-align: center;
+ color: var(--slate-400);
+}
+
+.empty-state p { margin: 1.5rem 0 2rem; font-weight: 600; }
+
+.login-modal { text-align: center; }
+.user-icon-large { color: var(--brand-red); margin-bottom: 1rem; }
+.login-modal h2 { font-size: 2rem; color: var(--deep-slate); font-weight: 800; letter-spacing: -1px; }
+.login-modal p { color: var(--slate-500); margin-bottom: 2.5rem; font-weight: 500; }
+
+.auth-form { display: flex; flex-direction: column; gap: 1rem; }
+.auth-form input {
+ height: 50px;
+ border-radius: var(--radius-md);
+ border: 1px solid var(--slate-200);
+ padding: 0 1.5rem;
+ font-size: 1rem;
+ outline: none;
+ transition: 0.3s;
+}
+
+.auth-form input:focus { border-color: var(--brand-red); }
+.auth-btn { height: 50px; justify-content: center; margin-top: 1rem; }
+
+.separator {
+ margin: 1.5rem 0;
+ border-bottom: 1px solid var(--slate-100);
+ position: relative;
+}
+
+.separator span {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ background: white;
+ padding: 0 1rem;
+ font-size: 0.75rem;
+ color: var(--slate-400);
+ font-weight: 700;
+}
+
+.google-btn { height: 50px; justify-content: center; }
+
+.auth-footer { margin-top: 2rem; border-top: 1px solid var(--slate-100); padding-top: 1.5rem; font-size: 0.9rem; text-align: center; }
+.auth-footer span { color: var(--brand-red); font-weight: 700; cursor: pointer; text-decoration: underline; }
+
+@media (max-width: 480px) {
+ .drawer { width: 100%; }
+ .modal { width: 90%; padding: 1.5rem; }
+}
+
.sticky-header {
- position: sticky;
- top: 0;
- z-index: 1000;
- height: 80px;
- display: flex;
- align-items: center;
- transition: var(--transition-smooth);
- }
-
- .header-wrapper {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 2rem;
- }
-
- .logo-section {
- display: flex;
- align-items: center;
- gap: 2rem;
- }
-
- .brand-logo {
- font-family: 'Outfit', sans-serif;
- font-size: 2.2rem;
- font-weight: 800;
- color: var(--deep-slate);
- letter-spacing: -1.5px;
- }
-
- .logo-accent {
- color: var(--brand-red);
- }
-
- .nav-links {
- display: flex;
- gap: 2.5rem;
- list-style: none;
- }
-
- .nav-item {
- font-size: 1rem;
- font-weight: 700;
- color: var(--slate-600);
- position: relative;
- padding: 0.5rem 0;
- letter-spacing: 0.5px;
- background: none;
- border: none;
- cursor: pointer;
- transition: 0.3s;
- }
-
- .nav-item.active {
- color: var(--brand-red);
- }
-
- .nav-item.active::after {
- content: '';
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 3px;
- background: var(--brand-red);
- }
-
- .search-container {
- flex: 1;
- max-width: 450px;
- height: 48px;
- background: var(--slate-100);
- border-radius: var(--radius-full);
- display: flex;
- align-items: center;
- padding: 0 1.5rem;
- gap: 1rem;
- border: 1px solid transparent;
- transition: var(--transition-smooth);
- }
-
- .search-container.focused {
- background: white;
- border-color: var(--brand-red);
- box-shadow: 0 0 0 4px rgba(255, 61, 0, 0.1);
- }
-
- .search-icon {
- color: var(--slate-400);
- }
-
- .search-container input {
- width: 100%;
- border: none;
- background: transparent;
- outline: none;
- font-size: 1rem;
- color: var(--deep-slate);
- }
-
- .user-actions {
- display: flex;
- gap: 1rem;
- }
-
- .action-btn {
- position: relative;
- padding: 0.6rem;
- color: var(--slate-700);
- border-radius: var(--radius-sm);
- background: none;
- border: none;
- cursor: pointer;
- }
-
- .action-btn:hover {
- background: var(--slate-100);
- color: var(--brand-red);
- }
-
- .badge {
- position: absolute;
- top: 4px;
- right: 4px;
- width: 18px;
- height: 18px;
- font-size: 0.7rem;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 50%;
- color: white;
- font-weight: bold;
- background: var(--slate-700);
- }
-
- .mobile-toggle {
- display: none;
- background: none;
- border: none;
- cursor: pointer;
- }
-
- @media (max-width: 1024px) {
- .nav-links { display: none; }
- .search-container { display: none; }
- .mobile-toggle { display: block; }
- .brand-logo { font-size: 1.8rem; }
- }
-
-/* Extracted from components/Sidebar.jsx */
+ position: sticky;
+ top: 0;
+ z-index: 1000;
+ background: #ffffff;
+ height: 80px;
+ display: flex;
+ align-items: center;
+ border-bottom: 1px solid var(--slate-100);
+ transition: var(--transition-smooth);
+}
+
+.header-wrapper {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 2rem;
+}
+
+.brand-logo {
+ font-family: 'Outfit', sans-serif;
+ font-size: 2.2rem;
+ font-weight: 800;
+ color: var(--deep-slate);
+ letter-spacing: -1.5px;
+}
+
+.logo-accent {
+ color: var(--brand-red);
+}
+
+.nav-links {
+ display: flex;
+ gap: 2.5rem;
+ list-style: none;
+}
+
+.nav-item {
+ font-size: 1rem;
+ font-weight: 700;
+ color: var(--slate-600);
+ position: relative;
+ padding: 0.5rem 0;
+ letter-spacing: 0.5px;
+ background: none;
+ border: none;
+ cursor: pointer;
+ transition: 0.3s;
+}
+
+.nav-item.active {
+ color: var(--brand-red);
+}
+
+.nav-item.active::after {
+ content: '';
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 3px;
+ background: var(--brand-red);
+}
+
+.search-container {
+ flex: 1;
+ max-width: 450px;
+ height: 48px;
+ background: var(--slate-100);
+ border-radius: var(--radius-full);
+ display: flex;
+ align-items: center;
+ padding: 0 1.5rem;
+ gap: 1rem;
+ border: 1px solid transparent;
+ transition: var(--transition-smooth);
+}
+
+.search-container.focused {
+ background: white;
+ border-color: var(--brand-red);
+ box-shadow: 0 0 0 4px rgba(255, 61, 0, 0.1);
+}
+
+.search-icon {
+ color: var(--slate-400);
+}
+
+.search-container input {
+ width: 100%;
+ border: none;
+ background: transparent;
+ outline: none;
+ font-size: 1rem;
+ color: var(--deep-slate);
+}
+
+.user-actions {
+ display: flex;
+ gap: 1rem;
+}
+
+.action-btn {
+ position: relative;
+ padding: 0.6rem;
+ color: var(--slate-700);
+ border-radius: var(--radius-sm);
+ background: none;
+ border: none;
+ cursor: pointer;
+}
+
+.action-btn:hover {
+ background: var(--slate-100);
+ color: var(--brand-red);
+}
+
+.badge {
+ position: absolute;
+ top: 4px;
+ right: 4px;
+ width: 18px;
+ height: 18px;
+ font-size: 0.7rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ color: white;
+ font-weight: bold;
+ background: var(--slate-700);
+}
+
+.mobile-toggle {
+ display: none;
+ background: none;
+ border: none;
+ cursor: pointer;
+}
+
+@media (max-width: 1024px) {
+ .nav-links { display: none; }
+ .search-container { display: none; }
+ .mobile-toggle { display: block; }
+ .brand-logo { font-size: 1.8rem; }
+}
+
.sidebar {
- width: 320px;
- padding: 2.5rem 2rem;
- background: white;
- border-right: 1px solid var(--slate-200);
- height: calc(100vh - 80px);
- position: sticky;
- top: 80px;
- overflow-y: auto;
- scrollbar-width: thin;
- }
-
- .filter-header {
- display: flex;
- align-items: center;
- gap: 1rem;
- padding-bottom: 2rem;
- border-bottom: 1px solid var(--slate-100);
- margin-bottom: 2rem;
- }
-
- .filter-header h3 {
- font-size: 1.1rem;
- letter-spacing: 2px;
- color: var(--deep-slate);
- font-weight: 800;
- }
-
- .filter-section {
- margin-bottom: 3rem;
- }
-
- .section-title {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 1.5rem;
- cursor: pointer;
- user-select: none;
- }
-
- .section-title h4 {
- font-size: 0.95rem;
- color: var(--slate-800);
- font-weight: 800;
- letter-spacing: 1px;
- }
-
- .filter-list {
- display: flex;
- flex-direction: column;
- gap: 1rem;
- }
-
- .filter-item {
- display: flex;
- align-items: center;
- font-size: 0.95rem;
- color: var(--slate-700);
- font-weight: 500;
- cursor: pointer;
- transition: var(--transition-smooth);
- }
-
- .filter-item:hover {
- color: var(--brand-red);
- }
-
- .filter-item label {
- display: flex;
- align-items: center;
- gap: 1rem;
- cursor: pointer;
- flex: 1;
- }
-
- .filter-item input {
- display: none;
- }
-
- .checkbox-custom {
- width: 22px;
- height: 22px;
- border: 2px solid var(--slate-200);
- border-radius: 6px;
- position: relative;
- transition: var(--transition-smooth);
- background: var(--background);
- }
-
- .filter-item input:checked + .checkbox-custom {
- background: var(--brand-red);
- border-color: var(--brand-red);
- box-shadow: 0 0 0 3px rgba(255, 61, 0, 0.1);
- }
-
- .filter-item input:checked + .checkbox-custom::after {
- content: '✓';
- position: absolute;
- color: white;
- font-size: 14px;
- font-weight: 900;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- }
-
- .item-name {
- line-height: 1.4;
- font-weight: 600;
- }
-
- @media (max-width: 1024px) {
- .sidebar { display: none; }
- }
-
-/* Extracted from components/ProductGrid.jsx */
+ width: 320px;
+ padding: 2.5rem 2rem;
+ background: white;
+ border-right: 1px solid var(--slate-200);
+ height: calc(100vh - 80px);
+ position: sticky;
+ top: 80px;
+ overflow-y: auto;
+ scrollbar-width: thin;
+}
+
+.filter-header {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ padding-bottom: 2rem;
+ border-bottom: 1px solid var(--slate-100);
+ margin-bottom: 2rem;
+}
+
+.filter-header h3 {
+ font-size: 1.1rem;
+ letter-spacing: 2px;
+ color: var(--deep-slate);
+ font-weight: 800;
+}
+
+.filter-section {
+ margin-bottom: 3rem;
+}
+
+.section-title {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 1.5rem;
+ cursor: pointer;
+ user-select: none;
+}
+
+.section-title h4 {
+ font-size: 0.95rem;
+ color: var(--slate-800);
+ font-weight: 800;
+ letter-spacing: 1px;
+}
+
+.filter-list {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+.filter-item {
+ display: flex;
+ align-items: center;
+ font-size: 0.95rem;
+ color: var(--slate-700);
+ font-weight: 500;
+ cursor: pointer;
+ transition: var(--transition-smooth);
+}
+
+.filter-item:hover {
+ color: var(--brand-red);
+}
+
+.filter-item label {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ cursor: pointer;
+ flex: 1;
+}
+
+.filter-item input {
+ display: none;
+}
+
+.checkbox-custom {
+ width: 22px;
+ height: 22px;
+ border: 2px solid var(--slate-200);
+ border-radius: 6px;
+ position: relative;
+ transition: var(--transition-smooth);
+ background: var(--background);
+}
+
+.filter-item input:checked + .checkbox-custom {
+ background: var(--brand-red);
+ border-color: var(--brand-red);
+ box-shadow: 0 0 0 3px rgba(255, 61, 0, 0.1);
+}
+
+.filter-item input:checked + .checkbox-custom::after {
+ content: '✓';
+ position: absolute;
+ color: white;
+ font-size: 14px;
+ font-weight: 900;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+}
+
+.item-name {
+ line-height: 1.4;
+ font-weight: 600;
+}
+
+@media (max-width: 1024px) {
+ .sidebar { display: none; }
+}
+
.main-content {
- flex: 1;
- padding: 2.5rem 3rem;
- min-height: calc(100vh - 80px);
- background: var(--background);
- }
-
- .content-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 3rem;
- border-bottom: 1px solid var(--slate-100);
- padding-bottom: 1.5rem;
- }
-
- .breadcrumb {
- font-size: 0.9rem;
- color: var(--slate-400);
- font-weight: 600;
- letter-spacing: 0.5px;
- }
-
- .breadcrumb .count {
- color: var(--slate-700);
- font-weight: 800;
- margin-left: 0.5rem;
- }
-
- .sort-dropdown select {
- padding: 0.8rem 1.5rem;
- border: 1px solid var(--slate-200);
- border-radius: var(--radius-md);
- font-size: 0.9rem;
- background: white;
- color: var(--slate-700);
- font-weight: 600;
- outline: none;
- cursor: pointer;
- transition: var(--transition-smooth);
- }
-
- .sort-dropdown select:hover {
- border-color: var(--brand-red);
- }
-
- .product-grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
- gap: 3rem 2rem;
- }
-
- .no-products {
- text-align: center;
- padding: 10rem 0;
- color: var(--slate-400);
- }
-
- .no-products h3 {
- font-size: 1.5rem;
- color: var(--slate-600);
- margin-bottom: 1rem;
- }
-
- @media (max-width: 640px) {
- .product-grid {
- grid-template-columns: repeat(2, 1fr);
- gap: 1.5rem 1rem;
- }
-
- .main-content {
- padding: 1.5rem 1rem;
- }
-
- .content-header {
- flex-direction: column;
- align-items: flex-start;
- gap: 1rem;
- }
- }
-
-/* Extracted from components/ProductDetail.jsx */
+ flex: 1;
+ padding: 2.5rem 3rem;
+ min-height: calc(100vh - 80px);
+ background: var(--background);
+}
+
+.content-header {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ margin-bottom: 1.5rem;
+ border-bottom: 1px solid var(--slate-100);
+ padding-bottom: 1rem;
+}
+
+.sort-dropdown {
+ margin-left: auto;
+}
+
+.sort-dropdown select {
+ padding: 0.4rem 0.8rem;
+ border: 1px solid var(--slate-200);
+ border-radius: var(--radius-md);
+ font-size: 0.75rem;
+ background: white;
+ color: var(--slate-700);
+ font-weight: 600;
+ outline: none;
+ cursor: pointer;
+ transition: var(--transition-smooth);
+ width: fit-content;
+}
+
+.sort-dropdown select:hover {
+ border-color: var(--brand-red);
+}
+
+.product-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+ gap: 3rem 2rem;
+}
+
+.no-products {
+ text-align: center;
+ padding: 10rem 0;
+ color: var(--slate-400);
+}
+
+/* --- Hero Banner --- */
+.hero-banner {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: #000000;
+ border-radius: var(--radius-lg);
+ padding: 0.8rem 4rem;
+ margin-bottom: 2rem;
+ overflow: hidden;
+ position: relative;
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
+ min-height: 180px;
+}
+
+/* Removed Diagonal Overlay for Dark Theme */
+.hero-banner * {
+ z-index: 2;
+}
+
+.hero-content {
+ flex: 1.2;
+ z-index: 2;
+ position: relative;
+}
+
+.hero-tag {
+ color: #FF6B00;
+ font-weight: 800;
+ letter-spacing: 0.3em;
+ font-size: 0.85rem;
+ margin-bottom: 1rem;
+ text-transform: uppercase;
+}
+
+.hero-banner h1 {
+ font-size: 2.6rem;
+ font-weight: 800;
+ line-height: 1.1;
+ margin-bottom: 1.2rem;
+ color: #FFFFFF;
+ letter-spacing: -2px;
+}
+
+.hero-subtitle {
+ font-size: 1.1rem;
+ color: #94A3B8;
+ margin-bottom: 1.5rem;
+ max-width: 440px;
+ line-height: 1.4;
+}
+
+.hero-cta {
+ background: #FF6B00 !important;
+ color: white !important;
+ padding: 0.9rem 2.5rem !important;
+ font-size: 0.9rem !important;
+ font-weight: 800;
+ letter-spacing: 1px;
+ border-radius: 30px !important;
+ box-shadow: 0 10px 25px rgba(255, 107, 0, 0.4) !important;
+}
+
+.hero-image-box {
+ flex: 1;
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.hero-image-box img {
+ width: 90%;
+ max-width: none;
+ transform: rotate(-5deg) translateY(0);
+ filter: drop-shadow(0 30px 60px rgba(0,0,0,0.5));
+}
+
+.hero-glow {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 400px;
+ height: 400px;
+ background: radial-gradient(circle, var(--brand) 0%, transparent 70%);
+ filter: blur(80px);
+ opacity: 0.15;
+ z-index: -1;
+}
+
+.content-area {
+ flex: 1;
+ min-width: 0;
+}
+
+.nike-collection-header {
+ margin-bottom: 1.5rem;
+ padding: 1.5rem 2rem;
+ background: #000;
+ border-radius: var(--radius-lg);
+ color: white;
+}
+
+.nike-collection-header h2 {
+ font-size: 1.8rem;
+ font-weight: 900;
+ letter-spacing: -1px;
+ margin: 0.4rem 0 0.3rem;
+ color: white;
+}
+
+.nike-collection-header p {
+ color: #94A3B8;
+ font-size: 0.9rem;
+ margin: 0;
+}
+
+.back-to-home {
+ background: none;
+ border: none;
+ color: #FF6B00;
+ font-size: 0.85rem;
+ font-weight: 700;
+ cursor: pointer;
+ padding: 0;
+ margin-bottom: 0.5rem;
+ letter-spacing: 0.5px;
+}
+
+@media (max-width: 1200px) {
+ .hero-banner {
+ padding: 2rem;
+ }
+ .hero-image-box img {
+ width: 100%;
+ }
+}
+
+@media (max-width: 991px) {
+ .hero-banner {
+ flex-direction: column;
+ text-align: center;
+ padding: 4rem 2rem;
+ min-height: auto;
+ }
+ .hero-content {
+ margin-bottom: 4rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+ .hero-subtitle {
+ margin-left: auto;
+ margin-right: auto;
+ }
+ .hero-image-box img {
+ width: 100%;
+ transform: rotate(-5deg);
+ }
+}
+
+.no-products h3 {
+ font-size: 1.5rem;
+ color: var(--slate-600);
+ margin-bottom: 1rem;
+}
+
+@media (max-width: 640px) {
+ .product-grid {
+ grid-template-columns: repeat(2, 1fr);
+ gap: 1.5rem 1rem;
+ }
+ .main-content {
+ padding: 1.5rem 1rem;
+ }
+ .content-header {
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 1rem;
+ }
+}
+
.product-detail-container { animation: fadeIn 0.5s ease-out; }
- .back-btn { display: flex; align-items: center; gap: 0.5rem; color: var(--slate-400); font-weight: 700; margin-bottom: 2rem; font-size: 0.9rem; transition: 0.2s; background: none; border: none; cursor: pointer; }
- .back-btn:hover { color: var(--brand-red); }
-
- .detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4rem; }
- .image-display { background: white; border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-xl); aspect-ratio: 1/1; }
- .image-display img { width: 100%; height: 100%; object-fit: cover; }
-
- .brand-tag { font-size: 0.9rem; font-weight: 800; color: var(--brand-red); letter-spacing: 2px; }
- .product-title { font-size: 3rem; font-weight: 800; color: var(--deep-slate); margin: 0.5rem 0; line-height: 1.1; }
- .product-cat { font-size: 1.2rem; color: var(--slate-600); font-weight: 500; margin-bottom: 2rem; }
- .price-tag { font-size: 2.5rem; font-weight: 700; color: var(--deep-slate); margin-bottom: 2rem; font-family: 'Outfit'; }
-
- .description-box { padding: 1.5rem; background: var(--slate-100); border-radius: var(--radius-md); margin-bottom: 2.5rem; color: var(--slate-600); line-height: 1.6; font-size: 1.05rem; }
-
- .size-selection { margin-bottom: 3rem; }
- .section-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; }
- .section-head h3 { font-size: 0.9rem; font-weight: 800; color: var(--deep-slate); }
- .section-head span { font-size: 0.8rem; font-weight: 700; color: var(--brand-red); text-decoration: underline; cursor: pointer; }
-
- .sizes-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1rem; }
- .size-btn { height: 50px; border: 2px solid var(--slate-200); border-radius: var(--radius-sm); font-weight: 700; color: var(--slate-600); transition: 0.3s; background: white; cursor: pointer; }
- .size-btn:hover { border-color: var(--brand-red); color: var(--brand-red); }
- .size-btn.active { background: var(--brand-red); border-color: var(--brand-red); color: white; }
-
- .action-buttons { display: flex; gap: 1.5rem; margin-bottom: 3rem; }
- .add-to-cart-btn { flex: 2; height: 60px; font-size: 1.1rem; justify-content: center; }
- .wishlist-btn-large { flex: 1; border: 2px solid var(--slate-200); border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; gap: 0.75rem; font-weight: 700; color: var(--slate-700); transition: 0.3s; background: white; cursor: pointer; }
- .wishlist-btn-large:hover { border-color: var(--brand-red); color: var(--brand-red); }
-
- .trust-badges { display: flex; flex-direction: column; gap: 1rem; }
- .badge-item { display: flex; align-items: center; gap: 0.75rem; color: var(--slate-500); font-weight: 600; font-size: 0.9rem; }
-
- @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
-
- @media (max-width: 768px) {
- .detail-grid { grid-template-columns: 1fr; gap: 2rem; }
- .product-title { font-size: 2.2rem; }
- .price-tag { font-size: 2rem; }
- }
-
-/* Extracted from components/ProductCard.jsx */
+.back-btn { display: flex; align-items: center; gap: 0.5rem; color: var(--slate-400); font-weight: 700; margin-bottom: 2rem; font-size: 0.9rem; transition: 0.2s; background: none; border: none; cursor: pointer; }
+.back-btn:hover { color: var(--brand-red); }
+
+.detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4rem; }
+.image-display { background: white; border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-xl); aspect-ratio: 1/1; }
+.image-display img { width: 100%; height: 100%; object-fit: cover; }
+
+.brand-tag { font-size: 0.9rem; font-weight: 800; color: var(--brand-red); letter-spacing: 2px; }
+.product-title { font-size: 3rem; font-weight: 800; color: var(--deep-slate); margin: 0.5rem 0; line-height: 1.1; }
+.product-cat { font-size: 1.2rem; color: var(--slate-600); font-weight: 500; margin-bottom: 2rem; }
+.price-tag { font-size: 2.5rem; font-weight: 700; color: var(--deep-slate); margin-bottom: 2rem; font-family: 'Outfit'; }
+
+.description-box { padding: 1.5rem; background: var(--slate-100); border-radius: var(--radius-md); margin-bottom: 2.5rem; color: var(--slate-600); line-height: 1.6; font-size: 1.05rem; }
+
+.size-selection { margin-bottom: 3rem; }
+.section-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; }
+.section-head h3 { font-size: 0.9rem; font-weight: 800; color: var(--deep-slate); }
+.section-head span { font-size: 0.8rem; font-weight: 700; color: var(--brand-red); text-decoration: underline; cursor: pointer; }
+
+.sizes-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1rem; }
+.size-btn { height: 50px; border: 2px solid var(--slate-200); border-radius: var(--radius-sm); font-weight: 700; color: var(--slate-600); transition: 0.3s; background: white; cursor: pointer; }
+.size-btn:hover { border-color: var(--brand-red); color: var(--brand-red); }
+.size-btn.active { background: var(--brand-red); border-color: var(--brand-red); color: white; }
+
+.action-buttons { display: flex; gap: 1.5rem; margin-bottom: 3rem; }
+.add-to-cart-btn { flex: 2; height: 60px; font-size: 1.1rem; justify-content: center; }
+.wishlist-btn-large { flex: 1; border: 2px solid var(--slate-200); border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; gap: 0.75rem; font-weight: 700; color: var(--slate-700); transition: 0.3s; background: white; cursor: pointer; }
+.wishlist-btn-large:hover { border-color: var(--brand-red); color: var(--brand-red); }
+
+.trust-badges { display: flex; flex-direction: column; gap: 1rem; }
+.badge-item { display: flex; align-items: center; gap: 0.75rem; color: var(--slate-500); font-weight: 600; font-size: 0.9rem; }
+
+@keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
+
+@media (max-width: 768px) {
+ .detail-grid { grid-template-columns: 1fr; gap: 2rem; }
+ .product-title { font-size: 2.2rem; }
+ .price-tag { font-size: 2rem; }
+}
+
.product-card {
- background: white;
- border-radius: var(--radius-md);
- overflow: hidden;
- transition: var(--transition-smooth);
- cursor: pointer;
- position: relative;
- }
-
- .card-image-wrap {
- position: relative;
- aspect-ratio: 1/1;
- background: #f0f0f0;
- overflow: hidden;
- }
-
- .card-image-wrap img {
- width: 100%;
- height: 100%;
- object-fit: cover;
- transition: transform 0.6s cubic-bezier(0.33, 1, 0.68, 1);
- }
-
- .product-card:hover .card-image-wrap img {
- transform: scale(1.1);
- }
-
- .badge-trending {
- position: absolute;
- top: 12px;
- left: 12px;
- background: rgba(255, 61, 0, 0.9);
- backdrop-filter: blur(4px);
- color: white;
- padding: 4px 8px;
- border-radius: 4px;
- display: flex;
- align-items: center;
- gap: 4px;
- font-size: 0.7rem;
- font-weight: 700;
- text-transform: uppercase;
- z-index: 10;
- }
-
- .wishlist-overlay {
- position: absolute;
- top: 12px;
- right: 12px;
- width: 36px;
- height: 36px;
- border-radius: 50%;
- background: white;
- display: flex;
- align-items: center;
- justify-content: center;
- color: var(--slate-400);
- box-shadow: var(--shadow-sm);
- z-index: 10;
- transition: var(--transition-smooth);
- }
-
- .wishlist-overlay:hover {
- color: var(--brand-red);
- transform: scale(1.1);
- }
-
- .quick-add {
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- padding: 0.75rem;
- background: linear-gradient(to top, rgba(0,0,0,0.5), transparent);
- transform: translateY(100%);
- transition: var(--transition-smooth);
- display: flex;
- justify-content: center;
- }
-
- .product-card:hover .quick-add {
- transform: translateY(0);
- }
-
- .quick-add button {
- background: white;
- color: black;
- font-weight: 800;
- font-size: 0.75rem;
- padding: 0.6rem 1.2rem;
- border-radius: 4px;
- letter-spacing: 0.5px;
- }
-
- .card-info {
- padding: 1rem;
- }
-
- .brand {
- font-size: 0.7rem;
- text-transform: uppercase;
- letter-spacing: 1px;
- color: var(--slate-400);
- font-weight: 700;
- margin-bottom: 0.25rem;
- }
-
- .name {
- font-size: 1rem;
- color: var(--deep-slate);
- margin-bottom: 0.25rem;
- font-weight: 600;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
-
- .category {
- font-size: 0.85rem;
- color: var(--slate-600);
- margin-bottom: 0.75rem;
- }
-
- .price {
- font-weight: 700;
- font-size: 1.1rem;
- color: var(--deep-slate);
- font-family: 'Outfit', sans-serif;
- }
-
-/* --- App.css --- */
+ background: white;
+ border-radius: var(--radius-md);
+ overflow: hidden;
+ transition: var(--transition-smooth);
+ cursor: pointer;
+ position: relative;
+}
+
+.card-image-wrap {
+ position: relative;
+ aspect-ratio: 1/1;
+ background: #f0f0f0;
+ overflow: hidden;
+}
+
+.card-image-wrap img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ transition: transform 0.6s cubic-bezier(0.33, 1, 0.68, 1);
+}
+
+.product-card:hover .card-image-wrap img {
+ transform: scale(1.1);
+}
+
+.badge-trending {
+ position: absolute;
+ top: 12px;
+ left: 12px;
+ background: rgba(255, 61, 0, 0.9);
+ backdrop-filter: blur(4px);
+ color: white;
+ padding: 4px 8px;
+ border-radius: 4px;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ font-size: 0.7rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ z-index: 10;
+}
+
+.wishlist-overlay {
+ position: absolute;
+ top: 12px;
+ right: 12px;
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ background: white;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--slate-400);
+ box-shadow: var(--shadow-sm);
+ z-index: 10;
+ transition: var(--transition-smooth);
+}
+
+.wishlist-overlay:hover {
+ color: var(--brand-red);
+ transform: scale(1.1);
+}
+
+.quick-add {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ padding: 0.75rem;
+ background: linear-gradient(to top, rgba(0,0,0,0.5), transparent);
+ transform: translateY(100%);
+ transition: var(--transition-smooth);
+ display: flex;
+ justify-content: center;
+}
+
+.product-card:hover .quick-add {
+ transform: translateY(0);
+}
+
+.quick-add button {
+ background: white;
+ color: black;
+ font-weight: 800;
+ font-size: 0.75rem;
+ padding: 0.6rem 1.2rem;
+ border-radius: 4px;
+ letter-spacing: 0.5px;
+}
+
+.card-info {
+ padding: 1rem;
+}
+
+.brand {
+ font-size: 0.7rem;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ color: var(--slate-400);
+ font-weight: 700;
+ margin-bottom: 0.25rem;
+}
+
+.name {
+ font-size: 1rem;
+ color: var(--deep-slate);
+ margin-bottom: 0.25rem;
+ font-weight: 600;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.category {
+ font-size: 0.85rem;
+ color: var(--slate-600);
+ margin-bottom: 0.75rem;
+}
+
+.price {
+ font-weight: 700;
+ font-size: 1.1rem;
+ color: var(--deep-slate);
+ font-family: 'Outfit', sans-serif;
+}
+
.counter {
font-size: 16px;
padding: 5px 10px;
@@ -820,53 +945,47 @@ ul {
border: 2px solid transparent;
transition: border-color 0.3s;
margin-bottom: 24px;
-
- &:hover {
- border-color: var(--accent-border);
- }
- &:focus-visible {
- outline: 2px solid var(--accent);
- outline-offset: 2px;
- }
+}
+.counter:hover {
+ border-color: var(--accent-border);
+}
+.counter:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
}
.hero {
position: relative;
-
- .base,
- .framework,
- .vite {
- inset-inline: 0;
- margin: 0 auto;
- }
-
- .base {
- width: 170px;
- position: relative;
- z-index: 0;
- }
-
- .framework,
- .vite {
- position: absolute;
- }
-
- .framework {
- z-index: 1;
- top: 34px;
- height: 28px;
- transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
- scale(1.4);
- }
-
- .vite {
- z-index: 0;
- top: 107px;
- height: 26px;
- width: auto;
- transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
- scale(0.8);
- }
+}
+.hero .base,
+.hero .framework,
+.hero .vite {
+ inset-inline: 0;
+ margin: 0 auto;
+}
+.hero .base {
+ width: 170px;
+ position: relative;
+ z-index: 0;
+}
+.hero .framework,
+.hero .vite {
+ position: absolute;
+}
+.hero .framework {
+ z-index: 1;
+ top: 34px;
+ height: 28px;
+ transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
+ scale(1.4);
+}
+.hero .vite {
+ z-index: 0;
+ top: 107px;
+ height: 26px;
+ width: auto;
+ transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
+ scale(0.8);
}
#center {
@@ -876,8 +995,9 @@ ul {
place-content: center;
place-items: center;
flex-grow: 1;
-
- @media (max-width: 1024px) {
+}
+@media (max-width: 1024px) {
+ #center {
padding: 32px 20px 24px;
gap: 18px;
}
@@ -887,22 +1007,23 @@ ul {
display: flex;
border-top: 1px solid var(--border);
text-align: left;
-
- & > div {
- flex: 1 1 0;
- padding: 32px;
- @media (max-width: 1024px) {
- padding: 24px 20px;
- }
- }
-
- .icon {
- margin-bottom: 16px;
- width: 22px;
- height: 22px;
+}
+#next-steps > div {
+ flex: 1 1 0;
+ padding: 32px;
+}
+@media (max-width: 1024px) {
+ #next-steps > div {
+ padding: 24px 20px;
}
-
- @media (max-width: 1024px) {
+}
+#next-steps .icon {
+ margin-bottom: 16px;
+ width: 22px;
+ height: 22px;
+}
+@media (max-width: 1024px) {
+ #next-steps {
flex-direction: column;
text-align: center;
}
@@ -910,8 +1031,9 @@ ul {
#docs {
border-right: 1px solid var(--border);
-
- @media (max-width: 1024px) {
+}
+@media (max-width: 1024px) {
+ #docs {
border-right: none;
border-bottom: 1px solid var(--border);
}
@@ -923,53 +1045,51 @@ ul {
display: flex;
gap: 8px;
margin: 32px 0 0;
-
- .logo {
- height: 18px;
- }
-
- a {
- color: var(--text-h);
- font-size: 16px;
- border-radius: 6px;
- background: var(--social-bg);
- display: flex;
- padding: 6px 12px;
- align-items: center;
- gap: 8px;
- text-decoration: none;
- transition: box-shadow 0.3s;
-
- &:hover {
- box-shadow: var(--shadow);
- }
- .button-icon {
- height: 18px;
- width: 18px;
- }
- }
-
- @media (max-width: 1024px) {
+}
+#next-steps ul .logo {
+ height: 18px;
+}
+#next-steps ul a {
+ color: var(--text-h);
+ font-size: 16px;
+ border-radius: 6px;
+ background: var(--social-bg);
+ display: flex;
+ padding: 6px 12px;
+ align-items: center;
+ gap: 8px;
+ text-decoration: none;
+ transition: box-shadow 0.3s;
+}
+#next-steps ul a:hover {
+ box-shadow: var(--shadow);
+}
+#next-steps ul a .button-icon {
+ height: 18px;
+ width: 18px;
+}
+@media (max-width: 1024px) {
+ #next-steps ul {
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
-
- li {
- flex: 1 1 calc(50% - 8px);
- }
-
- a {
- width: 100%;
- justify-content: center;
- box-sizing: border-box;
- }
+ }
+ #next-steps ul li {
+ flex: 1 1 calc(50% - 8px);
+ }
+ #next-steps ul a {
+ width: 100%;
+ justify-content: center;
+ box-sizing: border-box;
}
}
#spacer {
height: 88px;
border-top: 1px solid var(--border);
- @media (max-width: 1024px) {
+}
+@media (max-width: 1024px) {
+ #spacer {
height: 48px;
}
}
@@ -977,26 +1097,23 @@ ul {
.ticks {
position: relative;
width: 100%;
-
- &::before,
- &::after {
- content: '';
- position: absolute;
- top: -4.5px;
- border: 5px solid transparent;
- }
-
- &::before {
- left: 0;
- border-left-color: var(--border);
- }
- &::after {
- right: 0;
- border-right-color: var(--border);
- }
+}
+.ticks::before,
+.ticks::after {
+ content: '';
+ position: absolute;
+ top: -4.5px;
+ border: 5px solid transparent;
+}
+.ticks::before {
+ left: 0;
+ border-left-color: var(--border);
+}
+.ticks::after {
+ right: 0;
+ border-right-color: var(--border);
}
-/* Cart & Wishlist Drawer Items */
.cart-items { display: flex; flex-direction: column; gap: 0; padding: 0 20px; flex: 1; overflow-y: auto; }
.cart-item { display: flex; gap: 14px; align-items: center; padding: 16px 0; border-bottom: 1px solid #f2f2f2; }
.cart-item img { width: 80px; height: 80px; object-fit: cover; border-radius: 12px; background: #f7f7f7; }
@@ -1015,11 +1132,9 @@ ul {
.wishlist-overlay.wishlisted { color: #e85d04; }
.wishlist-btn-large.wishlisted { background: #fff0e6; color: #e85d04; border-color: #e85d04; }
-/* Google Login Button */
.google-custom-btn { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; padding: 12px; border: 1.5px solid #e0e0e0; border-radius: 10px; background: #fff; font-size: 14px; font-weight: 600; color: #333; cursor: pointer; margin-top: 4px; }
.google-custom-btn:hover { background: #f5f5f5; border-color: #ccc; }
-/* User Profile in Header */
.user-profile-wrap { position: relative; }
.user-avatar-btn { background: none; border: none; cursor: pointer; padding: 0; border-radius: 50%; }
.user-avatar { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; border: 2px solid #e85d04; }
@@ -1032,13 +1147,11 @@ ul {
.dropdown-logout { width: 100%; background: #fff0e6; color: #e85d04; border: none; border-radius: 8px; padding: 9px; font-weight: 600; font-size: 13px; cursor: pointer; }
.dropdown-logout:hover { background: #e85d04; color: #fff; }
-/* ── Checkout ── */
.checkout-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 16px; }
.checkout-modal { background: #fff; border-radius: 20px; width: 100%; max-width: 680px; max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; }
.checkout-header { display: flex; justify-content: space-between; align-items: center; padding: 20px 28px; border-bottom: 1px solid #f0f0f0; }
.checkout-header h2 { font-size: 16px; font-weight: 800; letter-spacing: 2px; }
-/* Steps */
.checkout-steps { display: flex; align-items: center; justify-content: center; padding: 20px 28px; gap: 0; }
.step-item { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.step-circle { width: 30px; height: 30px; border-radius: 50%; border: 2px solid #ddd; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; color: #aaa; background: #fff; }
@@ -1050,10 +1163,8 @@ ul {
.step-line { flex: 1; height: 2px; background: #eee; min-width: 60px; margin: 0 8px; margin-bottom: 20px; }
.step-line.done { background: #e85d04; }
-/* Body */
.checkout-body { flex: 1; overflow-y: auto; padding: 0 28px 28px; }
-/* Items */
.co-items { display: flex; flex-direction: column; gap: 0; margin-bottom: 20px; }
.co-item { display: flex; gap: 16px; padding: 16px 0; border-bottom: 1px solid #f2f2f2; align-items: center; }
.co-item img { width: 90px; height: 90px; object-fit: cover; border-radius: 12px; background: #f7f7f7; }
@@ -1065,7 +1176,6 @@ ul {
.co-item-price p { font-weight: 800; font-size: 15px; text-align: right; }
.co-item-price span { font-size: 11px; color: #aaa; white-space: nowrap; }
-/* Billing */
.co-billing { background: #fafafa; border-radius: 14px; padding: 16px 20px; margin-bottom: 20px; }
.co-billing h4 { font-size: 12px; letter-spacing: 1.5px; color: #aaa; margin-bottom: 12px; font-weight: 700; }
.billing-row { display: flex; justify-content: space-between; align-items: center; padding: 10px 0; border-bottom: 1px solid #f0f0f0; font-size: 14px; }
@@ -1074,13 +1184,11 @@ ul {
.billing-row.total-row { font-weight: 800; font-size: 15px; }
.free-ship { color: #16a34a; font-weight: 700; }
-/* Buttons */
.co-next-btn { width: 100%; display: flex; align-items: center; justify-content: center; gap: 8px; padding: 16px; border-radius: 14px; font-size: 14px; letter-spacing: 1px; }
.co-btn-row { display: flex; gap: 12px; margin-top: 20px; }
.co-back-btn { flex: 0 0 auto; padding: 16px 24px; border-radius: 14px; font-size: 13px; letter-spacing: 1px; }
.place-order-btn { flex: 2; }
-/* Address Form */
.co-address-form h4 { font-size: 13px; font-weight: 700; letter-spacing: 1px; margin-bottom: 16px; display: flex; align-items: center; gap: 6px; color: #333; }
.co-address-form input { width: 100%; padding: 12px 16px; border: 1.5px solid #e8e8e8; border-radius: 10px; font-size: 14px; margin-bottom: 12px; outline: none; box-sizing: border-box; }
.co-address-form input:focus { border-color: #e85d04; }
@@ -1088,21 +1196,18 @@ ul {
.form-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
.form-row-2 input, .form-row-3 input { margin-bottom: 0; }
-/* Payment */
.co-payment h4 { font-size: 13px; font-weight: 700; letter-spacing: 1px; margin-bottom: 16px; display: flex; align-items: center; gap: 6px; color: #333; }
.payment-options { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }
.payment-option { display: flex; align-items: center; gap: 12px; padding: 14px 16px; border: 1.5px solid #e8e8e8; border-radius: 12px; cursor: pointer; font-size: 14px; font-weight: 500; }
.payment-option.selected { border-color: #e85d04; background: #fff8f5; }
.payment-option input { accent-color: #e85d04; width: 16px; height: 16px; }
-/* Order Success */
.order-success { text-align: center; padding: 48px 28px; display: flex; flex-direction: column; align-items: center; }
.success-icon { width: 72px; height: 72px; background: #e85d04; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; margin: 0 auto 20px; }
.order-success h2 { font-size: 24px; font-weight: 800; margin-bottom: 10px; }
.order-success p { color: #888; margin-bottom: 28px; font-size: 14px; }
.order-success .btn-primary { width: auto; padding: 14px 32px; }
-/* ── Account Drawer ── */
.account-body { display: flex; flex-direction: column; gap: 20px; padding: 20px; flex: 1; overflow-y: auto; }
.account-profile-card { display: flex; align-items: center; gap: 16px; background: #fafafa; border-radius: 16px; padding: 20px; }
.account-avatar { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; border: 3px solid #e85d04; }
@@ -1125,7 +1230,6 @@ ul {
.account-logout-btn { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; padding: 14px; border: 1.5px solid #e8e8e8; border-radius: 12px; background: #fff; font-size: 13px; font-weight: 700; letter-spacing: 1px; color: #555; cursor: pointer; }
.account-logout-btn:hover { border-color: #e85d04; color: #e85d04; }
-/* Size Chart */
.size-chart-link { cursor: pointer; font-size: 12px; font-weight: 700; color: #e85d04; text-decoration: underline; }
.size-chart-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 1000; display: flex; align-items: center; justify-content: center; }
.size-chart-modal { background: #fff; border-radius: 16px; padding: 24px; width: 340px; }
@@ -1137,10 +1241,8 @@ ul {
.size-table td { padding: 10px; text-align: center; border-bottom: 1px solid #f0f0f0; }
.size-table tr.highlighted td { background: #fff0e6; font-weight: 700; color: #e85d04; }
-/* Auth error */
.auth-error { color: #e85d04; font-size: 13px; text-align: center; margin: -4px 0; }
-/* ── Order Detail & Cancel ── */
.order-detail-view, .cancel-view { display: flex; flex-direction: column; gap: 16px; }
.od-header { display: flex; justify-content: space-between; background: #f7f7f7; border-radius: 10px; padding: 12px 16px; font-size: 13px; }
.od-label { color: #888; }
@@ -1154,7 +1256,6 @@ ul {
.od-cancel-btn { font-size: 12px; font-weight: 700; border: 1.5px solid #ddd; background: #fff; border-radius: 6px; padding: 5px 14px; cursor: pointer; color: #555; }
.od-cancel-btn:hover { border-color: #e85d04; color: #e85d04; }
-/* Tracking */
.od-tracking { display: flex; flex-direction: column; padding: 12px 0; }
.track-step { display: flex; align-items: flex-start; gap: 16px; }
.track-left { display: flex; flex-direction: column; align-items: center; width: 18px; flex-shrink: 0; }
@@ -1167,7 +1268,6 @@ ul {
.track-date { font-size: 12px; color: #aaa; margin-top: 2px; }
.od-cancelled-badge { color: #dc2626; font-weight: 700; font-size: 14px; padding: 12px 0; }
-/* Cancel Form */
.cancel-form { display: flex; flex-direction: column; gap: 10px; }
.cancel-form h4 { font-weight: 800; font-size: 14px; }
.cancel-form p { font-size: 13px; color: #888; }
@@ -1180,7 +1280,6 @@ ul {
.cancel-back-btn { flex: 1; padding: 14px; border-radius: 12px; font-size: 13px; letter-spacing: 1px; }
.cancel-confirm-btn { flex: 2; padding: 14px; border-radius: 12px; font-size: 13px; letter-spacing: 1px; }
-/* Cancel Popup */
.cancel-popup-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.4); display: flex; align-items: center; justify-content: center; z-index: 10; border-radius: inherit; }
.cancel-popup { background: #fff; border-radius: 14px; padding: 24px; margin: 20px; box-shadow: 0 8px 30px rgba(0,0,0,0.15); }
.cancel-popup p { font-size: 14px; color: #333; line-height: 1.6; margin-bottom: 16px; }
@@ -1188,10 +1287,515 @@ ul {
.cancel-popup-btn { float: right; background: none; border: 1.5px solid #e85d04; color: #e85d04; font-weight: 700; font-size: 14px; padding: 8px 20px; border-radius: 8px; cursor: pointer; }
.order-status.cancelled { background: #fef2f2; color: #dc2626; }
-/* Search clear button */
.search-clear { background: none; border: none; cursor: pointer; color: #aaa; font-size: 14px; padding: 0 4px; line-height: 1; }
.search-clear:hover { color: #e85d04; }
-/* Sneakers Banner */
.sneakers-banner-full { width: 100%; overflow: hidden; margin-bottom: 0; }
.sneakers-banner-full img { width: 100%; aspect-ratio: 16 / 7; display: block; object-fit: cover; object-position: center center; }
+
+.category-chips { display: flex; gap: 8px; padding: 12px 0; overflow-x: auto; scrollbar-width: none; flex-wrap: nowrap; }
+.category-chips::-webkit-scrollbar { display: none; }
+.cat-chip { flex-shrink: 0; padding: 8px 16px; border-radius: 20px; background: #f5f5f5; border: none; cursor: pointer; font-size: 13px; font-weight: 600; color: #888; white-space: nowrap; transition: all 0.2s; }
+.cat-chip.active { background: #e85d04; color: #fff; }
+.cat-chip:hover { background: #ffe8e0; color: #e85d04; }
+.cat-chip.active:hover { background: #e85d04; color: #fff; }
+
+.splash-container {
+ position: fixed;
+ inset: 0;
+ z-index: 10000;
+ background-color: var(--brand-red);
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ color: white;
+ overflow: hidden;
+}
+
+.splash-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 1rem;
+}
+
+.splash-logo {
+ font-family: 'Outfit', sans-serif;
+ font-size: clamp(3.5rem, 10vw, 6rem);
+ font-weight: 900;
+ letter-spacing: -3px;
+ line-height: 1;
+ text-shadow: 0 10px 30px rgba(0,0,0,0.15);
+}
+
+.splash-subtitle {
+ font-size: clamp(0.75rem, 2vw, 1rem);
+ letter-spacing: 6px;
+ text-transform: uppercase;
+ font-weight: 600;
+ opacity: 0.9;
+ margin-top: 0.5rem;
+}
+
+.splash-loader {
+ margin-top: 3rem;
+ width: 40px;
+ height: 40px;
+ border: 3px solid rgba(255, 255, 255, 0.3);
+ border-top-color: white;
+ border-radius: 50%;
+ margin-left: auto;
+ margin-right: auto;
+ animation: splash-spin 0.8s linear infinite;
+}
+
+@keyframes splash-spin {
+ to { transform: rotate(360deg); }
+}
+
+.zappify-app {
+ opacity: 1;
+ transition: opacity 0.5s ease;
+}
+
+.zappify-app.loading {
+ height: 100vh;
+ overflow: hidden;
+}
+
+.splash-logo-img {
+ width: clamp(150px, 25vw, 250px);
+ max-height: 250px;
+ object-fit: contain;
+ }
+
+/* --- Nike Collection Page --- */
+.nike-collection-page {
+ min-height: 100vh;
+ background: var(--bg);
+}
+
+.nc-header {
+ position: sticky;
+ top: 0;
+ z-index: 100;
+ background: var(--surface);
+ border-bottom: 1px solid var(--border);
+ padding: 0 2rem;
+}
+
+.nc-header-inner {
+ max-width: 1400px;
+ margin: 0 auto;
+ height: 64px;
+ display: flex;
+ align-items: center;
+ gap: 2rem;
+}
+
+.nc-back-btn {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ background: none;
+ border: none;
+ color: var(--text-secondary);
+ font-size: 0.9rem;
+ font-weight: 600;
+ cursor: pointer;
+ padding: 6px 12px;
+ border-radius: 8px;
+ transition: background 0.2s;
+}
+
+.nc-back-btn:hover {
+ background: var(--bg);
+ color: var(--text);
+}
+
+.nc-hero {
+ background: #000;
+ padding: 3rem 2rem;
+ text-align: center;
+}
+
+.nc-hero-tag {
+ color: #FF6B00;
+ font-size: 0.75rem;
+ font-weight: 800;
+ letter-spacing: 0.3em;
+ margin-bottom: 0.8rem;
+}
+
+.nc-hero-title {
+ font-size: 3rem;
+ font-weight: 900;
+ color: #fff;
+ letter-spacing: -2px;
+ margin-bottom: 0.5rem;
+}
+
+.nc-hero-sub {
+ color: #94A3B8;
+ font-size: 1rem;
+}
+
+.nc-body {
+ max-width: 1400px;
+ margin: 0 auto;
+ padding: 2rem;
+}
+
+.nc-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
+ gap: 1.5rem;
+}
+
+/* --- Nike Info Banner --- */
+.nike-info-banner {
+ background: #000;
+ border-radius: 16px;
+ padding: 2rem 2.5rem;
+ margin-bottom: 1.5rem;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ overflow: hidden;
+ position: relative;
+ min-height: 180px;
+}
+
+.nike-banner-content {
+ flex: 1;
+ z-index: 2;
+}
+
+.nike-banner-tag {
+ color: #FF6B00;
+ font-size: 0.7rem;
+ font-weight: 800;
+ letter-spacing: 0.25em;
+ text-transform: uppercase;
+ margin-bottom: 0.6rem;
+}
+
+.nike-banner-title {
+ color: #fff;
+ font-size: 2.6rem;
+ font-weight: 900;
+ line-height: 1.05;
+ letter-spacing: -2px;
+ margin-bottom: 0.6rem;
+}
+
+.nike-banner-sub {
+ color: #64748B;
+ font-size: 0.9rem;
+ font-weight: 500;
+ max-width: 320px;
+ margin-bottom: 1.2rem;
+ line-height: 1.5;
+}
+
+.nike-banner-stats {
+ display: flex;
+ align-items: center;
+ gap: 1.2rem;
+ margin-bottom: 1.2rem;
+}
+
+.nike-stat {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+}
+
+.nike-stat-num {
+ color: #fff;
+ font-size: 1.3rem;
+ font-weight: 900;
+ letter-spacing: -1px;
+ line-height: 1;
+}
+
+.nike-stat-label {
+ color: #475569;
+ font-size: 0.7rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.nike-stat-divider {
+ width: 1px;
+ height: 32px;
+ background: #1e293b;
+}
+
+.nike-banner-btn {
+ background: none;
+ border: 1.5px solid #1e293b;
+ color: #94A3B8;
+ font-size: 0.8rem;
+ font-weight: 700;
+ padding: 0.5rem 1.2rem;
+ border-radius: 20px;
+ cursor: pointer;
+ transition: all 0.2s;
+ letter-spacing: 0.5px;
+}
+
+.nike-banner-btn:hover {
+ border-color: #FF6B00;
+ color: #FF6B00;
+}
+
+.nike-banner-img {
+ flex: 0 0 260px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.nike-banner-img img {
+ width: 260px;
+ transform: rotate(-8deg);
+ filter: drop-shadow(0 20px 40px rgba(0,0,0,0.6));
+}
+
+.landing-page {
+ position: fixed;
+ inset: 0;
+ z-index: 9999;
+ background: #000;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 8vw;
+ overflow: hidden;
+}
+
+.landing-bg {
+ position: absolute;
+ inset: 0;
+ background: radial-gradient(ellipse at 70% 50%, rgba(255, 107, 0, 0.12) 0%, transparent 60%);
+ pointer-events: none;
+}
+
+.landing-content {
+ flex: 1;
+ z-index: 2;
+ max-width: 560px;
+}
+
+.landing-logo {
+ font-size: 1.8rem;
+ font-weight: 900;
+ letter-spacing: -1px;
+ color: #fff;
+ margin-bottom: 2rem;
+}
+
+.landing-tag {
+ color: #FF6B00;
+ font-size: 0.75rem;
+ font-weight: 800;
+ letter-spacing: 0.3em;
+ text-transform: uppercase;
+ margin-bottom: 1rem;
+}
+
+.landing-title {
+ font-size: clamp(3rem, 6vw, 5.5rem);
+ font-weight: 900;
+ color: #fff;
+ line-height: 1.0;
+ letter-spacing: -3px;
+ margin-bottom: 1.5rem;
+}
+
+.landing-sub {
+ font-size: 1.1rem;
+ color: #64748B;
+ line-height: 1.6;
+ max-width: 420px;
+ margin-bottom: 2.5rem;
+}
+
+.landing-cta {
+ background: #FF6B00;
+ color: #fff;
+ border: none;
+ padding: 1rem 3rem;
+ font-size: 1rem;
+ font-weight: 800;
+ letter-spacing: 1.5px;
+ border-radius: 50px;
+ cursor: pointer;
+ box-shadow: 0 15px 40px rgba(255, 107, 0, 0.35);
+ margin-bottom: 3rem;
+}
+
+.landing-scroll-hint {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
+ color: #475569;
+ font-size: 0.75rem;
+ font-weight: 600;
+ letter-spacing: 1px;
+ text-transform: uppercase;
+}
+
+.scroll-arrow {
+ width: 1px;
+ height: 40px;
+ background: linear-gradient(to bottom, #FF6B00, transparent);
+ animation: scrollPulse 1.5s ease-in-out infinite;
+}
+
+@keyframes scrollPulse {
+ 0%, 100% { opacity: 0.4; transform: scaleY(1); }
+ 50% { opacity: 1; transform: scaleY(1.2); }
+}
+
+.landing-shoe {
+ flex: 0 0 45%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 2;
+}
+
+.landing-shoe img {
+ width: 100%;
+ max-width: 600px;
+ transform: rotate(-10deg);
+ filter: drop-shadow(0 40px 80px rgba(255, 107, 0, 0.2));
+}
+
+@media (max-width: 768px) {
+ .landing-page {
+ flex-direction: column;
+ justify-content: center;
+ padding: 2rem;
+ text-align: center;
+ }
+ .landing-content {
+ max-width: 100%;
+ }
+ .landing-scroll-hint {
+ align-items: center;
+ }
+ .landing-shoe {
+ display: none;
+ }
+}
+
+.login-modal-new {
+ width: 420px !important;
+ max-width: 95vw !important;
+ padding: 0 !important;
+ overflow: hidden !important;
+ border-radius: 20px !important;
+}
+
+.login-hero-banner {
+ position: relative;
+ height: 220px;
+ background: #000;
+ overflow: hidden;
+}
+
+.login-hero-img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ opacity: 0.75;
+}
+
+.login-close-btn {
+ position: absolute !important;
+ top: 12px !important;
+ right: 12px !important;
+ background: rgba(255,255,255,0.15) !important;
+ border: 1px solid rgba(255,255,255,0.3) !important;
+ border-radius: 20px !important;
+ padding: 6px 12px !important;
+ color: #fff !important;
+}
+
+.login-hero-overlay {
+ position: absolute;
+ bottom: 20px;
+ left: 24px;
+}
+
+.login-hero-tag {
+ color: #FF6B00;
+ font-size: 0.65rem;
+ font-weight: 900;
+ letter-spacing: 3px;
+ margin-bottom: 4px;
+}
+
+.login-hero-title {
+ color: #fff;
+ font-size: 1.8rem;
+ font-weight: 900;
+ line-height: 1.1;
+ letter-spacing: -1px;
+ margin-bottom: 4px;
+}
+
+.login-hero-sub {
+ color: #94A3B8;
+ font-size: 0.85rem;
+}
+
+.login-form-card {
+ padding: 24px 28px 28px;
+ background: #fff;
+}
+
+.login-form-card h2 {
+ font-size: 1.4rem;
+ font-weight: 800;
+ color: #0F172A;
+ margin-bottom: 4px;
+}
+
+.login-form-card > p {
+ font-size: 0.9rem;
+ color: #64748B;
+ margin-bottom: 20px;
+}
+
+.google-proper-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 12px;
+ width: 100%;
+ padding: 12px;
+ border: 1.5px solid #e0e0e0;
+ border-radius: 12px;
+ background: #fff;
+ cursor: pointer;
+ font-size: 0.95rem;
+ font-weight: 600;
+ color: #1a1a1a;
+ transition: background 0.2s;
+}
+
+.google-proper-btn:hover {
+ background: #f5f5f5;
+}
+
+.google-icon-large {
+ width: 22px;
+ height: 22px;
+}
diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx
index af05417..6105491 100644
--- a/frontend/src/main.jsx
+++ b/frontend/src/main.jsx
@@ -3,18 +3,15 @@ import { createRoot } from 'react-dom/client'
import { GoogleOAuthProvider } from '@react-oauth/google'
import './index.css'
import App from './App.jsx'
-import Preview from './Preview.jsx'
-const isPreview = window.location.pathname === '/preview';
+if (window.location.pathname === '/preview') {
+ window.location.replace('/');
+}
createRoot(document.getElementById('root')).render(
- {isPreview ? (
-
- ) : (
-
-
-
- )}
+
+
+
,
)
diff --git a/frontend/vercel.json b/frontend/vercel.json
index 0d199b2..2ffe2c5 100644
--- a/frontend/vercel.json
+++ b/frontend/vercel.json
@@ -1,4 +1,7 @@
{
+ "redirects": [
+ { "source": "/preview", "destination": "/", "permanent": true }
+ ],
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
]
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index 9ffcc67..b94a372 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -3,4 +3,7 @@ import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
+ server: {
+ historyApiFallback: true,
+ },
})
diff --git a/mobile/App.js b/mobile/App.js
index 235b24f..de37f3c 100644
--- a/mobile/App.js
+++ b/mobile/App.js
@@ -1,9 +1,10 @@
import 'react-native-gesture-handler';
-import React from 'react';
-import { View, Text } from 'react-native';
+import React, { useState, useEffect, useRef } from 'react';
+import { View, Text, StyleSheet, Animated, StatusBar, Image } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { SafeAreaProvider } from 'react-native-safe-area-context';
+import AsyncStorage from '@react-native-async-storage/async-storage';
import { AppProvider } from './src/context/AppContext';
import HomeScreen from './src/screens/HomeScreen';
@@ -17,11 +18,53 @@ import AccountScreen from './src/screens/AccountScreen';
const Stack = createNativeStackNavigator();
export default function App() {
+ const [showSplash, setShowSplash] = useState(true);
+ const [initialRoute, setInitialRoute] = useState('Login');
+ const fadeAnim = useRef(new Animated.Value(1)).current;
+ const scaleAnim = useRef(new Animated.Value(0.95)).current;
+
+ useEffect(() => {
+ AsyncStorage.getItem('zappify_user').then(saved => {
+ if (saved) setInitialRoute('Home');
+ });
+
+ Animated.loop(
+ Animated.sequence([
+ Animated.timing(scaleAnim, { toValue: 1.05, duration: 1000, useNativeDriver: true }),
+ Animated.timing(scaleAnim, { toValue: 0.95, duration: 1000, useNativeDriver: true }),
+ ])
+ ).start();
+
+ const timer = setTimeout(() => {
+ Animated.timing(fadeAnim, {
+ toValue: 0,
+ duration: 800,
+ useNativeDriver: true,
+ }).start(() => setShowSplash(false));
+ }, 2500);
+
+ return () => clearTimeout(timer);
+ }, []);
+
+ if (showSplash) {
+ return (
+
+
+
+
+
+ Premium Shoe Store
+
+
+
+ );
+ }
+
return (
-
+
@@ -35,3 +78,27 @@ export default function App() {
);
}
+
+const styles = StyleSheet.create({
+ splashContainer: {
+ flex: 1,
+ backgroundColor: '#FF3D00',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ splashLogoImg: {
+ width: 280,
+ height: 280,
+ resizeMode: 'contain',
+ },
+ splashSubtitle: {
+ fontSize: 12,
+ color: '#FFFFFF',
+ opacity: 0.9,
+ textTransform: 'uppercase',
+ letterSpacing: 6,
+ textAlign: 'center',
+ marginTop: 8,
+ fontWeight: '700',
+ },
+});
diff --git a/mobile/app.json b/mobile/app.json
index ae02df6..295b730 100644
--- a/mobile/app.json
+++ b/mobile/app.json
@@ -7,10 +7,18 @@
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"newArchEnabled": true,
+ "updates": {
+ "url": "https://u.expo.dev/4e2e0935-79af-41b1-a1b8-af2b90d261d2",
+ "enabled": true,
+ "checkAutomatically": "ON_LOAD"
+ },
+ "runtimeVersion": {
+ "policy": "appVersion"
+ },
"splash": {
- "image": "./assets/splash-icon.png",
+ "image": "./assets/logo.png",
"resizeMode": "contain",
- "backgroundColor": "#ffffff"
+ "backgroundColor": "#FF3D00"
},
"ios": {
"supportsTablet": true,
diff --git a/mobile/assets/hero-nike.png b/mobile/assets/hero-nike.png
new file mode 100644
index 0000000..c3e6045
Binary files /dev/null and b/mobile/assets/hero-nike.png differ
diff --git a/mobile/assets/logo.png b/mobile/assets/logo.png
new file mode 100644
index 0000000..c3d6c53
Binary files /dev/null and b/mobile/assets/logo.png differ
diff --git a/mobile/assets/shoes/Air Jordan 1 Low SE.jpg b/mobile/assets/shoes/Air Jordan 1 Low SE.jpg
new file mode 100644
index 0000000..2fdf962
Binary files /dev/null and b/mobile/assets/shoes/Air Jordan 1 Low SE.jpg differ
diff --git a/mobile/assets/shoes/Air Jordan 1 Mid.jpg b/mobile/assets/shoes/Air Jordan 1 Mid.jpg
new file mode 100644
index 0000000..cd98828
Binary files /dev/null and b/mobile/assets/shoes/Air Jordan 1 Mid.jpg differ
diff --git a/mobile/assets/shoes/LeBron Witness IX EP.jpg b/mobile/assets/shoes/LeBron Witness IX EP.jpg
new file mode 100644
index 0000000..2de46fd
Binary files /dev/null and b/mobile/assets/shoes/LeBron Witness IX EP.jpg differ
diff --git a/mobile/assets/shoes/Nike Air Max 270.jpg b/mobile/assets/shoes/Nike Air Max 270.jpg
new file mode 100644
index 0000000..a270adb
Binary files /dev/null and b/mobile/assets/shoes/Nike Air Max 270.jpg differ
diff --git a/mobile/assets/shoes/Nike Air Max Alpha Trainer 6.jpg b/mobile/assets/shoes/Nike Air Max Alpha Trainer 6.jpg
new file mode 100644
index 0000000..3748134
Binary files /dev/null and b/mobile/assets/shoes/Nike Air Max Alpha Trainer 6.jpg differ
diff --git a/mobile/assets/shoes/Nike Air Max Dn Roam.jpg b/mobile/assets/shoes/Nike Air Max Dn Roam.jpg
new file mode 100644
index 0000000..f4dec56
Binary files /dev/null and b/mobile/assets/shoes/Nike Air Max Dn Roam.jpg differ
diff --git a/mobile/assets/shoes/Nike Air Max Excee.jpg b/mobile/assets/shoes/Nike Air Max Excee.jpg
new file mode 100644
index 0000000..3f951fd
Binary files /dev/null and b/mobile/assets/shoes/Nike Air Max Excee.jpg differ
diff --git a/mobile/assets/shoes/Nike Ava Rover.jpg b/mobile/assets/shoes/Nike Ava Rover.jpg
new file mode 100644
index 0000000..72d7dc9
Binary files /dev/null and b/mobile/assets/shoes/Nike Ava Rover.jpg differ
diff --git a/mobile/assets/shoes/Nike Downshifter 14.jpg b/mobile/assets/shoes/Nike Downshifter 14.jpg
new file mode 100644
index 0000000..05f6713
Binary files /dev/null and b/mobile/assets/shoes/Nike Downshifter 14.jpg differ
diff --git a/mobile/assets/shoes/Nike Free Metcon 6.jpg b/mobile/assets/shoes/Nike Free Metcon 6.jpg
new file mode 100644
index 0000000..0eadd04
Binary files /dev/null and b/mobile/assets/shoes/Nike Free Metcon 6.jpg differ
diff --git a/mobile/assets/shoes/Nike Journey Run.jpg b/mobile/assets/shoes/Nike Journey Run.jpg
new file mode 100644
index 0000000..9b2d1e6
Binary files /dev/null and b/mobile/assets/shoes/Nike Journey Run.jpg differ
diff --git a/mobile/assets/shoes/Nike Killshot 2 Leather Premium.jpg b/mobile/assets/shoes/Nike Killshot 2 Leather Premium.jpg
new file mode 100644
index 0000000..5ab6884
Binary files /dev/null and b/mobile/assets/shoes/Nike Killshot 2 Leather Premium.jpg differ
diff --git a/mobile/assets/shoes/Nike Killshot 2 Leather.jpg b/mobile/assets/shoes/Nike Killshot 2 Leather.jpg
new file mode 100644
index 0000000..9070846
Binary files /dev/null and b/mobile/assets/shoes/Nike Killshot 2 Leather.jpg differ
diff --git a/mobile/assets/shoes/Nike P-6000.jpg b/mobile/assets/shoes/Nike P-6000.jpg
new file mode 100644
index 0000000..3188e76
Binary files /dev/null and b/mobile/assets/shoes/Nike P-6000.jpg differ
diff --git a/mobile/assets/shoes/Nike Promina.jpg b/mobile/assets/shoes/Nike Promina.jpg
new file mode 100644
index 0000000..b4ff48f
Binary files /dev/null and b/mobile/assets/shoes/Nike Promina.jpg differ
diff --git a/mobile/assets/shoes/Nike Quest 6.jpg b/mobile/assets/shoes/Nike Quest 6.jpg
new file mode 100644
index 0000000..dd1fcb3
Binary files /dev/null and b/mobile/assets/shoes/Nike Quest 6.jpg differ
diff --git a/mobile/assets/shoes/Nike Revolution 8 EasyOn.jpg b/mobile/assets/shoes/Nike Revolution 8 EasyOn.jpg
new file mode 100644
index 0000000..0edbc56
Binary files /dev/null and b/mobile/assets/shoes/Nike Revolution 8 EasyOn.jpg differ
diff --git a/mobile/assets/shoes/Nike Run Defy.jpg b/mobile/assets/shoes/Nike Run Defy.jpg
new file mode 100644
index 0000000..d492a3f
Binary files /dev/null and b/mobile/assets/shoes/Nike Run Defy.jpg differ
diff --git a/mobile/assets/shoes/Nike SB Zoom Blazer Low Pro GT.jpg b/mobile/assets/shoes/Nike SB Zoom Blazer Low Pro GT.jpg
new file mode 100644
index 0000000..122981a
Binary files /dev/null and b/mobile/assets/shoes/Nike SB Zoom Blazer Low Pro GT.jpg differ
diff --git a/mobile/assets/shoes/Nike Winflo 11.jpg b/mobile/assets/shoes/Nike Winflo 11.jpg
new file mode 100644
index 0000000..b98fe28
Binary files /dev/null and b/mobile/assets/shoes/Nike Winflo 11.jpg differ
diff --git a/mobile/assets/shoes/shoe1.jpg b/mobile/assets/shoes/shoe1.jpg
new file mode 100644
index 0000000..0019210
Binary files /dev/null and b/mobile/assets/shoes/shoe1.jpg differ
diff --git a/mobile/assets/shoes/shoe10.jpg b/mobile/assets/shoes/shoe10.jpg
new file mode 100644
index 0000000..2468204
Binary files /dev/null and b/mobile/assets/shoes/shoe10.jpg differ
diff --git a/mobile/assets/shoes/shoe15.jpg b/mobile/assets/shoes/shoe15.jpg
new file mode 100644
index 0000000..56f16b8
Binary files /dev/null and b/mobile/assets/shoes/shoe15.jpg differ
diff --git a/mobile/assets/shoes/shoe16.jpg b/mobile/assets/shoes/shoe16.jpg
new file mode 100644
index 0000000..80890cb
Binary files /dev/null and b/mobile/assets/shoes/shoe16.jpg differ
diff --git a/mobile/assets/shoes/shoe17.jpg b/mobile/assets/shoes/shoe17.jpg
new file mode 100644
index 0000000..5b5418b
Binary files /dev/null and b/mobile/assets/shoes/shoe17.jpg differ
diff --git a/mobile/assets/shoes/shoe18.jpg b/mobile/assets/shoes/shoe18.jpg
new file mode 100644
index 0000000..e33bad3
Binary files /dev/null and b/mobile/assets/shoes/shoe18.jpg differ
diff --git a/mobile/assets/shoes/shoe19.jpg b/mobile/assets/shoes/shoe19.jpg
new file mode 100644
index 0000000..c3bbef7
Binary files /dev/null and b/mobile/assets/shoes/shoe19.jpg differ
diff --git a/mobile/assets/shoes/shoe2.jpg b/mobile/assets/shoes/shoe2.jpg
new file mode 100644
index 0000000..78c8878
Binary files /dev/null and b/mobile/assets/shoes/shoe2.jpg differ
diff --git a/mobile/assets/shoes/shoe20.jpg b/mobile/assets/shoes/shoe20.jpg
new file mode 100644
index 0000000..8b049ce
Binary files /dev/null and b/mobile/assets/shoes/shoe20.jpg differ
diff --git a/mobile/assets/shoes/shoe21.jpg b/mobile/assets/shoes/shoe21.jpg
new file mode 100644
index 0000000..6db7b76
Binary files /dev/null and b/mobile/assets/shoes/shoe21.jpg differ
diff --git a/mobile/assets/shoes/shoe22.jpg b/mobile/assets/shoes/shoe22.jpg
new file mode 100644
index 0000000..16c76c8
Binary files /dev/null and b/mobile/assets/shoes/shoe22.jpg differ
diff --git a/mobile/assets/shoes/shoe23.jpg b/mobile/assets/shoes/shoe23.jpg
new file mode 100644
index 0000000..b4a7f5f
Binary files /dev/null and b/mobile/assets/shoes/shoe23.jpg differ
diff --git a/mobile/assets/shoes/shoe24.jpg b/mobile/assets/shoes/shoe24.jpg
new file mode 100644
index 0000000..d5b72e4
Binary files /dev/null and b/mobile/assets/shoes/shoe24.jpg differ
diff --git a/mobile/assets/shoes/shoe25.jpg b/mobile/assets/shoes/shoe25.jpg
new file mode 100644
index 0000000..a1e135e
Binary files /dev/null and b/mobile/assets/shoes/shoe25.jpg differ
diff --git a/mobile/assets/shoes/shoe26.jpg b/mobile/assets/shoes/shoe26.jpg
new file mode 100644
index 0000000..a87ef2d
Binary files /dev/null and b/mobile/assets/shoes/shoe26.jpg differ
diff --git a/mobile/assets/shoes/shoe27.jpg b/mobile/assets/shoes/shoe27.jpg
new file mode 100644
index 0000000..4f92f1b
Binary files /dev/null and b/mobile/assets/shoes/shoe27.jpg differ
diff --git a/mobile/assets/shoes/shoe28.jpg b/mobile/assets/shoes/shoe28.jpg
new file mode 100644
index 0000000..0c0e05d
Binary files /dev/null and b/mobile/assets/shoes/shoe28.jpg differ
diff --git a/mobile/assets/shoes/shoe29.jpg b/mobile/assets/shoes/shoe29.jpg
new file mode 100644
index 0000000..b34cc41
Binary files /dev/null and b/mobile/assets/shoes/shoe29.jpg differ
diff --git a/mobile/assets/shoes/shoe3.jpg b/mobile/assets/shoes/shoe3.jpg
new file mode 100644
index 0000000..a805fb9
Binary files /dev/null and b/mobile/assets/shoes/shoe3.jpg differ
diff --git a/mobile/assets/shoes/shoe30.jpg b/mobile/assets/shoes/shoe30.jpg
new file mode 100644
index 0000000..bc76c94
Binary files /dev/null and b/mobile/assets/shoes/shoe30.jpg differ
diff --git a/mobile/assets/shoes/shoe31.jpg b/mobile/assets/shoes/shoe31.jpg
new file mode 100644
index 0000000..d84513f
Binary files /dev/null and b/mobile/assets/shoes/shoe31.jpg differ
diff --git a/mobile/assets/shoes/shoe32.jpg b/mobile/assets/shoes/shoe32.jpg
new file mode 100644
index 0000000..39e3038
Binary files /dev/null and b/mobile/assets/shoes/shoe32.jpg differ
diff --git a/mobile/assets/shoes/shoe33.jpg b/mobile/assets/shoes/shoe33.jpg
new file mode 100644
index 0000000..a01b346
Binary files /dev/null and b/mobile/assets/shoes/shoe33.jpg differ
diff --git a/mobile/assets/shoes/shoe34.jpg b/mobile/assets/shoes/shoe34.jpg
new file mode 100644
index 0000000..7f8fc74
Binary files /dev/null and b/mobile/assets/shoes/shoe34.jpg differ
diff --git a/mobile/assets/shoes/shoe35.jpg b/mobile/assets/shoes/shoe35.jpg
new file mode 100644
index 0000000..e20ba58
Binary files /dev/null and b/mobile/assets/shoes/shoe35.jpg differ
diff --git a/mobile/assets/shoes/shoe36.jpg b/mobile/assets/shoes/shoe36.jpg
new file mode 100644
index 0000000..7a915c7
Binary files /dev/null and b/mobile/assets/shoes/shoe36.jpg differ
diff --git a/mobile/assets/shoes/shoe37.jpg b/mobile/assets/shoes/shoe37.jpg
new file mode 100644
index 0000000..eca4cda
Binary files /dev/null and b/mobile/assets/shoes/shoe37.jpg differ
diff --git a/mobile/assets/shoes/shoe38.jpg b/mobile/assets/shoes/shoe38.jpg
new file mode 100644
index 0000000..651ada1
Binary files /dev/null and b/mobile/assets/shoes/shoe38.jpg differ
diff --git a/mobile/assets/shoes/shoe39.jpg b/mobile/assets/shoes/shoe39.jpg
new file mode 100644
index 0000000..3655032
Binary files /dev/null and b/mobile/assets/shoes/shoe39.jpg differ
diff --git a/mobile/assets/shoes/shoe4.jpg b/mobile/assets/shoes/shoe4.jpg
new file mode 100644
index 0000000..ca7d255
Binary files /dev/null and b/mobile/assets/shoes/shoe4.jpg differ
diff --git a/mobile/assets/shoes/shoe40.jpg b/mobile/assets/shoes/shoe40.jpg
new file mode 100644
index 0000000..d19d701
Binary files /dev/null and b/mobile/assets/shoes/shoe40.jpg differ
diff --git a/mobile/assets/shoes/shoe41.jpg b/mobile/assets/shoes/shoe41.jpg
new file mode 100644
index 0000000..150a50e
Binary files /dev/null and b/mobile/assets/shoes/shoe41.jpg differ
diff --git a/mobile/assets/shoes/shoe42.jpg b/mobile/assets/shoes/shoe42.jpg
new file mode 100644
index 0000000..186bbef
Binary files /dev/null and b/mobile/assets/shoes/shoe42.jpg differ
diff --git a/mobile/assets/shoes/shoe43.jpg b/mobile/assets/shoes/shoe43.jpg
new file mode 100644
index 0000000..35d41b0
Binary files /dev/null and b/mobile/assets/shoes/shoe43.jpg differ
diff --git a/mobile/assets/shoes/shoe44.jpg b/mobile/assets/shoes/shoe44.jpg
new file mode 100644
index 0000000..2ebbfb8
Binary files /dev/null and b/mobile/assets/shoes/shoe44.jpg differ
diff --git a/mobile/assets/shoes/shoe5.jpg b/mobile/assets/shoes/shoe5.jpg
new file mode 100644
index 0000000..3268966
Binary files /dev/null and b/mobile/assets/shoes/shoe5.jpg differ
diff --git a/mobile/assets/shoes/shoe6.jpg b/mobile/assets/shoes/shoe6.jpg
new file mode 100644
index 0000000..4a6dfb3
Binary files /dev/null and b/mobile/assets/shoes/shoe6.jpg differ
diff --git a/mobile/assets/shoes/shoe7.jpg b/mobile/assets/shoes/shoe7.jpg
new file mode 100644
index 0000000..f633541
Binary files /dev/null and b/mobile/assets/shoes/shoe7.jpg differ
diff --git a/mobile/assets/shoes/shoe8.jpg b/mobile/assets/shoes/shoe8.jpg
new file mode 100644
index 0000000..5ee7fba
Binary files /dev/null and b/mobile/assets/shoes/shoe8.jpg differ
diff --git a/mobile/assets/shoes/shoe9.jpg b/mobile/assets/shoes/shoe9.jpg
new file mode 100644
index 0000000..92d4e52
Binary files /dev/null and b/mobile/assets/shoes/shoe9.jpg differ
diff --git a/mobile/package-lock.json b/mobile/package-lock.json
index e2832d1..07ebc2a 100644
--- a/mobile/package-lock.json
+++ b/mobile/package-lock.json
@@ -14,16 +14,19 @@
"@react-navigation/native": "^7.2.2",
"@react-navigation/native-stack": "^7.14.10",
"expo": "~54.0.33",
- "expo-auth-session": "~7.0.10",
+ "expo-auth-session": "~55.0.12",
"expo-crypto": "~15.0.8",
"expo-dev-client": "~6.0.20",
"expo-status-bar": "~3.0.9",
+ "expo-updates": "~29.0.16",
"expo-web-browser": "~15.0.10",
"react": "19.1.0",
"react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0",
+ "react-native-razorpay": "^2.3.1",
"react-native-safe-area-context": "~5.6.0",
- "react-native-screens": "~4.16.0"
+ "react-native-screens": "~4.16.0",
+ "react-native-webview": "^13.16.1"
}
},
"node_modules/@0no-co/graphql.web": {
@@ -63,7 +66,6 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.0",
"@babel/generator": "^7.29.0",
@@ -1418,7 +1420,6 @@
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
"integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=6.9.0"
}
@@ -2192,6 +2193,39 @@
"xmlbuilder": "^15.1.1"
}
},
+ "node_modules/@expo/require-utils": {
+ "version": "55.0.3",
+ "resolved": "https://registry.npmjs.org/@expo/require-utils/-/require-utils-55.0.3.tgz",
+ "integrity": "sha512-TS1m5tW45q4zoaTlt6DwmdYHxvFTIxoLrTHKOFrIirHIqIXnHCzpceg8wumiBi+ZXSaGY2gobTbfv+WVhJY6Fw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.20.0",
+ "@babel/core": "^7.25.2",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.8"
+ },
+ "peerDependencies": {
+ "typescript": "^5.0.0 || ^5.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@expo/require-utils/node_modules/@babel/code-frame": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@expo/schema-utils": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-0.1.8.tgz",
@@ -3061,7 +3095,6 @@
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.2.2.tgz",
"integrity": "sha512-kem1Ko2BcbAjmbQIv66dNmr6EtfDut3QU0qjsVhMnLLhktwyXb6FzZYp8gTrUb6AvkAbaJoi+BF5Pl55pAUa5w==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@react-navigation/core": "^7.17.2",
"escape-string-regexp": "^4.0.0",
@@ -3845,7 +3878,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.10.12",
"caniuse-lite": "^1.0.30001782",
@@ -4485,7 +4517,6 @@
"resolved": "https://registry.npmjs.org/expo/-/expo-54.0.33.tgz",
"integrity": "sha512-3yOEfAKqo+gqHcV8vKcnq0uA5zxlohnhA3fu4G43likN8ct5ZZ3LjAh9wDdKteEkoad3tFPvwxmXW711S5OHUw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/runtime": "^7.20.0",
"@expo/cli": "54.0.23",
@@ -4534,16 +4565,16 @@
}
},
"node_modules/expo-auth-session": {
- "version": "7.0.10",
- "resolved": "https://registry.npmjs.org/expo-auth-session/-/expo-auth-session-7.0.10.tgz",
- "integrity": "sha512-XDnKkudvhHSKkZfJ+KkodM+anQcrxB71i+h0kKabdLa5YDXTQ81aC38KRc3TMqmnBDHAu0NpfbzEVd9WDFY3Qg==",
+ "version": "55.0.12",
+ "resolved": "https://registry.npmjs.org/expo-auth-session/-/expo-auth-session-55.0.12.tgz",
+ "integrity": "sha512-UXtLP3V9R8a9eZSZhjC3lpFvH1RBVQQNn2NBZ1SdClq4D83HRUaFBmtzkpKxODk2t3ZWDMcyhpwV1O+A6rsqKw==",
"license": "MIT",
"dependencies": {
- "expo-application": "~7.0.8",
- "expo-constants": "~18.0.11",
- "expo-crypto": "~15.0.8",
- "expo-linking": "~8.0.10",
- "expo-web-browser": "~15.0.10",
+ "expo-application": "~55.0.12",
+ "expo-constants": "~55.0.11",
+ "expo-crypto": "~55.0.12",
+ "expo-linking": "~55.0.11",
+ "expo-web-browser": "~55.0.12",
"invariant": "^2.2.4"
},
"peerDependencies": {
@@ -4551,29 +4582,189 @@
"react-native": "*"
}
},
+ "node_modules/expo-auth-session/node_modules/@expo/config": {
+ "version": "55.0.12",
+ "resolved": "https://registry.npmjs.org/@expo/config/-/config-55.0.12.tgz",
+ "integrity": "sha512-qVih0IrjupykH/yAUilZqW1RCpqm8TKG8XJabji2VHI1LstGqw0NJAsBjX927yns08u/fFJTwOsB4PYOoq1HiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-plugins": "~55.0.7",
+ "@expo/config-types": "^55.0.5",
+ "@expo/json-file": "^10.0.13",
+ "@expo/require-utils": "^55.0.3",
+ "deepmerge": "^4.3.1",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "resolve-from": "^5.0.0",
+ "resolve-workspace-root": "^2.0.0",
+ "semver": "^7.6.0",
+ "slugify": "^1.3.4"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/@expo/config-plugins": {
+ "version": "55.0.7",
+ "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-55.0.7.tgz",
+ "integrity": "sha512-XZUoDWrsHEkH3yasnDSJABM/UxP5a1ixzRwU/M+BToyn/f0nTrSJJe/Ay/FpxkI4JSNz2n0e06I23b2bleXKVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-types": "^55.0.5",
+ "@expo/json-file": "~10.0.12",
+ "@expo/plist": "^0.5.2",
+ "@expo/sdk-runtime-versions": "^1.0.0",
+ "chalk": "^4.1.2",
+ "debug": "^4.3.5",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.4",
+ "slugify": "^1.6.6",
+ "xcode": "^3.0.1",
+ "xml2js": "0.6.0"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/@expo/config-types": {
+ "version": "55.0.5",
+ "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-55.0.5.tgz",
+ "integrity": "sha512-sCmSUZG4mZ/ySXvfyyBdhjivz8Q539X1NondwDdYG7s3SBsk+wsgPJzYsqgAG/P9+l0xWjUD2F+kQ1cAJ6NNLg==",
+ "license": "MIT"
+ },
+ "node_modules/expo-auth-session/node_modules/@expo/env": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.1.1.tgz",
+ "integrity": "sha512-rVvHC4I6xlPcg+mAO09ydUi2Wjv1ZytpLmHOSzvXzBAz9mMrJggqCe4s4dubjJvi/Ino/xQCLhbaLCnTtLpikg==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "debug": "^4.3.4",
+ "getenv": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=20.12.0"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/@expo/plist": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.5.2.tgz",
+ "integrity": "sha512-o4xdVdBpe4aTl3sPMZ2u3fJH4iG1I768EIRk1xRZP+GaFI93MaR3JvoFibYqxeTmLQ1p1kNEVqylfUjezxx45g==",
+ "license": "MIT",
+ "dependencies": {
+ "@xmldom/xmldom": "^0.8.8",
+ "base64-js": "^1.5.1",
+ "xmlbuilder": "^15.1.1"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
"node_modules/expo-auth-session/node_modules/expo-application": {
- "version": "7.0.8",
- "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-7.0.8.tgz",
- "integrity": "sha512-qFGyxk7VJbrNOQWBbE09XUuGuvkOgFS9QfToaK2FdagM2aQ+x3CvGV2DuVgl/l4ZxPgIf3b/MNh9xHpwSwn74Q==",
+ "version": "55.0.12",
+ "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-55.0.12.tgz",
+ "integrity": "sha512-pDmgZKWZDCgLF9CUlPPBEDKEvYKaAELMXkS7EMz5tRsWTQswwvaa9DW7Lfz9cTn3Bw4fz8agliuF/AU2Ce9T+A==",
"license": "MIT",
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-auth-session/node_modules/expo-constants": {
- "version": "18.0.13",
- "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.13.tgz",
- "integrity": "sha512-FnZn12E1dRYKDHlAdIyNFhBurKTS3F9CrfrBDJI5m3D7U17KBHMQ6JEfYlSj7LG7t+Ulr+IKaj58L1k5gBwTcQ==",
+ "version": "55.0.11",
+ "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-55.0.11.tgz",
+ "integrity": "sha512-efWOJr0oVDId0lhvXJwoWfzucwi1/upDDseuYAhK0m8v5Hg7ObDehMmKRMGL0dgABmlSnppNmmYIeTVe7e2yVg==",
"license": "MIT",
"dependencies": {
- "@expo/config": "~12.0.13",
- "@expo/env": "~2.0.8"
+ "@expo/config": "~55.0.12",
+ "@expo/env": "~2.1.1"
},
"peerDependencies": {
"expo": "*",
"react-native": "*"
}
},
+ "node_modules/expo-auth-session/node_modules/expo-crypto": {
+ "version": "55.0.12",
+ "resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-55.0.12.tgz",
+ "integrity": "sha512-P6GHuypnOV2rUw8mCoVFlpBQtvXbIQSOjA3UECE72dTNAYUfa5nHZtB8HNEVAycNn+fW6f58vNlnl5oIYdMPkA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/expo-web-browser": {
+ "version": "55.0.12",
+ "resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-55.0.12.tgz",
+ "integrity": "sha512-fMmDx/belJ7oW3+Ee7LbPMYKWxQlRYY/JXWFkQ72Zm1cg9Fmxzcu8iSu8gzdvjViM3B545PPv3src5TWq9qDdA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/expo-auth-session/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/expo-crypto": {
"version": "15.0.8",
"resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-15.0.8.tgz",
@@ -4637,6 +4828,12 @@
"expo": "*"
}
},
+ "node_modules/expo-eas-client": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-1.0.8.tgz",
+ "integrity": "sha512-5or11NJhSeDoHHI6zyvQDW2cz/yFyE+1Cz8NTs5NK8JzC7J0JrkUgptWtxyfB6Xs/21YRNifd3qgbBN3hfKVgA==",
+ "license": "MIT"
+ },
"node_modules/expo-json-utils": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-0.15.0.tgz",
@@ -4644,12 +4841,12 @@
"license": "MIT"
},
"node_modules/expo-linking": {
- "version": "8.0.11",
- "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.11.tgz",
- "integrity": "sha512-+VSaNL5om3kOp/SSKO5qe6cFgfSIWnnQDSbA7XLs3ECkYzXRquk5unxNS3pg7eK5kNUmQ4kgLI7MhTggAEUBLA==",
+ "version": "55.0.11",
+ "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-55.0.11.tgz",
+ "integrity": "sha512-qVKOeaFZvaJl99mB1gle0AWaC+36t4SxIIf23rkqyjEs/ZJtt7Zr2NKcQpzNhxUyWms8CSKTAlMO1k9Hx9z9zw==",
"license": "MIT",
"dependencies": {
- "expo-constants": "~18.0.12",
+ "expo-constants": "~55.0.11",
"invariant": "^2.2.4"
},
"peerDependencies": {
@@ -4657,20 +4854,161 @@
"react-native": "*"
}
},
+ "node_modules/expo-linking/node_modules/@expo/config": {
+ "version": "55.0.12",
+ "resolved": "https://registry.npmjs.org/@expo/config/-/config-55.0.12.tgz",
+ "integrity": "sha512-qVih0IrjupykH/yAUilZqW1RCpqm8TKG8XJabji2VHI1LstGqw0NJAsBjX927yns08u/fFJTwOsB4PYOoq1HiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-plugins": "~55.0.7",
+ "@expo/config-types": "^55.0.5",
+ "@expo/json-file": "^10.0.13",
+ "@expo/require-utils": "^55.0.3",
+ "deepmerge": "^4.3.1",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "resolve-from": "^5.0.0",
+ "resolve-workspace-root": "^2.0.0",
+ "semver": "^7.6.0",
+ "slugify": "^1.3.4"
+ }
+ },
+ "node_modules/expo-linking/node_modules/@expo/config-plugins": {
+ "version": "55.0.7",
+ "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-55.0.7.tgz",
+ "integrity": "sha512-XZUoDWrsHEkH3yasnDSJABM/UxP5a1ixzRwU/M+BToyn/f0nTrSJJe/Ay/FpxkI4JSNz2n0e06I23b2bleXKVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/config-types": "^55.0.5",
+ "@expo/json-file": "~10.0.12",
+ "@expo/plist": "^0.5.2",
+ "@expo/sdk-runtime-versions": "^1.0.0",
+ "chalk": "^4.1.2",
+ "debug": "^4.3.5",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "resolve-from": "^5.0.0",
+ "semver": "^7.5.4",
+ "slugify": "^1.6.6",
+ "xcode": "^3.0.1",
+ "xml2js": "0.6.0"
+ }
+ },
+ "node_modules/expo-linking/node_modules/@expo/config-types": {
+ "version": "55.0.5",
+ "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-55.0.5.tgz",
+ "integrity": "sha512-sCmSUZG4mZ/ySXvfyyBdhjivz8Q539X1NondwDdYG7s3SBsk+wsgPJzYsqgAG/P9+l0xWjUD2F+kQ1cAJ6NNLg==",
+ "license": "MIT"
+ },
+ "node_modules/expo-linking/node_modules/@expo/env": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.1.1.tgz",
+ "integrity": "sha512-rVvHC4I6xlPcg+mAO09ydUi2Wjv1ZytpLmHOSzvXzBAz9mMrJggqCe4s4dubjJvi/Ino/xQCLhbaLCnTtLpikg==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "debug": "^4.3.4",
+ "getenv": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=20.12.0"
+ }
+ },
+ "node_modules/expo-linking/node_modules/@expo/plist": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.5.2.tgz",
+ "integrity": "sha512-o4xdVdBpe4aTl3sPMZ2u3fJH4iG1I768EIRk1xRZP+GaFI93MaR3JvoFibYqxeTmLQ1p1kNEVqylfUjezxx45g==",
+ "license": "MIT",
+ "dependencies": {
+ "@xmldom/xmldom": "^0.8.8",
+ "base64-js": "^1.5.1",
+ "xmlbuilder": "^15.1.1"
+ }
+ },
+ "node_modules/expo-linking/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/expo-linking/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/expo-linking/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/expo-linking/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
"node_modules/expo-linking/node_modules/expo-constants": {
- "version": "18.0.13",
- "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.13.tgz",
- "integrity": "sha512-FnZn12E1dRYKDHlAdIyNFhBurKTS3F9CrfrBDJI5m3D7U17KBHMQ6JEfYlSj7LG7t+Ulr+IKaj58L1k5gBwTcQ==",
+ "version": "55.0.11",
+ "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-55.0.11.tgz",
+ "integrity": "sha512-efWOJr0oVDId0lhvXJwoWfzucwi1/upDDseuYAhK0m8v5Hg7ObDehMmKRMGL0dgABmlSnppNmmYIeTVe7e2yVg==",
"license": "MIT",
"dependencies": {
- "@expo/config": "~12.0.13",
- "@expo/env": "~2.0.8"
+ "@expo/config": "~55.0.12",
+ "@expo/env": "~2.1.1"
},
"peerDependencies": {
"expo": "*",
"react-native": "*"
}
},
+ "node_modules/expo-linking/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/expo-linking/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/expo-manifests": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-1.0.10.tgz",
@@ -4805,6 +5143,42 @@
"react-native": "*"
}
},
+ "node_modules/expo-structured-headers": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-5.0.0.tgz",
+ "integrity": "sha512-RmrBtnSphk5REmZGV+lcdgdpxyzio5rJw8CXviHE6qH5pKQQ83fhMEcigvrkBdsn2Efw2EODp4Yxl1/fqMvOZw==",
+ "license": "MIT"
+ },
+ "node_modules/expo-updates": {
+ "version": "29.0.16",
+ "resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-29.0.16.tgz",
+ "integrity": "sha512-E9/fxRz/Eurtc7hxeI/6ZPyHH3To9Xoccm1kXoICZTRojmuTo+dx0Xv53UHyHn4G5zGMezyaKF2Qtj3AKcT93w==",
+ "license": "MIT",
+ "dependencies": {
+ "@expo/code-signing-certificates": "^0.0.6",
+ "@expo/plist": "^0.4.8",
+ "@expo/spawn-async": "^1.7.2",
+ "arg": "4.1.0",
+ "chalk": "^4.1.2",
+ "debug": "^4.3.4",
+ "expo-eas-client": "~1.0.8",
+ "expo-manifests": "~1.0.10",
+ "expo-structured-headers": "~5.0.0",
+ "expo-updates-interface": "~2.0.0",
+ "getenv": "^2.0.0",
+ "glob": "^13.0.0",
+ "ignore": "^5.3.1",
+ "resolve-from": "^5.0.0"
+ },
+ "bin": {
+ "expo-updates": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/expo-updates-interface": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-2.0.0.tgz",
@@ -4814,6 +5188,82 @@
"expo": "*"
}
},
+ "node_modules/expo-updates/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/expo-updates/node_modules/arg": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
+ "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==",
+ "license": "MIT"
+ },
+ "node_modules/expo-updates/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/expo-updates/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/expo-updates/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/expo-updates/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/expo-updates/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/expo-web-browser": {
"version": "15.0.10",
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-15.0.10.tgz",
@@ -5145,7 +5595,6 @@
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz",
"integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"fontfaceobserver": "^2.1.0"
},
@@ -7721,7 +8170,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -7759,7 +8207,6 @@
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz",
"integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@jest/create-cache-key-function": "^29.7.0",
"@react-native/assets-registry": "0.81.5",
@@ -7837,12 +8284,21 @@
"react-native": "*"
}
},
+ "node_modules/react-native-razorpay": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/react-native-razorpay/-/react-native-razorpay-2.3.1.tgz",
+ "integrity": "sha512-aEod2YigiWx9Vik+2YRpTh9kNKK9KZbfhrRpk5tU8z8ZPDdLt57rRsqd7lVuDybqqO6nLY6ughPjMN+FPyX8Ag==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-native": ">=0.66.0"
+ }
+ },
"node_modules/react-native-safe-area-context": {
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz",
"integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==",
"license": "MIT",
- "peer": true,
"peerDependencies": {
"react": "*",
"react-native": "*"
@@ -7853,7 +8309,6 @@
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz",
"integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==",
"license": "MIT",
- "peer": true,
"dependencies": {
"react-freeze": "^1.0.0",
"react-native-is-edge-to-edge": "^1.2.1",
@@ -7864,6 +8319,32 @@
"react-native": "*"
}
},
+ "node_modules/react-native-webview": {
+ "version": "13.16.1",
+ "resolved": "https://registry.npmjs.org/react-native-webview/-/react-native-webview-13.16.1.tgz",
+ "integrity": "sha512-If0eHhoEdOYDcHsX+xBFwHMbWBGK1BvGDQDQdVkwtSIXiq1uiqjkpWVP2uQ1as94J0CzvFE9PUNDuhiX0Z6ubw==",
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^4.0.0",
+ "invariant": "2.2.4"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/react-native-webview/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/react-native/node_modules/@react-native/virtualized-lists": {
"version": "0.81.5",
"resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.81.5.tgz",
@@ -7953,7 +8434,6 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8855,7 +9335,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
diff --git a/mobile/package.json b/mobile/package.json
index 344ac99..ab55731 100644
--- a/mobile/package.json
+++ b/mobile/package.json
@@ -4,6 +4,7 @@
"main": "index.js",
"scripts": {
"start": "expo start",
+ "go": "expo start --go",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
@@ -15,16 +16,19 @@
"@react-navigation/native": "^7.2.2",
"@react-navigation/native-stack": "^7.14.10",
"expo": "~54.0.33",
- "expo-auth-session": "~7.0.10",
+ "expo-auth-session": "~55.0.12",
"expo-crypto": "~15.0.8",
"expo-dev-client": "~6.0.20",
"expo-status-bar": "~3.0.9",
+ "expo-updates": "~29.0.16",
"expo-web-browser": "~15.0.10",
"react": "19.1.0",
"react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0",
+ "react-native-razorpay": "^2.3.1",
"react-native-safe-area-context": "~5.6.0",
- "react-native-screens": "~4.16.0"
+ "react-native-screens": "~4.16.0",
+ "react-native-webview": "^13.16.1"
},
"private": true
}
diff --git a/mobile/src/components/ProductCard.js b/mobile/src/components/ProductCard.js
index 19e0f58..c9cd6cd 100644
--- a/mobile/src/components/ProductCard.js
+++ b/mobile/src/components/ProductCard.js
@@ -1,54 +1,139 @@
-import React from 'react';
import { View, Text, Image, TouchableOpacity, StyleSheet, Dimensions } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
import { colors } from '../theme/colors';
import { useApp } from '../context/AppContext';
-const W = Dimensions.get('window').width;
-const CARD_W = (W - 36) / 2;
+const { width } = Dimensions.get('window');
+const CARD_W = (width - 40) / 2;
export default function ProductCard({ product, onPress }) {
const { toggleWishlist, isWishlisted } = useApp();
const wishlisted = isWishlisted(product.id);
return (
-
+
-
+
{product.isTrending && (
-
- Trending
+
+ TRENDING
)}
- toggleWishlist(product)}
>
-
+
+
- {product.brand}
- {product.name}
- {product.category}
- ₹ {product.price.toLocaleString('en-IN')}
+ {product.brand}
+ {product.name}
+
+ {product.category.slice(0, 4) === 'Men ' ? product.category.slice(4) : product.category}
+
+
+ ₹{product.price.toLocaleString('en-IN')}
+
);
}
const styles = StyleSheet.create({
- card: { backgroundColor: colors.white, borderRadius: 14, marginBottom: 12, overflow: 'hidden', shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.08, shadowRadius: 8, elevation: 3 },
- imageWrap: { position: 'relative' },
- image: { width: '100%', height: CARD_W, backgroundColor: colors.lightGray },
- trendBadge: { position: 'absolute', top: 8, left: 8, backgroundColor: colors.brand, borderRadius: 6, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 6, paddingVertical: 3, gap: 3 },
- trendText: { color: colors.white, fontSize: 9, fontWeight: '700' },
- wishBtn: { position: 'absolute', top: 8, right: 8, backgroundColor: colors.white, borderRadius: 20, padding: 6, shadowColor: '#000', shadowOpacity: 0.1, shadowRadius: 4, elevation: 2 },
- wishBtnActive: { backgroundColor: colors.brandLight },
- info: { padding: 10 },
- brand: { fontSize: 10, fontWeight: '700', color: colors.gray, letterSpacing: 1, marginBottom: 2 },
- name: { fontSize: 13, fontWeight: '700', color: colors.dark, marginBottom: 2 },
- category: { fontSize: 11, color: colors.gray, marginBottom: 6 },
- price: { fontSize: 14, fontWeight: '800', color: colors.dark },
+ card: {
+ width: CARD_W,
+ backgroundColor: colors.surface,
+ borderRadius: 20,
+ marginBottom: 16,
+ overflow: 'hidden',
+ shadowColor: colors.dark,
+ shadowOffset: { width: 0, height: 6 },
+ shadowOpacity: 0.1,
+ shadowRadius: 12,
+ elevation: 8,
+ },
+ imageWrap: {
+ backgroundColor: '#F1F5F9',
+ height: CARD_W * 1.1,
+ overflow: 'hidden',
+ position: 'relative',
+ },
+ image: {
+ width: '100%',
+ height: '100%',
+ },
+ trendBadge: {
+ position: 'absolute',
+ top: 10,
+ left: 10,
+ backgroundColor: colors.brand,
+ paddingHorizontal: 8,
+ paddingVertical: 4,
+ borderRadius: 6,
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 4,
+ },
+ trendText: {
+ color: colors.white,
+ fontSize: 8,
+ fontWeight: '900',
+ letterSpacing: 0.5,
+ },
+ wishBtn: {
+ position: 'absolute',
+ top: 10,
+ right: 10,
+ width: 28,
+ height: 28,
+ borderRadius: 14,
+ backgroundColor: colors.white,
+ alignItems: 'center',
+ justifyContent: 'center',
+ shadowColor: colors.dark,
+ shadowOpacity: 0.1,
+ shadowRadius: 4,
+ elevation: 3,
+ },
+ wishBtnActive: {
+ backgroundColor: '#FFF0F0',
+ },
+ info: {
+ padding: 12,
+ },
+ brand: {
+ fontSize: 9,
+ fontWeight: '800',
+ color: colors.gray,
+ letterSpacing: 1.2,
+ marginBottom: 3,
+ textTransform: 'uppercase',
+ },
+ name: {
+ fontSize: 14,
+ fontWeight: '700',
+ color: colors.dark,
+ marginBottom: 2,
+ },
+ category: {
+ fontSize: 11,
+ color: colors.slate,
+ marginBottom: 8,
+ },
+ priceRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ price: {
+ fontSize: 15,
+ fontWeight: '900',
+ color: colors.brand,
+ }
});
diff --git a/mobile/src/data/products.js b/mobile/src/data/products.js
index 448762d..16491ec 100644
--- a/mobile/src/data/products.js
+++ b/mobile/src/data/products.js
@@ -1,44 +1,603 @@
-const BASE = 'https://raw.githubusercontent.com/Mishra-coder/Zappify/main/frontend/public/shoes/shoe';
-const img = (n) => `${BASE}${n}.jpg`;
-
export const ALL_PRODUCTS = [
- { id: 1, name: 'The Incredible Hulk', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Cyber Sport', price: 3799, image: img(31), isTrending: true, description: 'Smash your limits with The Incredible Hulk High Tops. Featuring heavy-duty impact cushioning and gamma-green accents.' },
- { id: 2, name: 'Spider-Man: Spider Verse', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Cyber Sport', price: 3999, image: img(2), isTrending: true, description: 'Step into the multiverse. These low-tops feature web-reactive textures, striking contrast colors, and an agile profile.' },
- { id: 3, name: 'Urban Blaze: Hawkins', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Urban Tech', price: 2599, image: img(3), isTrending: false, description: 'Classic Hawkins energy. A vibrant design combining retro aesthetics with modern urban traction technology.' },
- { id: 4, name: 'Rovers: Batman', brand: 'ZAPPIFY', category: 'Men Slip-ons', theme: 'Minimalist', price: 3499, image: img(4), isTrending: true, description: 'Lounge like a Dark Knight. Premium dark synthetic leather construction designed for ultimate comfort and stealth.' },
- { id: 5, name: 'Urban Blaze: Blue Moon', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Retro Classic', price: 2599, image: img(5), isTrending: false, description: 'A striking blue moon aesthetic. Features reinforced stitching and maximum breathability for everyday street wear.' },
- { id: 6, name: 'Deadpool: 2.0', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Urban Tech', price: 2599, image: img(6), isTrending: true, description: 'Maximum effort for your feet. Deep red canvas panels mixed with anti-abrasion overlays for the merc on the move.' },
- { id: 7, name: 'Urban Blaze: Cappuccino', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Minimalist', price: 2599, image: img(7), isTrending: false, description: 'Rich earth tones and creamy accents. A laid-back silhouette built on top of a highly responsive foam midsole.' },
- { id: 8, name: 'Milano: Walnut', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Retro Classic', price: 2599, image: img(8), isTrending: false, description: 'Sleek Italian-inspired lines. The Milano Walnut blends casual elegance with a durable, long-lasting rubber cupsole.' },
- { id: 9, name: 'Star Wars: Mandalorian', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Cyber Sport', price: 3199, image: img(9), isTrending: true, description: 'This is the way. Featuring heavy-duty Beskar-inspired metallic finishes and a rugged terrain grip.' },
- { id: 10, name: 'Hydros: The Dark Knight', brand: 'ZAPPIFY', category: 'Men Clogs', theme: 'Minimalist', price: 1499, image: img(10), isTrending: true, description: 'Waterproof, ultra-light, and effortlessly stealthy. The ultimate companion for quick missions or total relaxation.' },
- { id: 11, name: 'Captain America: First Avenger', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Retro Classic', price: 3699, image: img(2), isTrending: true, description: 'The shield of the streets. Vintage combat styling paired with highly durable shock-absorbent outsoles.' },
- { id: 12, name: 'Black Panther: Wakanda Forever', brand: 'ZAPPIFY', category: 'Men Mid Top Sneakers', theme: 'Urban Tech', price: 3899, image: img(4), isTrending: true, description: 'Sleek, powerful, agile. Built with ultra-responsive vibranium-inspired bounce technology for unmatched speed.' },
- { id: 15, name: 'Urban Blaze: Cappuccino', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Urban Tech', price: 2599, image: img(15), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 16, name: 'Milano: Walnut', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Cyber Sport', price: 2599, image: img(16), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 17, name: 'Star Wars: Mandalorian', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Urban Tech', price: 3199, image: img(17), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 18, name: 'Hydros: The Dark Knight', brand: 'ZAPPIFY', category: 'Men Mid Top Sneakers', theme: 'Minimalist', price: 1499, image: img(18), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 19, name: 'Velocity: Silver', brand: 'ZAPPIFY', category: 'Men Slip-ons', theme: 'Cyber Sport', price: 2599, image: img(19), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 20, name: 'Urban Blaze: Black', brand: 'ZAPPIFY', category: 'Men Mid Top Sneakers', theme: 'Minimalist', price: 2599, image: img(20), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 21, name: 'Urban Blaze: Mafia', brand: 'ZAPPIFY', category: 'Men Mid Top Sneakers', theme: 'Cyber Sport', price: 2599, image: img(21), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 22, name: 'Urban Blaze: Green Lab', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Urban Tech', price: 1999, image: img(22), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 23, name: 'Black Panther: Warrior', brand: 'ZAPPIFY', category: 'Men Mid Top Sneakers', theme: 'Urban Tech', price: 3499, image: img(23), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 24, name: 'Velocity: Scarlet', brand: 'ZAPPIFY', category: 'Men Slip-ons', theme: 'Cyber Sport', price: 2599, image: img(24), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 25, name: 'Kanso V2: Beige', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Retro Classic', price: 2599, image: img(25), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 26, name: 'Kanso ZE: Black', brand: 'ZAPPIFY', category: 'Men Mid Top Sneakers', theme: 'Urban Tech', price: 2599, image: img(26), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 28, name: 'UBZ Ascend: Mocha', brand: 'ZAPPIFY', category: 'Men Slip-ons', theme: 'Urban Tech', price: 3599, image: img(28), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 29, name: 'MACH 1', brand: 'ZAPPIFY', category: 'Men Slip-ons', theme: 'Retro Classic', price: 3499, image: img(29), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 30, name: 'Naruto Shippuden: Sasuke', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Urban Tech', price: 3299, image: img(30), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 31, name: 'Kanso V2: Sapphire', brand: 'ZAPPIFY', category: 'Men Clogs', theme: 'Urban Tech', price: 2599, image: img(31), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 32, name: 'UBZ Ascend: Oasis', brand: 'ZAPPIFY', category: 'Men Mid Top Sneakers', theme: 'Cyber Sport', price: 3499, image: img(32), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 33, name: 'MACH 3', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Retro Classic', price: 3499, image: img(33), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 34, name: "Daredevil: Hell's Knight", brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Cyber Sport', price: 3799, image: img(34), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 36, name: 'Mortal Kombat: Scorpion', brand: 'ZAPPIFY', category: 'Men Slip-ons', theme: 'Retro Classic', price: 3499, image: img(36), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 37, name: 'Urban Blaze: Butter', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Urban Tech', price: 2599, image: img(37), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 38, name: 'Kanso V2: Emerald', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Cyber Sport', price: 2599, image: img(38), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 39, name: 'Souled: Outlast', brand: 'ZAPPIFY', category: 'Men Clogs', theme: 'Retro Classic', price: 2499, image: img(39), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 40, name: 'Mortal Kombat: Sub Zero', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Urban Tech', price: 3499, image: img(40), isTrending: true, description: 'Exclusive release from The Souled Store collection.' },
- { id: 41, name: 'Rovers: Black Panther', brand: 'ZAPPIFY', category: 'Men Mid Top Sneakers', theme: 'Urban Tech', price: 3499, image: img(41), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 42, name: 'Rovers: Deadpool', brand: 'ZAPPIFY', category: 'Men High Top Sneakers', theme: 'Urban Tech', price: 3499, image: img(42), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
- { id: 44, name: 'UBZ Ascend: Black', brand: 'ZAPPIFY', category: 'Men Low Top Sneakers', theme: 'Retro Classic', price: 3299, image: img(44), isTrending: false, description: 'Exclusive release from The Souled Store collection.' },
+ {
+ id: 105,
+ name: "Nike Journey Run",
+ brand: "NIKE",
+ category: "Running",
+ price: 6796,
+ image: require("../../assets/shoes/Nike Journey Run.jpg"),
+ description:
+ "Perfect for daily jogs, these shoes offer a smooth ride and great cushioning for every mile.",
+ },
+ {
+ id: 106,
+ name: "Nike Revolution 8 EasyOn",
+ brand: "NIKE",
+ category: "Running",
+ price: 4295,
+ image: require("../../assets/shoes/Nike Revolution 8 EasyOn.jpg"),
+ description:
+ "Designed for convenience with an EasyOn entry system, making it simple to get out and start running.",
+ },
+ {
+ id: 107,
+ name: "Nike Air Max Alpha Trainer 6",
+ brand: "NIKE",
+ category: "Training & Gym",
+ price: 8495,
+ image: require("../../assets/shoes/Nike Air Max Alpha Trainer 6.jpg"),
+ description:
+ "Stability meets style in this trainer, perfect for heavy lifts and explosive gym movements.",
+ },
+ {
+ id: 108,
+ name: "Nike Winflo 11",
+ brand: "NIKE",
+ category: "Running",
+ price: 6956,
+ image: require("../../assets/shoes/Nike Winflo 11.jpg"),
+ description:
+ "A reliable road runner with updated cushioning that provides a balanced and energetic feel.",
+ },
+ {
+ id: 109,
+ name: "Nike Quest 6",
+ brand: "NIKE",
+ category: "Running",
+ price: 7095,
+ image: require("../../assets/shoes/Nike Quest 6.jpg"),
+ description:
+ "Built for the long road ahead, offering a breathable mesh upper and durable traction.",
+ },
+ {
+ id: 110,
+ name: "Nike Killshot 2 Leather Premium",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 9195,
+ image: require("../../assets/shoes/Nike Killshot 2 Leather Premium.jpg"),
+ description:
+ "Inspired by classic tennis shoes, this leather premium edition brings a retro look to your street style.",
+ },
+ {
+ id: 111,
+ name: "LeBron Witness IX EP",
+ brand: "NIKE",
+ category: "Basketball",
+ price: 6956,
+ image: require("../../assets/shoes/LeBron Witness IX EP.jpg"),
+ description:
+ "Unleash your inner athlete with LeBron's signature performance and lockdown support on the court.",
+ },
+ {
+ id: 112,
+ name: "Nike Air Max Excee",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 7495,
+ image: require("../../assets/shoes/Nike Air Max Excee.jpg"),
+ description:
+ "Featuring a visible Air unit, these sneakers blend iconic design with modern everyday comfort.",
+ },
+ {
+ id: 113,
+ name: "Nike Downshifter 14",
+ brand: "NIKE",
+ category: "Running",
+ price: 4895,
+ image: require("../../assets/shoes/Nike Downshifter 14.jpg"),
+ description:
+ "An entry-level runner that doesn't compromise on support, ideal for beginners starting their journey.",
+ },
+ {
+ id: 114,
+ name: "Nike Air Max Dn Roam",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 16995,
+ image: require("../../assets/shoes/Nike Air Max Dn Roam.jpg"),
+ description:
+ "High-end style meets revolutionary Air technology in this bold, futuristic lifestyle sneaker.",
+ },
+ {
+ id: 115,
+ name: "Nike SB Zoom Blazer Low Pro GT",
+ brand: "NIKE",
+ category: "Skateboarding",
+ price: 6795,
+ image: require("../../assets/shoes/Nike SB Zoom Blazer Low Pro GT.jpg"),
+ description:
+ "Engineered for skaters, this low-profile shoe offers exceptional boardfeel and durability.",
+ },
+ {
+ id: 116,
+ name: "Air Jordan 1 Low SE",
+ brand: "NIKE",
+ category: "Jordan",
+ price: 11495,
+ image: require("../../assets/shoes/Air Jordan 1 Low SE.jpg"),
+ description:
+ "The timeless AJ1 look in a low-top silhouette, featuring premium materials and iconic colorways.",
+ },
+ {
+ id: 117,
+ name: "Nike Killshot 2 Leather",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 7995,
+ image: require("../../assets/shoes/Nike Killshot 2 Leather.jpg"),
+ description:
+ "A versatile wardrobe staple that pairs perfectly with jeans, offering a clean and polished finish.",
+ },
+ {
+ id: 118,
+ name: "Nike Run Defy",
+ brand: "NIKE",
+ category: "Running",
+ price: 3196,
+ image: require("../../assets/shoes/Nike Run Defy.jpg"),
+ description:
+ "Budget-friendly performance shoe that delivers comfort for short runs and daily wear.",
+ },
+ {
+ id: 119,
+ name: "Nike Promina",
+ brand: "NIKE",
+ category: "Walking",
+ price: 3996,
+ image: require("../../assets/shoes/Nike Promina.jpg"),
+ description:
+ "Specifically designed for walking, ensuring all-day comfort with a soft, cushioned midsole.",
+ },
+ {
+ id: 120,
+ name: "Nike P-6000",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 9695,
+ image: require("../../assets/shoes/Nike P-6000.jpg"),
+ description:
+ "A mash-up of past Pegasus sneakers, this model offers a ventilated, breathable and comfortable Y2K vibe.",
+ },
+ {
+ id: 121,
+ name: "Nike Ava Rover",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 11895,
+ image: require("../../assets/shoes/Nike Ava Rover.jpg"),
+ description:
+ "A bold and unique silhouette that stands out in any crowd, perfect for fashion-forward enthusiasts.",
+ },
+ {
+ id: 122,
+ name: "Nike Free Metcon 6",
+ brand: "NIKE",
+ category: "Training & Gym",
+ price: 10795,
+ image: require("../../assets/shoes/Nike Free Metcon 6.jpg"),
+ description:
+ "Combines the flexibility of Nike Free with the stability of Metcon for a truly all-in-one workout shoe.",
+ },
+ {
+ id: 123,
+ name: "Air Jordan 1 Mid",
+ brand: "NIKE",
+ category: "Jordan",
+ price: 11495,
+ image: require("../../assets/shoes/Air Jordan 1 Mid.jpg"),
+ description:
+ "The classic mid-top legend remains a favorite, delivering heritage style and premium comfort.",
+ },
+ {
+ id: 124,
+ name: "Nike Air Max 270",
+ brand: "NIKE",
+ category: "Lifestyle",
+ price: 13995,
+ image: require("../../assets/shoes/Nike Air Max 270.jpg"),
+ description:
+ "Boasting Nike's tallest heel bag yet, these sneakers offer a super-soft ride that feels as good as it looks.",
+ },
+
+ {
+ id: 201,
+ name: "Men's Street Runner Pro",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 7495,
+ image: require("../../assets/shoes/shoe1.jpg"),
+ description: "Lightweight and responsive, built for men who push the pace on every run.",
+ },
+ {
+ id: 202,
+ name: "Men's Urban Glide",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 8295,
+ image: require("../../assets/shoes/shoe2.jpg"),
+ description: "Sleek silhouette with premium cushioning, perfect for city streets.",
+ },
+ {
+ id: 203,
+ name: "Men's Court Dominator",
+ brand: "NIKE",
+ category: "Basketball",
+ gender: "MEN",
+ price: 9995,
+ image: require("../../assets/shoes/shoe3.jpg"),
+ description: "Ankle support and grip engineered for explosive court performance.",
+ },
+ {
+ id: 204,
+ name: "Men's Trail Blazer",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 8795,
+ image: require("../../assets/shoes/shoe4.jpg"),
+ description: "Rugged outsole and cushioned midsole for off-road adventures.",
+ },
+ {
+ id: 205,
+ name: "Men's Classic Low",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 6495,
+ image: require("../../assets/shoes/shoe5.jpg"),
+ description: "Timeless low-top design that pairs with any outfit effortlessly.",
+ },
+ {
+ id: 206,
+ name: "Men's Power Lift",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 9295,
+ image: require("../../assets/shoes/shoe6.jpg"),
+ description: "Flat, stable base designed for heavy lifts and gym sessions.",
+ },
+ {
+ id: 207,
+ name: "Men's Skate Edge",
+ brand: "NIKE",
+ category: "Skateboarding",
+ gender: "MEN",
+ price: 7195,
+ image: require("../../assets/shoes/shoe7.jpg"),
+ description: "Durable canvas upper with vulcanized sole for superior boardfeel.",
+ },
+ {
+ id: 208,
+ name: "Men's Air Cushion Max",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 12495,
+ image: require("../../assets/shoes/shoe8.jpg"),
+ description: "Max Air unit delivers all-day comfort with a bold, modern look.",
+ },
+ {
+ id: 209,
+ name: "Men's Sprint Elite",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 10995,
+ image: require("../../assets/shoes/shoe9.jpg"),
+ description: "Carbon-fiber inspired plate for explosive speed on race day.",
+ },
+ {
+ id: 210,
+ name: "Men's Retro High",
+ brand: "NIKE",
+ category: "Jordan",
+ gender: "MEN",
+ price: 13495,
+ image: require("../../assets/shoes/shoe10.jpg"),
+ description: "Heritage high-top silhouette with modern comfort upgrades.",
+ },
+ {
+ id: 211,
+ name: "Men's Flex Trainer",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 7895,
+ image: require("../../assets/shoes/shoe15.jpg"),
+ description: "Flexible grooves and breathable mesh for dynamic training sessions.",
+ },
+ {
+ id: 212,
+ name: "Men's Walk Comfort",
+ brand: "NIKE",
+ category: "Walking",
+ gender: "MEN",
+ price: 5495,
+ image: require("../../assets/shoes/shoe16.jpg"),
+ description: "Plush foam midsole and wide toe box for all-day walking comfort.",
+ },
+ {
+ id: 213,
+ name: "Men's Hoop Legend",
+ brand: "NIKE",
+ category: "Basketball",
+ gender: "MEN",
+ price: 11295,
+ image: require("../../assets/shoes/shoe17.jpg"),
+ description: "Zoom Air cushioning and herringbone traction for elite court play.",
+ },
+ {
+ id: 214,
+ name: "Men's Everyday Runner",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 5995,
+ image: require("../../assets/shoes/shoe18.jpg"),
+ description: "Reliable daily trainer with responsive foam and breathable upper.",
+ },
+ {
+ id: 215,
+ name: "Men's Street Classic",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 8995,
+ image: require("../../assets/shoes/shoe19.jpg"),
+ description: "Clean lines and premium leather for a polished street look.",
+ },
+ {
+ id: 216,
+ name: "Men's Zoom Speed",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 9495,
+ image: require("../../assets/shoes/shoe20.jpg"),
+ description: "Zoom Air unit in the forefoot for a snappy, fast-paced ride.",
+ },
+ {
+ id: 217,
+ name: "Men's Board King",
+ brand: "NIKE",
+ category: "Skateboarding",
+ gender: "MEN",
+ price: 6995,
+ image: require("../../assets/shoes/shoe21.jpg"),
+ description: "Reinforced toe cap and padded collar for skate park sessions.",
+ },
+ {
+ id: 218,
+ name: "Men's Gym Beast",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 10295,
+ image: require("../../assets/shoes/shoe22.jpg"),
+ description: "Wide platform and locked-down fit for heavy compound movements.",
+ },
+ {
+ id: 219,
+ name: "Men's Air Retro 90",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 11995,
+ image: require("../../assets/shoes/shoe23.jpg"),
+ description: "90s-inspired design with modern Air cushioning for everyday wear.",
+ },
+ {
+ id: 220,
+ name: "Men's Jordan Legacy",
+ brand: "NIKE",
+ category: "Jordan",
+ gender: "MEN",
+ price: 14995,
+ image: require("../../assets/shoes/shoe24.jpg"),
+ description: "Iconic Jordan DNA with premium materials and heritage colorways.",
+ },
+ {
+ id: 221,
+ name: "Men's Long Run",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 8195,
+ image: require("../../assets/shoes/shoe25.jpg"),
+ description: "Extra cushioning and energy return for marathon-distance training.",
+ },
+ {
+ id: 222,
+ name: "Men's Low Rider",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 7295,
+ image: require("../../assets/shoes/shoe26.jpg"),
+ description: "Low-profile design with suede overlays for a premium casual look.",
+ },
+ {
+ id: 223,
+ name: "Men's Dunk Force",
+ brand: "NIKE",
+ category: "Basketball",
+ gender: "MEN",
+ price: 10495,
+ image: require("../../assets/shoes/shoe27.jpg"),
+ description: "Dunk-inspired silhouette with modern cushioning for on and off court.",
+ },
+ {
+ id: 224,
+ name: "Men's Cross Trainer",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 8695,
+ image: require("../../assets/shoes/shoe28.jpg"),
+ description: "Versatile trainer built for HIIT, agility drills, and gym work.",
+ },
+ {
+ id: 225,
+ name: "Men's Hike Ready",
+ brand: "NIKE",
+ category: "Walking",
+ gender: "MEN",
+ price: 9195,
+ image: require("../../assets/shoes/shoe29.jpg"),
+ description: "Grippy outsole and waterproof upper for light trail and urban hikes.",
+ },
+ {
+ id: 226,
+ name: "Men's Pegasus Next",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 11495,
+ image: require("../../assets/shoes/shoe30.jpg"),
+ description: "Next-gen Pegasus with React foam and wider fit for long-distance comfort.",
+ },
+ {
+ id: 227,
+ name: "Men's Skate Pro",
+ brand: "NIKE",
+ category: "Skateboarding",
+ gender: "MEN",
+ price: 7595,
+ image: require("../../assets/shoes/shoe31.jpg"),
+ description: "Pro-level skate shoe with Zoom Air for impact protection.",
+ },
+ {
+ id: 228,
+ name: "Men's Air Force Classic",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 10995,
+ image: require("../../assets/shoes/shoe32.jpg"),
+ description: "The all-time classic AF1 silhouette in a fresh men's colorway.",
+ },
+ {
+ id: 229,
+ name: "Men's React Infinity",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 13995,
+ image: require("../../assets/shoes/shoe33.jpg"),
+ description: "React foam and wide base designed to reduce injury risk on long runs.",
+ },
+ {
+ id: 230,
+ name: "Men's Jordan Flight",
+ brand: "NIKE",
+ category: "Jordan",
+ gender: "MEN",
+ price: 12995,
+ image: require("../../assets/shoes/shoe34.jpg"),
+ description: "Flight-inspired Jordan with lightweight upper and responsive cushioning.",
+ },
+ {
+ id: 231,
+ name: "Men's Metcon Power",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 11295,
+ image: require("../../assets/shoes/shoe35.jpg"),
+ description: "Metcon stability meets Free flexibility for the ultimate cross-training shoe.",
+ },
+ {
+ id: 232,
+ name: "Men's Blazer Mid",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 9495,
+ image: require("../../assets/shoes/shoe36.jpg"),
+ description: "Mid-top Blazer with vintage basketball DNA and everyday wearability.",
+ },
+ {
+ id: 233,
+ name: "Men's Vomero Plush",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 14495,
+ image: require("../../assets/shoes/shoe37.jpg"),
+ description: "Maximum cushioning Vomero for plush, comfortable long-distance runs.",
+ },
+ {
+ id: 234,
+ name: "Men's Court Vision",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 7995,
+ image: require("../../assets/shoes/shoe38.jpg"),
+ description: "Court-inspired low-top with clean leather upper for everyday style.",
+ },
+ {
+ id: 235,
+ name: "Men's Invincible 3",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 16995,
+ image: require("../../assets/shoes/shoe39.jpg"),
+ description: "Nike's most cushioned running shoe for recovery and easy-day runs.",
+ },
+ {
+ id: 236,
+ name: "Men's Alphafly Next",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 19995,
+ image: require("../../assets/shoes/shoe40.jpg"),
+ description: "Elite race-day shoe with ZoomX foam and carbon fiber plate.",
+ },
+ {
+ id: 237,
+ name: "Men's Dri-FIT Trainer",
+ brand: "NIKE",
+ category: "Training & Gym",
+ gender: "MEN",
+ price: 8495,
+ image: require("../../assets/shoes/shoe41.jpg"),
+ description: "Breathable Dri-FIT upper keeps feet cool during intense workouts.",
+ },
+ {
+ id: 238,
+ name: "Men's SB Nyjah",
+ brand: "NIKE",
+ category: "Skateboarding",
+ gender: "MEN",
+ price: 8995,
+ image: require("../../assets/shoes/shoe42.jpg"),
+ description: "Nyjah Huston's signature skate shoe with Zoom Air and durable build.",
+ },
+ {
+ id: 239,
+ name: "Men's Air Max 97",
+ brand: "NIKE",
+ category: "Lifestyle",
+ gender: "MEN",
+ price: 15995,
+ image: require("../../assets/shoes/shoe43.jpg"),
+ description: "Full-length Air unit and bullet-train inspired design for iconic style.",
+ },
+ {
+ id: 240,
+ name: "Men's Zoom Rival",
+ brand: "NIKE",
+ category: "Running",
+ gender: "MEN",
+ price: 6295,
+ image: require("../../assets/shoes/shoe44.jpg"),
+ description: "Track-inspired road runner with Zoom Air for competitive training.",
+ },
];
diff --git a/mobile/src/screens/AccountScreen.js b/mobile/src/screens/AccountScreen.js
index cd41b61..ca6bdaf 100644
--- a/mobile/src/screens/AccountScreen.js
+++ b/mobile/src/screens/AccountScreen.js
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import { useState, useEffect } from 'react';
import { View, Text, Image, ScrollView, TouchableOpacity, StyleSheet, Alert, Modal } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
@@ -17,19 +17,11 @@ export default function AccountScreen({ navigation }) {
const [cancelReason, setCancelReason] = useState('');
const [showConfirm, setShowConfirm] = useState(false);
- if (!user) {
- return (
-
-
-
- You're not logged in
- navigation.navigate('Login')}>
- LOGIN / SIGN UP
-
-
-
- );
- }
+ useEffect(() => {
+ if (!user) navigation.replace('Login');
+ }, [user]);
+
+ if (!user) return null;
const handleCancelConfirm = () => {
if (!cancelReason) { Alert.alert('Select Reason', 'Please select a reason'); return; }
@@ -84,7 +76,7 @@ export default function AccountScreen({ navigation }) {
) : (
orders.map((order, i) => (
{ setSelectedOrder(order); setView('detail'); }}>
-
+
{order.name}
Size: UK {order.size} · Qty: {order.qty}
@@ -114,7 +106,7 @@ export default function AccountScreen({ navigation }) {
Date: {formatDate(selectedOrder.placedAt)}
-
+
{selectedOrder.name}
Size: UK {selectedOrder.size} · Qty: {selectedOrder.qty}
@@ -212,10 +204,6 @@ const styles = StyleSheet.create({
statusTxtCancelled: { color: colors.danger },
logoutBtn: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 8, borderWidth: 1.5, borderColor: colors.border, borderRadius: 12, paddingVertical: 14, marginTop: 8 },
logoutTxt: { fontSize: 13, fontWeight: '700', color: colors.gray, letterSpacing: 1 },
- guestBox: { flex: 1, alignItems: 'center', justifyContent: 'center', gap: 16 },
- guestTitle: { fontSize: 16, fontWeight: '700', color: colors.gray },
- loginBtn: { backgroundColor: colors.brand, paddingHorizontal: 32, paddingVertical: 14, borderRadius: 12 },
- loginBtnTxt: { color: colors.white, fontWeight: '800', fontSize: 14, letterSpacing: 1 },
odHeader: { backgroundColor: colors.lightGray, borderRadius: 10, padding: 14, gap: 4 },
odLabel: { fontSize: 13, color: colors.gray },
odVal: { fontWeight: '700', color: colors.dark },
diff --git a/mobile/src/screens/CartScreen.js b/mobile/src/screens/CartScreen.js
index 429fc3d..0d0fabf 100644
--- a/mobile/src/screens/CartScreen.js
+++ b/mobile/src/screens/CartScreen.js
@@ -1,4 +1,3 @@
-import React from 'react';
import { View, Text, FlatList, Image, TouchableOpacity, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
@@ -44,7 +43,7 @@ export default function CartScreen({ navigation }) {
contentContainerStyle={styles.list}
renderItem={({ item }) => (
-
+
{item.name}
Size: UK {item.size} · Qty: {item.qty}
@@ -95,10 +94,10 @@ const styles = StyleSheet.create({
totalRow: { paddingTop: 8, borderTopWidth: 1, borderTopColor: colors.border, marginTop: 4 },
totalLabel: { fontSize: 16, fontWeight: '800', color: colors.dark },
totalVal: { fontSize: 18, fontWeight: '900', color: colors.dark },
- checkoutBtn: { backgroundColor: colors.brand, borderRadius: 14, paddingVertical: 16, alignItems: 'center', marginTop: 8 },
+ checkoutBtn: { backgroundColor: '#D83100', borderRadius: 14, paddingVertical: 16, alignItems: 'center', marginTop: 8 },
checkoutTxt: { color: colors.white, fontWeight: '800', fontSize: 14, letterSpacing: 1 },
empty: { flex: 1, alignItems: 'center', justifyContent: 'center', gap: 16 },
emptyTitle: { fontSize: 16, fontWeight: '700', color: colors.gray },
- shopBtn: { backgroundColor: colors.brand, paddingHorizontal: 24, paddingVertical: 12, borderRadius: 10 },
+ shopBtn: { backgroundColor: '#D83100', paddingHorizontal: 24, paddingVertical: 12, borderRadius: 10 },
shopBtnTxt: { color: colors.white, fontWeight: '700', fontSize: 13 },
});
diff --git a/mobile/src/screens/CheckoutScreen.js b/mobile/src/screens/CheckoutScreen.js
index 654b1ec..c705114 100644
--- a/mobile/src/screens/CheckoutScreen.js
+++ b/mobile/src/screens/CheckoutScreen.js
@@ -1,9 +1,13 @@
-import React, { useState } from 'react';
+import { useState, Fragment } from 'react';
import { View, Text, ScrollView, TouchableOpacity, TextInput, StyleSheet, Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
import { colors } from '../theme/colors';
import { useApp } from '../context/AppContext';
+import RazorpayCheckout from 'react-native-razorpay';
+
+const API_URL = 'https://zappify-dz5a.vercel.app';
+const RAZORPAY_KEY_ID = 'rzp_test_SZtLthHdKYuLeQ';
const STEPS = ['MY BAG', 'ADDRESS', 'PAYMENT'];
const PAYMENT_OPTIONS = [
@@ -21,8 +25,54 @@ export default function CheckoutScreen({ navigation }) {
const shipping = cartTotal > 999 ? 0 : 99;
const handlePlaceOrder = async () => {
- await placeOrder(cartItems);
- setDone(true);
+ if (payment === 'cod') {
+ await placeOrder(cartItems);
+ setDone(true);
+ return;
+ }
+ try {
+ const res = await fetch(`${API_URL}/api/payment/create-order`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ amount: cartTotal + shipping }),
+ });
+ const data = await res.json();
+
+ const options = {
+ description: 'Shoe Purchase',
+ image: 'https://zappify-sepia.vercel.app/logo.png',
+ currency: 'INR',
+ key: RAZORPAY_KEY_ID,
+ amount: data.amount,
+ order_id: data.orderId,
+ name: 'Zappify',
+ prefill: { contact: address.phone, name: address.name },
+ theme: { color: '#D83100' },
+ };
+
+ RazorpayCheckout.open(options)
+ .then(async (response) => {
+ const verifyRes = await fetch(`${API_URL}/api/payment/verify`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(response),
+ });
+ const verifyData = await verifyRes.json();
+ if (verifyData.success) {
+ await placeOrder(cartItems);
+ setDone(true);
+ } else {
+ Alert.alert('Failed', 'Payment verification failed.');
+ }
+ })
+ .catch((error) => {
+ if (error.code !== 'PAYMENT_CANCELLED') {
+ Alert.alert('Payment Failed', error.description || 'Something went wrong.');
+ }
+ });
+ } catch {
+ Alert.alert('Error', 'Could not connect to server. Is backend running?');
+ }
};
if (done) {
@@ -48,7 +98,7 @@ export default function CheckoutScreen({ navigation }) {
{STEPS.map((s, i) => (
-
+
{i < step
@@ -59,7 +109,7 @@ export default function CheckoutScreen({ navigation }) {
{s}
{i < STEPS.length - 1 && }
-
+
))}
@@ -91,14 +141,14 @@ export default function CheckoutScreen({ navigation }) {
DELIVERY ADDRESS
- setAddress({ ...address, name: v })} />
- setAddress({ ...address, phone: v })} keyboardType="phone-pad" />
+ setAddress({ ...address, name: v })} />
+ setAddress({ ...address, phone: v })} keyboardType="phone-pad" />
- setAddress({ ...address, street: v })} />
+ setAddress({ ...address, street: v })} />
- setAddress({ ...address, pincode: v })} keyboardType="numeric" />
- setAddress({ ...address, city: v })} />
- setAddress({ ...address, state: v })} />
+ setAddress({ ...address, pincode: v })} keyboardType="numeric" />
+ setAddress({ ...address, city: v })} />
+ setAddress({ ...address, state: v })} />
setStep(0)}>BACK
@@ -148,15 +198,14 @@ const styles = StyleSheet.create({
title: { fontSize: 16, fontWeight: '800', letterSpacing: 1.5, color: colors.dark },
stepsRow: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 20, paddingVertical: 16 },
stepItem: { alignItems: 'center', gap: 4 },
- stepCircle: { width: 28, height: 28, borderRadius: 14, borderWidth: 2, borderColor: colors.border, alignItems: 'center', justifyContent: 'center' },
- stepCircleActive: { borderColor: colors.brand },
- stepCircleDone: { backgroundColor: colors.brand, borderColor: colors.brand },
+ stepCircleDone: { backgroundColor: '#D83100', borderColor: '#D83100' },
+ stepCircleActive: { borderColor: '#D83100' },
stepNum: { fontSize: 12, fontWeight: '700', color: colors.gray },
- stepNumActive: { color: colors.brand },
+ stepNumActive: { color: '#D83100' },
stepLabel: { fontSize: 10, fontWeight: '700', color: colors.gray, letterSpacing: 0.5 },
- stepLabelActive: { color: colors.brand },
+ stepLabelActive: { color: '#D83100' },
stepLine: { flex: 1, height: 2, backgroundColor: colors.border, marginBottom: 16 },
- stepLineDone: { backgroundColor: colors.brand },
+ stepLineDone: { backgroundColor: '#D83100' },
body: { padding: 20, paddingBottom: 40 },
bagItem: { flexDirection: 'row', justifyContent: 'space-between', paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: colors.border },
bagInfo: { flex: 1 },
@@ -170,7 +219,7 @@ const styles = StyleSheet.create({
totalRow: { paddingTop: 8, borderTopWidth: 1, borderTopColor: colors.border, marginTop: 4 },
totalLabel: { fontSize: 15, fontWeight: '800', color: colors.dark },
totalVal: { fontSize: 16, fontWeight: '900', color: colors.dark },
- nextBtn: { flex: 1, backgroundColor: colors.brand, borderRadius: 12, paddingVertical: 14, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 6 },
+ nextBtn: { flex: 1, backgroundColor: '#D83100', borderRadius: 12, paddingVertical: 14, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 6 },
nextTxt: { color: colors.white, fontWeight: '800', fontSize: 13, letterSpacing: 0.5 },
btnRow: { flexDirection: 'row', gap: 10, marginTop: 8 },
backBtn: { paddingHorizontal: 20, paddingVertical: 14, borderRadius: 12, borderWidth: 1.5, borderColor: colors.border, alignItems: 'center', justifyContent: 'center' },
@@ -179,15 +228,15 @@ const styles = StyleSheet.create({
formRow: { flexDirection: 'row', gap: 10 },
input: { borderWidth: 1.5, borderColor: colors.border, borderRadius: 10, paddingHorizontal: 14, paddingVertical: 12, fontSize: 14, color: colors.dark, marginBottom: 12 },
payOption: { flexDirection: 'row', alignItems: 'center', gap: 12, padding: 14, borderWidth: 1.5, borderColor: colors.border, borderRadius: 12, marginBottom: 10 },
- payOptionActive: { borderColor: colors.brand, backgroundColor: colors.brandLight },
+ payOptionActive: { borderColor: '#D83100', backgroundColor: 'rgba(216,49,0,0.06)' },
radio: { width: 18, height: 18, borderRadius: 9, borderWidth: 2, borderColor: colors.border, alignItems: 'center', justifyContent: 'center' },
- radioActive: { borderColor: colors.brand },
- radioDot: { width: 8, height: 8, borderRadius: 4, backgroundColor: colors.brand },
+ radioActive: { borderColor: '#D83100' },
+ radioDot: { width: 8, height: 8, borderRadius: 4, backgroundColor: '#D83100' },
payLabel: { fontSize: 14, fontWeight: '500', color: colors.dark },
successBox: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 32, gap: 16 },
- successIcon: { width: 72, height: 72, borderRadius: 36, backgroundColor: colors.brand, alignItems: 'center', justifyContent: 'center' },
+ successIcon: { width: 72, height: 72, borderRadius: 36, backgroundColor: '#D83100', alignItems: 'center', justifyContent: 'center' },
successTitle: { fontSize: 24, fontWeight: '800', color: colors.dark },
successMsg: { fontSize: 14, color: colors.gray, textAlign: 'center', lineHeight: 22 },
- continueBtn: { backgroundColor: colors.brand, paddingHorizontal: 32, paddingVertical: 14, borderRadius: 12, marginTop: 8 },
+ continueBtn: { backgroundColor: '#D83100', paddingHorizontal: 32, paddingVertical: 14, borderRadius: 12, marginTop: 8 },
continueTxt: { color: colors.white, fontWeight: '800', fontSize: 14, letterSpacing: 1 },
});
diff --git a/mobile/src/screens/HomeScreen.js b/mobile/src/screens/HomeScreen.js
index 3b6e420..a27072f 100644
--- a/mobile/src/screens/HomeScreen.js
+++ b/mobile/src/screens/HomeScreen.js
@@ -1,5 +1,5 @@
-import React, { useState, useMemo } from 'react';
-import { View, Text, FlatList, TextInput, TouchableOpacity, StyleSheet, StatusBar } from 'react-native';
+import { useState, useMemo } from 'react';
+import { View, Text, FlatList, TextInput, TouchableOpacity, StyleSheet, StatusBar, Image, Modal } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
import { ALL_PRODUCTS } from '../data/products';
@@ -7,82 +7,137 @@ import { colors } from '../theme/colors';
import ProductCard from '../components/ProductCard';
import { useApp } from '../context/AppContext';
-const CATEGORIES = ['All', 'Men Low Top Sneakers', 'Men High Top Sneakers', 'Men Mid Top Sneakers', 'Men Clogs', 'Men Slip-ons'];
+const CATEGORIES = ['Running', 'Lifestyle', 'Basketball', 'Training & Gym', 'Jordan', 'Skateboarding', 'Walking'];
+const GENDER_TABS = ['ALL', 'MEN', 'SNEAKERS'];
export default function HomeScreen({ navigation }) {
const [search, setSearch] = useState('');
- const [activeCategory, setActiveCategory] = useState('All');
- const { cartCount, wishlistItems, user } = useApp();
+ const [activeGender, setActiveGender] = useState('ALL');
+ const [showNikeBanner, setShowNikeBanner] = useState(false);
+ const [showFilter, setShowFilter] = useState(false);
+ const [selectedCategories, setSelectedCategories] = useState([]);
+ const { cartCount, wishlistItems } = useApp();
const filtered = useMemo(() => {
- return ALL_PRODUCTS.filter(p => {
- const catMatch = activeCategory === 'All' || p.category === activeCategory;
- const searchMatch = search.trim() === '' ||
- p.name.toLowerCase().includes(search.toLowerCase()) ||
- p.brand.toLowerCase().includes(search.toLowerCase());
- return catMatch && searchMatch;
- });
- }, [search, activeCategory]);
+ const catMatch = (p) => selectedCategories.length === 0 || selectedCategories.includes(p.category);
- return (
-
-
+ const searchMatch = (p) => {
+ if (search.trim() === '') return true;
+ const q = search.toLowerCase();
+ return p.name.toLowerCase().indexOf(q) !== -1 || p.brand.toLowerCase().indexOf(q) !== -1;
+ };
+
+ if (showNikeBanner) {
+ return ALL_PRODUCTS.filter(p => p.brand === 'NIKE' && !p.gender && catMatch(p) && searchMatch(p));
+ }
+
+ if (activeGender === 'MEN') {
+ const menProducts = ALL_PRODUCTS.filter(p => p.gender === 'MEN' && catMatch(p) && searchMatch(p));
+ const nikeOriginal = ALL_PRODUCTS.filter(p => !p.gender && catMatch(p) && searchMatch(p));
+ return [...menProducts, ...nikeOriginal];
+ }
+ if (activeGender === 'SNEAKERS') {
+ return ALL_PRODUCTS.filter(p => p.brand === 'NIKE' && !p.gender && catMatch(p) && searchMatch(p));
+ }
+
+ return ALL_PRODUCTS.filter(p => catMatch(p) && searchMatch(p));
+ }, [search, activeGender, showNikeBanner, selectedCategories]);
+
+ const renderHeader = () => (
+
- Z appify
+
+ Z
+ appify
+
navigation.navigate('Wishlist')}>
- {wishlistItems.length > 0 && {wishlistItems.length} }
+ {wishlistItems.length > 0 && }
navigation.navigate('Cart')}>
-
- {cartCount > 0 && {cartCount} }
+
+ {cartCount > 0 && }
navigation.navigate('Account')}>
- {user
- ? {user.name[0]}
- :
- }
+
-
-
-
- {search.length > 0 && (
- setSearch('')}>
-
-
- )}
+
+
+
+
+
+ setShowFilter(true)}>
+
+
- item}
- style={styles.catList}
- contentContainerStyle={{ paddingHorizontal: 16, paddingVertical: 6, alignItems: 'center' }}
- renderItem={({ item }) => (
+ {!search && (
+
+
+ SPRING COLLECTION 2026
+ Experience The{'\n'}Future of{'\n'}Streetwear
+ Unmatched comfort. Uncompromising style. Crafted for those who move.
+ { setShowNikeBanner(true); setSearch('Nike'); }}>
+ EXPLORE NOW
+
+
+
+
+
+
+ )}
+
+
+ {GENDER_TABS.map(tab => (
setActiveCategory(item)}
+ key={tab}
+ style={[styles.genderTab, activeGender === tab && styles.genderTabActive]}
+ onPress={() => { setActiveGender(tab); setShowNikeBanner(false); setSearch(''); }}
>
- {item}
+
+ {tab}
+
- )}
- />
+ ))}
+
+
+ {showNikeBanner && (
+
+
+ SPRING COLLECTION 2026
+ 20 Iconic{'\n'}Nike Shoes
+ Handpicked for you
+ { setShowNikeBanner(false); setSearch(''); }}>
+ ← Back to All
+
+
+
+
+ )}
+
+ );
+ return (
+
+
item.id.toString()}
numColumns={2}
contentContainerStyle={styles.grid}
@@ -93,33 +148,104 @@ export default function HomeScreen({ navigation }) {
)}
ListEmptyComponent={
- No products found
+
+ No kicks found for your search
}
/>
+
+
+
+
+
+ CATEGORIES
+ setShowFilter(false)}>
+
+
+
+ {CATEGORIES.map(cat => (
+ {
+ if (selectedCategories.includes(cat)) {
+ setSelectedCategories(selectedCategories.filter(c => c !== cat));
+ } else {
+ setSelectedCategories([...selectedCategories, cat]);
+ }
+ }}
+ >
+
+ {selectedCategories.includes(cat) && }
+
+ {cat}
+
+ ))}
+
+ setSelectedCategories([])}>
+ Clear All
+
+ setShowFilter(false)}>
+ Apply
+
+
+
+
+
);
}
const styles = StyleSheet.create({
- safe: { flex: 1, backgroundColor: colors.white },
- header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 12 },
- logo: { fontSize: 22, fontWeight: '800', color: colors.dark },
- logoZ: { color: colors.brand },
+ safe: { flex: 1, backgroundColor: colors.lightGray },
+ header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 20, paddingVertical: 12, backgroundColor: colors.white, borderBottomWidth: 1, borderBottomColor: colors.border },
+ logoRow: { flexDirection: 'row', alignItems: 'center' },
+ logoZ: { fontSize: 26, fontWeight: '900', color: '#FF6B00', letterSpacing: -1 },
+ logoRest: { fontSize: 26, fontWeight: '900', color: colors.dark, letterSpacing: -1 },
headerActions: { flexDirection: 'row', gap: 8 },
- iconBtn: { padding: 6, position: 'relative' },
- badge: { position: 'absolute', top: 0, right: 0, backgroundColor: colors.brand, borderRadius: 8, minWidth: 16, height: 16, alignItems: 'center', justifyContent: 'center' },
- badgeText: { color: colors.white, fontSize: 10, fontWeight: '700' },
- avatarSmall: { width: 28, height: 28, borderRadius: 14, backgroundColor: colors.brand, alignItems: 'center', justifyContent: 'center' },
- searchBar: { flexDirection: 'row', alignItems: 'center', backgroundColor: colors.lightGray, marginHorizontal: 16, borderRadius: 12, paddingHorizontal: 12, paddingVertical: 10, gap: 8, marginBottom: 8 },
- searchInput: { flex: 1, fontSize: 14, color: colors.dark },
- catList: { marginBottom: 10, maxHeight: 48 },
- catChip: { paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20, backgroundColor: colors.lightGray, marginRight: 8, height: 36, justifyContent: 'center' },
- catChipActive: { backgroundColor: colors.brand },
- catText: { fontSize: 12, fontWeight: '600', color: colors.gray },
- catTextActive: { color: colors.white },
- grid: { paddingHorizontal: 12, paddingBottom: 20 },
- row: { justifyContent: 'space-between' },
- empty: { alignItems: 'center', marginTop: 60 },
- emptyText: { color: colors.gray, fontSize: 15 },
+ iconBtn: { width: 38, height: 38, borderRadius: 19, backgroundColor: colors.lightGray, alignItems: 'center', justifyContent: 'center' },
+ badge: { position: 'absolute', top: 8, right: 8, width: 8, height: 8, borderRadius: 4, backgroundColor: '#D83100', borderWidth: 1.5, borderColor: colors.white },
+ searchContainer: { flexDirection: 'row', paddingHorizontal: 20, gap: 12, marginBottom: 20 },
+ searchBar: { flex: 1, flexDirection: 'row', alignItems: 'center', backgroundColor: colors.white, borderRadius: 15, paddingHorizontal: 15, height: 50, gap: 10, shadowColor: colors.dark, shadowOpacity: 0.05, shadowRadius: 10, elevation: 2 },
+ searchInput: { flex: 1, fontSize: 15, color: colors.dark, fontWeight: '500' },
+ filterBtn: { width: 50, height: 50, borderRadius: 15, backgroundColor: colors.dark, alignItems: 'center', justifyContent: 'center' },
+ heroContainer: { marginHorizontal: 20, height: 200, borderRadius: 20, overflow: 'hidden', marginBottom: 15, backgroundColor: '#000000', flexDirection: 'row', shadowColor: '#000000', shadowOpacity: 0.3, shadowRadius: 15, elevation: 8 },
+ heroLeft: { flex: 1.3, padding: 16, justifyContent: 'center' },
+ heroRight: { flex: 1, overflow: 'hidden', justifyContent: 'center', alignItems: 'center' },
+ heroImage: { width: '120%', height: '120%', transform: [{ rotate: '-5deg' }] },
+ heroTag: { color: '#FF6B00', fontSize: 9, fontWeight: '900', letterSpacing: 1.5, marginBottom: 6, textTransform: 'uppercase' },
+ heroTitle: { color: colors.white, fontSize: 16, fontWeight: '900', lineHeight: 20, marginBottom: 6 },
+ heroSubtitle: { color: '#94A3B8', fontSize: 11, fontWeight: '500', lineHeight: 15, marginBottom: 10 },
+ heroBtn: { backgroundColor: '#FF6B00', paddingHorizontal: 16, paddingVertical: 9, borderRadius: 20, alignSelf: 'flex-start' },
+ heroBtnText: { color: colors.white, fontSize: 11, fontWeight: '900', letterSpacing: 0.5 },
+ genderTabsRow: { flexDirection: 'row', paddingHorizontal: 20, marginBottom: 14, gap: 10 },
+ genderTab: { flex: 1, paddingVertical: 10, borderRadius: 12, backgroundColor: colors.white, borderWidth: 1.5, borderColor: colors.border, alignItems: 'center' },
+ genderTabActive: { backgroundColor: '#D83100', borderColor: '#D83100' },
+ genderTabText: { fontSize: 14, fontWeight: '800', color: colors.gray, letterSpacing: 1 },
+ genderTabTextActive: { color: colors.white },
+ nikeBanner: { marginHorizontal: 16, marginBottom: 14, backgroundColor: '#000', borderRadius: 16, padding: 18, flexDirection: 'row', alignItems: 'center', overflow: 'hidden' },
+ nikeBannerContent: { flex: 1 },
+ nikeBannerTag: { color: '#FF6B00', fontSize: 9, fontWeight: '800', letterSpacing: 2, marginBottom: 6, textTransform: 'uppercase' },
+ nikeBannerTitle: { color: '#fff', fontSize: 20, fontWeight: '900', lineHeight: 24, marginBottom: 4 },
+ nikeBannerSub: { color: '#64748B', fontSize: 12, marginBottom: 12 },
+ nikeBannerBtn: { borderWidth: 1.5, borderColor: '#333', borderRadius: 20, paddingHorizontal: 14, paddingVertical: 6, alignSelf: 'flex-start' },
+ nikeBannerBtnTxt: { color: '#aaa', fontSize: 11, fontWeight: '700' },
+ nikeBannerImg: { width: 110, height: 100, transform: [{ rotate: '-8deg' }] },
+ grid: { paddingBottom: 20 },
+ row: { paddingHorizontal: 15, justifyContent: 'space-between' },
+ empty: { alignItems: 'center', marginTop: 100, gap: 10 },
+ emptyText: { color: colors.gray, fontSize: 14, fontWeight: '500' },
+ filterOverlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'flex-end' },
+ filterSheet: { backgroundColor: colors.white, borderTopLeftRadius: 24, borderTopRightRadius: 24, padding: 24, paddingBottom: 40 },
+ filterSheetHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 },
+ filterSheetTitle: { fontSize: 14, fontWeight: '800', letterSpacing: 1.5, color: colors.dark },
+ filterOption: { flexDirection: 'row', alignItems: 'center', gap: 14, paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: colors.border },
+ filterCheck: { width: 22, height: 22, borderRadius: 6, borderWidth: 2, borderColor: colors.border, alignItems: 'center', justifyContent: 'center' },
+ filterCheckActive: { backgroundColor: '#D83100', borderColor: '#D83100' },
+ filterOptionTxt: { fontSize: 15, fontWeight: '600', color: colors.dark },
+ filterBtnRow: { flexDirection: 'row', gap: 12, marginTop: 20 },
+ filterClearBtn: { flex: 1, paddingVertical: 14, borderRadius: 12, borderWidth: 1.5, borderColor: colors.border, alignItems: 'center' },
+ filterClearTxt: { fontSize: 13, fontWeight: '700', color: colors.gray },
+ filterApplyBtn: { flex: 2, paddingVertical: 14, borderRadius: 12, backgroundColor: '#D83100', alignItems: 'center' },
+ filterApplyTxt: { fontSize: 13, fontWeight: '800', color: colors.white, letterSpacing: 0.5 },
});
diff --git a/mobile/src/screens/LoginScreen.js b/mobile/src/screens/LoginScreen.js
index 20d2258..1dbc35d 100644
--- a/mobile/src/screens/LoginScreen.js
+++ b/mobile/src/screens/LoginScreen.js
@@ -1,7 +1,6 @@
-import React, { useState } from 'react';
-import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert, KeyboardAvoidingView, Platform, ScrollView } from 'react-native';
+import { useState, useEffect } from 'react';
+import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert, KeyboardAvoidingView, Platform, ScrollView, Image } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
-import { Ionicons } from '@expo/vector-icons';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { colors } from '../theme/colors';
import { useApp } from '../context/AppContext';
@@ -25,6 +24,14 @@ export default function LoginScreen({ navigation }) {
const [form, setForm] = useState({ name: '', email: '', password: '', confirm: '' });
const { login } = useApp();
+ useEffect(() => {
+ const checkUser = async () => {
+ const saved = await AsyncStorage.getItem('zappify_user');
+ if (saved) navigation.replace('Home');
+ };
+ checkUser();
+ }, []);
+
const handleGoogleSignIn = async () => {
if (!GoogleSignin) {
Alert.alert('Not Available', 'Google Sign In is only available in the production build.');
@@ -39,7 +46,7 @@ export default function LoginScreen({ navigation }) {
picture: userInfo.data.user.photo,
};
await login(user);
- navigation.goBack();
+ navigation.replace('Home');
} catch (error) {
if (error.code === statusCodes.SIGN_IN_CANCELLED) return;
if (error.code === statusCodes.IN_PROGRESS) return;
@@ -55,14 +62,14 @@ export default function LoginScreen({ navigation }) {
if (form.password.length < 6) { Alert.alert('Error', 'Password must be at least 6 characters'); return; }
const user = { name: form.name, email: form.email, picture: null };
await login(user);
- navigation.goBack();
+ navigation.replace('Home');
} else {
const saved = await AsyncStorage.getItem('zappify_user');
if (saved) {
const u = JSON.parse(saved);
if (u.email === form.email) {
await login(u);
- navigation.goBack();
+ navigation.replace('Home');
} else {
Alert.alert('Error', 'Account not found. Please sign up first.');
}
@@ -75,43 +82,62 @@ export default function LoginScreen({ navigation }) {
return (
-
-
-
+
+
+
+
+ navigation.replace('Home')}>
+ SKIP
+
+
+ ZAPPIFY
+ Premium{'\n'}Footwear
+ Step into the future
+
- {isSignUp ? 'Create Account' : 'Welcome Back'}
- {isSignUp ? 'Join Zappify today' : 'Login to your Zappify account'}
- {isSignUp && (
- setForm({ ...form, name: v })} />
- )}
- setForm({ ...form, email: v })} keyboardType="email-address" autoCapitalize="none" />
- setForm({ ...form, password: v })} secureTextEntry />
- {isSignUp && (
- setForm({ ...form, confirm: v })} secureTextEntry />
- )}
+
+ {isSignUp ? 'Create Account' : 'Welcome Back'}
+ {isSignUp ? 'Join Zappify today' : 'Login to your Zappify account'}
-
- {isSignUp ? 'CREATE ACCOUNT' : 'SIGN IN'}
-
+ {isSignUp && (
+ setForm({ ...form, name: v })} />
+ )}
+ setForm({ ...form, email: v })} keyboardType="email-address" autoCapitalize="none" />
+ setForm({ ...form, password: v })} secureTextEntry />
+ {isSignUp && (
+ setForm({ ...form, confirm: v })} secureTextEntry />
+ )}
-
-
- OR CONTINUE WITH
-
-
+
+ {isSignUp ? 'CREATE ACCOUNT' : 'SIGN IN'}
+
-
- G
- {isSignUp ? 'Sign up with Google' : 'Sign in with Google'}
-
+
+
+ OR
+
+
+
+
+
+ G
+
+ Continue with Google
+
+
+ setIsSignUp(!isSignUp)}>
+
+ {isSignUp ? 'Already have an account? ' : "Don't have an account? "}
+ {isSignUp ? 'Sign In' : 'Sign Up'}
+
+
+
- setIsSignUp(!isSignUp)}>
-
- {isSignUp ? 'Already have an account? ' : "Don't have an account? "}
- {isSignUp ? 'Sign In' : 'Sign Up'}
-
-
@@ -120,20 +146,85 @@ export default function LoginScreen({ navigation }) {
const styles = StyleSheet.create({
safe: { flex: 1, backgroundColor: colors.white },
- container: { padding: 28, alignItems: 'center' },
- iconWrap: { width: 80, height: 80, borderRadius: 40, backgroundColor: colors.brandLight, alignItems: 'center', justifyContent: 'center', marginBottom: 20, marginTop: 20 },
- heading: { fontSize: 26, fontWeight: '800', color: colors.dark, marginBottom: 6 },
- sub: { fontSize: 14, color: colors.gray, marginBottom: 28 },
- input: { width: '100%', borderWidth: 1.5, borderColor: colors.border, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 14, fontSize: 15, color: colors.dark, marginBottom: 14 },
- authBtn: { width: '100%', backgroundColor: colors.brand, borderRadius: 12, paddingVertical: 16, alignItems: 'center', marginTop: 4 },
+ container: { flexGrow: 1 },
+ heroBanner: {
+ height: 280,
+ backgroundColor: '#000',
+ position: 'relative',
+ overflow: 'hidden',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ heroImage: {
+ width: '100%',
+ height: '100%',
+ position: 'absolute',
+ opacity: 0.7,
+ },
+ heroBannerOverlay: {
+ position: 'absolute',
+ bottom: 24,
+ left: 24,
+ },
+ skipBtn: {
+ position: 'absolute',
+ top: 16,
+ right: 16,
+ backgroundColor: 'rgba(255,255,255,0.15)',
+ paddingHorizontal: 14,
+ paddingVertical: 6,
+ borderRadius: 20,
+ borderWidth: 1,
+ borderColor: 'rgba(255,255,255,0.3)',
+ },
+ skipTxt: {
+ color: '#fff',
+ fontSize: 12,
+ fontWeight: '700',
+ letterSpacing: 1,
+ },
+ heroBrandTag: {
+ color: '#FF6B00',
+ fontSize: 10,
+ fontWeight: '900',
+ letterSpacing: 3,
+ marginBottom: 6,
+ },
+ heroTitle: {
+ color: '#fff',
+ fontSize: 32,
+ fontWeight: '900',
+ lineHeight: 36,
+ letterSpacing: -1,
+ marginBottom: 4,
+ },
+ heroSub: {
+ color: '#94A3B8',
+ fontSize: 13,
+ fontWeight: '500',
+ },
+ formCard: {
+ flex: 1,
+ backgroundColor: colors.white,
+ borderTopLeftRadius: 28,
+ borderTopRightRadius: 28,
+ padding: 28,
+ paddingBottom: 40,
+ marginTop: -20,
+ },
+ heading: { fontSize: 24, fontWeight: '800', color: colors.dark, marginBottom: 4 },
+ sub: { fontSize: 14, color: colors.gray, marginBottom: 24 },
+ input: { borderWidth: 1.5, borderColor: colors.border, borderRadius: 12, paddingHorizontal: 16, paddingVertical: 14, fontSize: 15, color: colors.dark, marginBottom: 14 },
+ authBtn: { backgroundColor: '#D83100', borderRadius: 12, paddingVertical: 16, alignItems: 'center', marginTop: 4 },
authBtnTxt: { color: colors.white, fontWeight: '800', fontSize: 15, letterSpacing: 1 },
- separator: { flexDirection: 'row', alignItems: 'center', width: '100%', marginVertical: 16, gap: 10 },
+ separator: { flexDirection: 'row', alignItems: 'center', marginVertical: 20, gap: 10 },
sepLine: { flex: 1, height: 1, backgroundColor: colors.border },
- sepTxt: { fontSize: 11, color: colors.gray, fontWeight: '600', letterSpacing: 0.5 },
- googleBtn: { width: '100%', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 10, borderWidth: 1.5, borderColor: colors.border, borderRadius: 12, paddingVertical: 14 },
- googleG: { fontSize: 18, fontWeight: '800', color: '#4285F4' },
- googleBtnTxt: { fontSize: 14, fontWeight: '600', color: colors.dark },
- switchBtn: { marginTop: 20 },
- switchTxt: { fontSize: 14, color: colors.gray },
- switchLink: { color: colors.brand, fontWeight: '700' },
+ sepTxt: { fontSize: 12, color: colors.gray, fontWeight: '600', letterSpacing: 1 },
+ googleBtn: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 12, borderWidth: 1.5, borderColor: colors.border, borderRadius: 12, paddingVertical: 14, backgroundColor: colors.white },
+ googleIconWrap: { width: 24, height: 24, borderRadius: 12, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', borderWidth: 1, borderColor: '#e0e0e0' },
+ googleG: { fontSize: 14, fontWeight: '900', color: '#4285F4' },
+ googleBtnTxt: { fontSize: 15, fontWeight: '600', color: colors.dark },
+ switchBtn: { marginTop: 20, alignItems: 'center', width: '100%' },
+ switchTxt: { fontSize: 14, color: colors.gray, textAlign: 'center' },
+ switchLink: { color: '#D83100', fontWeight: '700' },
});
diff --git a/mobile/src/screens/ProductDetailScreen.js b/mobile/src/screens/ProductDetailScreen.js
index 12981f3..f221eba 100644
--- a/mobile/src/screens/ProductDetailScreen.js
+++ b/mobile/src/screens/ProductDetailScreen.js
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
import { View, Text, Image, ScrollView, TouchableOpacity, StyleSheet, Alert, Modal, Dimensions } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
@@ -26,74 +26,99 @@ export default function ProductDetailScreen({ route, navigation }) {
const handleAddToCart = () => {
if (!selectedSize) { Alert.alert('Select Size', 'Please select a size first'); return; }
addToCart(product, selectedSize);
- Alert.alert('Added!', `${product.name} (UK ${selectedSize}) added to cart`);
+ navigation.navigate('Cart');
};
return (
-
-
- navigation.goBack()} style={styles.backBtn}>
-
-
- {product.name}
-
-
+
+
+
+ navigation.goBack()} style={styles.iconBtn}>
+
+
+ {product.brand}
+ toggleWishlist(product)} style={styles.iconBtn}>
+
+
+
+
-
-
-
- {product.brand}
- {product.name}
- {product.category}
- ₹ {product.price.toLocaleString('en-IN')}
- {product.description}
+
+
+
+
-
- SELECT SIZE (UK)
- setShowChart(true)}>
- SIZE CHART
-
+
+
+
+ {product.name}
+ {product.category}
+
+ ₹ {product.price.toLocaleString('en-IN')}
-
- {SIZES.map(s => (
- setSelectedSize(s)}
- >
- {s}
+
+
+ Product Description
+ {product.description}
+
+
+
+ Select Size (UK)
+ setShowChart(true)}>
+ Size Guide
- ))}
+
+
+ {SIZES.map(s => (
+ setSelectedSize(s)}
+ >
+ {s}
+
+ ))}
+
-
- 100% Authentic
- 30-Day Returns
+
+
+
+
+ Authentic Product
+ Verified & Quality Checked
+
+
+
+
+
+ Expedited Shipping
+ Delivery in 2-3 Business Days
+
+
- toggleWishlist(product)}
- >
-
-
-
- ADD TO CART
+
+ Add to Cart • ₹{product.price.toLocaleString('en-IN')}
-
+
- UK SIZE CHART
- setShowChart(false)}>
-
+ UK Size Chart
+ setShowChart(false)} style={styles.modalClose}>
+
@@ -109,46 +134,51 @@ export default function ProductDetailScreen({ route, navigation }) {
-
+
);
}
const styles = StyleSheet.create({
- safe: { flex: 1, backgroundColor: colors.white },
- topBar: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 16, paddingVertical: 10 },
- backBtn: { padding: 4 },
- topTitle: { flex: 1, textAlign: 'center', fontSize: 15, fontWeight: '700', color: colors.dark, marginHorizontal: 8 },
- image: { width: W, height: W * 0.85, backgroundColor: colors.lightGray },
- body: { padding: 20 },
- brand: { fontSize: 11, fontWeight: '700', color: colors.gray, letterSpacing: 1.5, marginBottom: 4 },
- name: { fontSize: 22, fontWeight: '800', color: colors.dark, marginBottom: 4 },
- category: { fontSize: 13, color: colors.gray, marginBottom: 10 },
- price: { fontSize: 24, fontWeight: '900', color: colors.dark, marginBottom: 16 },
- desc: { fontSize: 14, color: colors.slate, lineHeight: 22, marginBottom: 20 },
- sizeHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 },
- sizeTitle: { fontSize: 13, fontWeight: '800', color: colors.dark, letterSpacing: 1 },
- chartLink: { fontSize: 12, fontWeight: '700', color: colors.brand, textDecorationLine: 'underline' },
- sizesRow: { flexDirection: 'row', gap: 10, marginBottom: 20 },
- sizeBtn: { width: 48, height: 48, borderRadius: 10, borderWidth: 1.5, borderColor: colors.border, alignItems: 'center', justifyContent: 'center' },
- sizeBtnActive: { borderColor: colors.brand, backgroundColor: colors.brand },
- sizeTxt: { fontSize: 14, fontWeight: '700', color: colors.dark },
+ container: { flex: 1, backgroundColor: colors.white },
+ safeTop: { backgroundColor: colors.white },
+ topBar: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 20, paddingVertical: 10 },
+ iconBtn: { width: 44, height: 44, borderRadius: 22, backgroundColor: colors.lightGray, alignItems: 'center', justifyContent: 'center' },
+ topTitle: { fontSize: 16, fontWeight: '800', letterSpacing: 0.5, color: colors.dark, textTransform: 'uppercase' },
+ scroll: { paddingBottom: 100 },
+ imageContainer: { width: W, height: W, backgroundColor: '#F8F9FA', alignItems: 'center', justifyContent: 'center' },
+ image: { width: '85%', height: '85%' },
+ body: { padding: 25, marginTop: -30, backgroundColor: colors.white, borderTopLeftRadius: 30, borderTopRightRadius: 30 },
+ titleRow: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 15 },
+ name: { fontSize: 24, fontWeight: '900', color: colors.dark, flex: 1, marginRight: 10 },
+ category: { fontSize: 14, color: colors.gray, fontWeight: '600', marginTop: 4 },
+ price: { fontSize: 22, fontWeight: '900', color: colors.brand },
+ divider: { height: 1, backgroundColor: colors.border, marginVertical: 20 },
+ sectionTitle: { fontSize: 16, fontWeight: '800', color: colors.dark, marginBottom: 12 },
+ desc: { fontSize: 15, color: colors.slate, lineHeight: 24, fontWeight: '400' },
+ sizeSection: { marginTop: 25 },
+ sizeHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 15 },
+ chartLink: { fontSize: 13, fontWeight: '700', color: colors.brand },
+ sizesRow: { flexDirection: 'row', gap: 12 },
+ sizeBtn: { flex: 1, height: 50, borderRadius: 15, borderWidth: 1.5, borderColor: colors.border, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.white },
+ sizeBtnActive: { borderColor: colors.dark, backgroundColor: colors.dark },
+ sizeTxt: { fontSize: 15, fontWeight: '700', color: colors.dark },
sizeTxtActive: { color: colors.white },
- badges: { flexDirection: 'row', gap: 16 },
- badgeItem: { flexDirection: 'row', alignItems: 'center', gap: 6 },
- badgeTxt: { fontSize: 12, color: colors.slate, fontWeight: '500' },
- footer: { flexDirection: 'row', padding: 16, gap: 12, borderTopWidth: 1, borderTopColor: colors.border },
- wishlistBtn: { width: 52, height: 52, borderRadius: 12, borderWidth: 1.5, borderColor: colors.border, alignItems: 'center', justifyContent: 'center' },
- wishlistBtnActive: { borderColor: colors.brand, backgroundColor: colors.brandLight },
- cartBtn: { flex: 1, height: 52, backgroundColor: colors.brand, borderRadius: 12, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 8 },
- cartBtnTxt: { color: colors.white, fontWeight: '800', fontSize: 14, letterSpacing: 1 },
- modalOverlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', alignItems: 'center', justifyContent: 'center' },
- modalBox: { backgroundColor: colors.white, borderRadius: 16, padding: 20, width: W - 60 },
- modalHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 },
- modalTitle: { fontSize: 14, fontWeight: '800', letterSpacing: 1 },
- tableHeader: { flexDirection: 'row', backgroundColor: colors.lightGray, borderRadius: 8, paddingVertical: 8, marginBottom: 4 },
- tableHead: { flex: 1, textAlign: 'center', fontSize: 12, fontWeight: '700', color: colors.slate },
- tableRow: { flexDirection: 'row', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: colors.border },
+ perks: { marginTop: 30, gap: 20 },
+ perkItem: { flexDirection: 'row', alignItems: 'center', gap: 15 },
+ perkTitle: { fontSize: 14, fontWeight: '700', color: colors.dark },
+ perkSub: { fontSize: 12, color: colors.gray, fontWeight: '500' },
+ footer: { position: 'absolute', bottom: 0, width: '100%', padding: 20, paddingBottom: 35, backgroundColor: colors.white, shadowColor: colors.dark, shadowOpacity: 0.1, shadowRadius: 10, elevation: 10, borderTopWidth: 1, borderTopColor: colors.border },
+ cartBtn: { height: 60, backgroundColor: '#D83100', borderRadius: 20, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 12 },
+ cartBtnTxt: { color: colors.white, fontWeight: '800', fontSize: 16, letterSpacing: 0.5 },
+ modalOverlay: { flex: 1, backgroundColor: 'rgba(15,23,42,0.8)', justifyContent: 'flex-end' },
+ modalBox: { backgroundColor: colors.white, borderTopLeftRadius: 30, borderTopRightRadius: 30, padding: 25, maxHeight: '60%' },
+ modalHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 25 },
+ modalTitle: { fontSize: 18, fontWeight: '800' },
+ modalClose: { padding: 5 },
+ tableHeader: { flexDirection: 'row', backgroundColor: colors.lightGray, borderRadius: 12, paddingVertical: 12, marginBottom: 8 },
+ tableHead: { flex: 1, textAlign: 'center', fontSize: 13, fontWeight: '800', color: colors.slate },
+ tableRow: { flexDirection: 'row', paddingVertical: 15, borderBottomWidth: 1, borderBottomColor: colors.border },
tableRowActive: { backgroundColor: colors.brandLight },
- tableCell: { flex: 1, textAlign: 'center', fontSize: 13, color: colors.dark },
- tableCellActive: { fontWeight: '700', color: colors.brand },
+ tableCell: { flex: 1, textAlign: 'center', fontSize: 14, color: colors.dark, fontWeight: '500' },
+ tableCellActive: { fontWeight: '800', color: colors.brand },
});
diff --git a/mobile/src/screens/WishlistScreen.js b/mobile/src/screens/WishlistScreen.js
index 53a9f0e..19a7680 100644
--- a/mobile/src/screens/WishlistScreen.js
+++ b/mobile/src/screens/WishlistScreen.js
@@ -1,4 +1,3 @@
-import React from 'react';
import { View, Text, FlatList, Image, TouchableOpacity, StyleSheet } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
@@ -37,7 +36,7 @@ export default function WishlistScreen({ navigation }) {
contentContainerStyle={styles.list}
renderItem={({ item }) => (
navigation.navigate('ProductDetail', { product: item })} activeOpacity={0.9}>
-
+
{item.brand}
{item.name}
diff --git a/mobile/src/theme/colors.js b/mobile/src/theme/colors.js
index f6d8d86..849cda3 100644
--- a/mobile/src/theme/colors.js
+++ b/mobile/src/theme/colors.js
@@ -1,12 +1,13 @@
export const colors = {
- brand: '#e85d04',
- brandLight: '#fff0e6',
- dark: '#1a1a1a',
- slate: '#4a5568',
- gray: '#888888',
- lightGray: '#f5f5f5',
- border: '#e8e8e8',
- white: '#ffffff',
- success: '#16a34a',
- danger: '#dc2626',
+ brand: '#FF3D00',
+ brandLight: 'rgba(255, 61, 0, 0.08)',
+ dark: '#0F172A',
+ slate: '#334155',
+ gray: '#64748B',
+ lightGray: '#F8FAFC',
+ border: '#E2E8F0',
+ surface: '#FFFFFF',
+ white: '#FFFFFF',
+ success: '#10B981',
+ danger: '#EF4444',
};