diff --git a/.env.example b/.env.example deleted file mode 100644 index c34f8e0..0000000 --- a/.env.example +++ /dev/null @@ -1,8 +0,0 @@ -# GEMINI_API_KEY: Optional; used if you wire Gemini into the app. -GEMINI_API_KEY="MY_GEMINI_API_KEY" - -# APP_URL: Public URL for links and callbacks. -APP_URL="MY_APP_URL" - -# Firebase: copy config/firebase-applet-config.example.json to config/firebase-applet-config.json -# and fill in your Firebase web app values (see Firebase console). diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a711bbb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,51 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + frontend: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npm run lint -w frontend + - run: npm test -w frontend + - run: npm run build -w frontend + + backend: + runs-on: ubuntu-latest + services: + mongo: + image: mongo:7 + ports: ["27017:27017"] + env: + MONGODB_TEST_URI: mongodb://localhost:27017/authentick_test + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npm run lint -w backend + - run: npm test -w backend + - run: npm run build -w backend + + contracts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npm run lint -w contracts + - run: npm test -w contracts diff --git a/.gitignore b/.gitignore index 991a319..fb2ddaa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,16 @@ -# Node modules -/node_modules +node_modules/ +dist/ +coverage/ +.env +.env.* +!.env.example +.vercel/ +*.log +.DS_Store -# Compilation output -/dist - -# pnpm deploy output -/bundle - -# Hardhat Build Artifacts -/artifacts - -# Hardhat compilation (v2) support directory -/cache - -# Typechain output -/types - -# Hardhat coverage reports -/coverage +# hardhat +contracts/artifacts/ +contracts/cache/ +contracts/types/ +contracts/ignition/deployments/ +contracts/deployedAddresses.json diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md deleted file mode 100644 index 4d3cc7f..0000000 --- a/ARCHITECTURE.md +++ /dev/null @@ -1,38 +0,0 @@ -# AuthenTick Architecture - -## 1. System Overview -AuthenTick is a hybrid blockchain-based anti-counterfeit system that combines the immutability of public ledgers with the scalability of centralized high-performance databases. - -## 2. Component Breakdown - -### A. Smart Contracts (On-Chain) -- **AuthenTickNFT (ERC-721)**: Represents the "Digital Twin" of a physical product. -- **OwnershipRegistry**: Manages the lifecycle of a product (Mint -> Distribute -> Retail -> Own). -- **RoleManager**: Implements RBAC (Manufacturer, Distributor, Retailer, Customer). - -### B. Backend Services (Off-Chain) -- **GS1 EPCIS Ingestion Engine**: Standardizes product event data. -- **ZK-Prover Service**: Generates zero-knowledge proofs for ownership verification without revealing user PII. -- **Metadata API**: Serves high-resolution product data and history. - -### C. Frontend Applications -- **Manufacturer Portal**: Batch minting and serial generation. -- **Supply Chain Dashboard**: Tracking transfers between distributors and retailers. -- **Consumer App**: QR-based verification and ownership claiming. - -## 3. Data Flow (Verification) -1. **Product Scan**: Consumer scans the secure QR code. -2. **Identity Fetch**: App retrieves the NFT ID and associated GS1 events. -3. **ZK-Proof Verification**: The backend verifies the current owner's signature against the on-chain registry using a ZK-proof. -4. **Authenticity Result**: User sees the full provenance and "Verified" status. - -## 4. GS1 EPCIS Interoperability -We use the **Electronic Product Code Information Services (EPCIS)** standard to ensure interoperability with global supply chains. -- **What**: Product ID (GTIN + Serial). -- **When**: Timestamp of events. -- **Where**: Location (GLN). -- **Why**: Business step (e.g., shipping, receiving). - -## 5. Scalability (2000+ TPS) -- **Batching**: Minting and state updates are batched off-chain and committed to Polygon in periodic intervals. -- **Hybrid State**: High-frequency tracking events are stored in Firestore, while critical ownership changes are on-chain. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fadd589..104a857 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,12 +7,12 @@ First off, thank you for considering contributing to AuthenTick! It's people lik 1. **Fork the repository** on GitHub. 2. **Clone your fork** locally: ```bash - git clone https://github.com/your-username/authentick.git - cd authentick + git clone https://github.com/Phantom8420/AuthenTick.git + cd AuthenTick ``` 3. **Set up the upstream remote**: ```bash - git remote add upstream https://github.com/your-org/authentick.git + git remote add upstream https://github.com/Phantom8420/AuthenTick.git ``` ## πŸ› οΈ Development Environment @@ -23,17 +23,19 @@ We use a mono-repo structure with npm workspaces. To install all dependencies ac npm install ``` -Make sure you copy `.env.example` to `.env` and configure any necessary external credentials (such as your Firebase settings or Gemini keys). +Copy `backend/.env.example` to `backend/.env` if you want to change the defaults. Without MongoDB the API uses an in-memory store, so this is enough to start: +```bash +npm run dev +``` -You can run the entire local testing stack (including the database) with: +Before opening a pull request, run everything CI runs: ```bash -npm run dev:stack +npm run lint && npm test && npm run build ``` ## πŸ§‘β€πŸ’» Code Style & Standards - **TypeScript Standard**: We use TypeScript across the entire off-chain stack. Ensure you compile successfully before committing (`npm run lint`). -- **Formatting**: Please adhere to the configured Prettier formatting standard. - **Smart Contracts**: Solidity files should adhere strictly to standard conventions; run `npm run test:contracts` to ensure all tests pass. Maintain security standard methodologies using standard OpenZeppelin extensions. - **Commit Messages**: We encourage conventional commit messages (e.g., `feat: Add ZK Verifier`, `fix: Patch metadata ingestion bug`). diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f593e5a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 AuthenTick contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index b3887f1..8eab59e 100644 --- a/README.md +++ b/README.md @@ -1,160 +1,81 @@ -# AuthenTick πŸ›‘οΈ +# AuthenTick -**AuthenTick** is a hybrid blockchain-based anti-counterfeit platform designed to combat supply chain fraud. It combines the immutability of public ledgers with the scalability of high-performance centralized databases to verify product authenticity seamlessly. +**Blockchain-backed product authentication.** Mint a digital twin for every product, log each handoff on the supply chain, and let anyone scan to prove it's real. -Through a beautiful, dark-themed interface, Manufacturers can mint serialized "Digital Twins" (NFTs), Distributors and Retailers can track shipments, and Consumers can confidently verify products by scanning secure QR codes. +**[Open the live app](https://authen-tick-web.vercel.app)** Β· [Docs](https://authen-tick-web.vercel.app/docs) Β· [Architecture](docs/ARCHITECTURE.md) ---- +> No backend or wallet needed to try it. On the Verify page, paste the demo token `0xde70a11ce0000001` into the search bar and step the item from factory to shopper. -## 🌟 Key Features +## How it works -- **Digital Twin Minting**: Generate non-fungible tokens (ERC-721) securely mapping to physical product serial numbers. -- **GS1 EPCIS Compliance**: Leverage global supply chain standards (GTINs, GLNs) for interoperability and standardized event tracking. -- **Hybrid Data Architecture**: Store high-frequency tracking events off-chain (MongoDB) while executing critical ownership transfers on-chain (Ethereum/Polygon). -- **Consumer Verification**: Instantly scan QR codes to confirm authenticity, revealing full supply-chain provenance. -- **Zero-Knowledge Capabilities (ZK-Proofs)**: Prepare the system for private ownership verifications, guaranteeing authenticity without revealing personal information. -- **Role-Based Access Control (RBAC)**: Distinct, secure interfaces for Manufacturers, Distributors, Retailers, and Customers. +1. **Mint**: a manufacturer registers a serialized product (GTIN + serial). It becomes a digital twin with a printable QR code. +2. **Hand off**: distributors and retailers log shipping, receiving, storing and selling as GS1 EPCIS events. +3. **Verify**: a shopper scans the QR code or searches the token ID and sees the full provenance trail. +4. **Own**: the buyer connects a wallet to confirm they are the registered owner. ---- +## Roles and rules -## πŸ›οΈ System Architecture +Writes need a wallet sign-in when `AUTH_REQUIRED=true` (the default in production). Each role does one job: -AuthenTick comprises three primary layers operating cohesively: +| Role | Can record | +|---|---| +| Manufacturer | mint, shipping | +| Distributor | shipping, receiving | +| Retailer | receiving, storing, selling | +| Admin | everything, plus granting roles | -1. **Smart Contracts (On-Chain)** - - `AuthenTickNFT` (ERC-721): The core token representing the physical item. - - `OwnershipRegistry`: Controls product lifecycles across the entire supply chain. - - `RoleManager`: Handles blockchain-verified permissions. +Events must follow the lifecycle: `commissioning β†’ shipping β†’ receiving β†’ storing β†’ selling`, with `shipping` allowed again after receiving or storing. A sold item is final. GTINs are checked against the GS1 check digit, and a token ID or GTIN + serial can only be registered once. -2. **Backend Services (Off-Chain)** - - **Ingestion Engine**: Processes GTINs and handles high-velocity tracking data. - - **Metadata API**: Serves robust product details and supply chain histories globally. +## Repository layout -3. **Frontend Applications** - - **Manufacturer Portal**: Simplified batch minting and initial lifecycle processing. - - **Supply Chain Dashboard**: Visual tracking interface for logistics. - - **Consumer UI**: Frictionless, mobile-responsive verification interface. +| Folder | What it is | +|---|---| +| `frontend/` | React 19 + Vite + TypeScript web app. Includes an in-browser demo mode, so it runs with no API. | +| `backend/` | Express + TypeScript API. MongoDB in production, in-memory store for local development. | +| `contracts/` | Solidity (Hardhat 3): `RoleManager`, `AuthenTickNFT`, `OwnershipRegistry`. | +| `docker/` | Compose stack: MongoDB, API, nginx-served frontend. | +| `docs/` | Architecture notes. | -For a deeper dive, check out the [ARCHITECTURE documentation](./docs/ARCHITECTURE.md). +## Run it locally ---- +Requires Node 20+. -## πŸ› οΈ Technology Stack - -An enterprise-ready mono-repo managed with npm workspaces: - -### Frontend (`frontend/`) -- **Framework:** React 19 + Vite -- **Styling:** Tailwind CSS v4, Framer Motion -- **Web3 Integration:** Ethers.js, viem -- **Utilities:** HTML5-QRCode, React Router DOM - -### Backend (`backend/`) -- **Server:** Node.js, Express.js -- **Database:** MongoDB (via Mongoose) -- **Validation:** Zod -- **Security:** Helmet, CORS - -### Smart Contracts (`contracts/`) -- **Environment:** Hardhat, NomicFoundation Verification -- **Language:** Solidity -- **Standards:** OpenZeppelin Contracts -- **Deployment:** Hardhat Ignition - ---- - -## πŸš€ Getting Started - -Follow these steps to run AuthenTick locally. - -### Prerequisites -- [Node.js](https://nodejs.org/en/) (v18 or higher recommended) -- [Docker](https://www.docker.com/) & Docker Compose (for local database services) - -### Installation - -1. **Clone the repository** - ```bash - git clone https://github.com/your-org/authentick.git - cd authentick - ``` - -2. **Install all workspace dependencies** - ```bash - npm install - ``` - -3. **Environment Configuration** - Copy the example environment files. Modify them as necessary if integrating Firebase or Gemini API. - ```bash - cp .env.example .env - ``` - -### Running the Application - -AuthenTick provides unified scripts via `concurrently` to bring the stack up effortlessly. - -**Option A: The Full Stack (Recommended)** -Spins up MongoDB in Docker and starts both the `frontend` and `backend` development servers. -```bash -npm run dev:stack -``` - -**Option B: Separate the DB and App** -Start your Docker services manually: -```bash -npm run docker:up -``` -Then start the Node.js development servers: ```bash +git clone https://github.com/Phantom8420/AuthenTick.git +cd AuthenTick +npm install npm run dev ``` -The frontend will be available locally (typically at `http://localhost:5173`), and the backend API will run on its designated port. +The web app is on http://localhost:5173 and the API on http://localhost:4000. Without `MONGODB_URI` the API keeps data in memory. If the API is unreachable the frontend falls back to demo mode automatically. -### Smart Contracts (Local Blockchain) +Copy `backend/.env.example` to `backend/.env` to configure the API (MongoDB, wallet sign-in, chain). -To spin up a local Hardhat node for smart contract testing: -```bash -npm run node:chain -``` +### Everything in Docker -In a new terminal window, deploy the contracts to your local node: ```bash -npm run deploy:local -w contracts +JWT_SECRET=$(openssl rand -hex 32) ADMIN_ADDRESSES=0xYourWallet npm run docker:up ``` ---- +The stack serves the app on http://localhost:8080. In production mode the API requires a wallet sign-in for writes; `ADMIN_ADDRESSES` can then grant roles. -## πŸ“‚ Project Structure +### Tests -```text -authentick/ -β”œβ”€β”€ apps/ # Additional standalone services/apps -β”œβ”€β”€ backend/ # Express.js REST API & Ingestion engine -β”œβ”€β”€ contracts/ # Hardhat configuration, smart contracts, & Ignition -β”œβ”€β”€ docker/ # Docker compose files for MongoDB / infrastructure -β”œβ”€β”€ docs/ # System documentation and architecture diagrams -β”œβ”€β”€ frontend/ # React + Tailwind CSS client application -β”œβ”€β”€ package.json # Root workspace configuration -└── README.md # You are here! +```bash +npm test # all workspaces +npm run test:contracts # Hardhat +npm run test:backend # Vitest +npm run test:frontend # Vitest ``` ---- - -## πŸ“œ Available Scripts +## Deploying the frontend -From the root directory, you have access to the following workspace scripts: +`frontend/vercel.json` rewrites all routes to the SPA. Build with `npm run build -w frontend` and deploy `frontend/dist` to any static host. Set `VITE_API_URL` to point at a hosted API; without it the app runs in demo mode. -- `npm run dev`: Starts the backend API and frontend concurrently. -- `npm run dev:stack`: Wakes the Docker MongoDB instance, then runs the `dev` script. -- `npm run build`: Compiles smart contracts, backend, and frontend for production. -- `npm run lint`: Runs TypeScripts/Eslint checks across all relevant workspaces. -- `npm run test:contracts`: Executes the Hardhat/Foundry test suites inside `contracts/`. -- `npm run docker:up` / `npm run docker:down`: Manage the background container infrastructure. +## Contributing ---- +See [CONTRIBUTING.md](CONTRIBUTING.md). Issues and pull requests are welcome. -## πŸ“„ License +## License -This project is licensed under the ISC License. See the internal package files for specific details. +[MIT](LICENSE) diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts deleted file mode 100644 index e4bcbef..0000000 --- a/apps/server/src/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -import express from "express"; -import { createServer as createViteServer } from "vite"; -import path from "path"; -import { fileURLToPath } from "url"; -import { registerApiRoutes, type ApiStore } from "./routes/api"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -const projectRoot = path.resolve(__dirname, "../../.."); -const webRoot = path.join(projectRoot, "apps", "web"); - -async function startServer() { - const app = express(); - const PORT = Number(process.env.PORT) || 3000; - - app.use(express.json()); - - const store: ApiStore = { - events: [], - }; - - registerApiRoutes(app, store); - - if (process.env.NODE_ENV !== "production") { - const vite = await createViteServer({ - root: webRoot, - server: { middlewareMode: true }, - appType: "spa", - }); - app.use(vite.middlewares); - } else { - const distPath = path.join(webRoot, "dist"); - app.use(express.static(distPath)); - app.get("*", (_req, res) => { - res.sendFile(path.join(distPath, "index.html")); - }); - } - - app.listen(PORT, "0.0.0.0", () => { - console.log(`AuthenTick server at http://localhost:${PORT}`); - }); -} - -startServer().catch((err) => { - console.error("Failed to start server:", err); -}); diff --git a/apps/server/src/routes/api.ts b/apps/server/src/routes/api.ts deleted file mode 100644 index a1c0ce8..0000000 --- a/apps/server/src/routes/api.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { Express } from "express"; - -export type ApiStore = { - events: Array & { productId?: string }>; -}; - -export function registerApiRoutes(app: Express, store: ApiStore) { - app.get("/api/health", (_req, res) => { - res.json({ status: "ok", timestamp: new Date().toISOString() }); - }); - - app.post("/api/events", (req, res) => { - const event = { - ...req.body, - id: Math.random().toString(36).substring(2, 11), - recordedTime: Date.now(), - }; - store.events.push(event); - res.status(201).json(event); - }); - - app.get("/api/products/:id/history", (req, res) => { - const productEvents = store.events.filter((e) => e.productId === req.params.id); - res.json(productEvents); - }); - - app.post("/api/verify-ownership", (req, res) => { - const { productId, proof, ownerAddress } = req.body; - - const isValid = Boolean(proof && ownerAddress); - - res.json({ - verified: isValid, - message: isValid ? "Ownership proof verified via ZK-SNARK" : "Invalid proof", - productId, - timestamp: Date.now(), - }); - }); -} diff --git a/apps/web/dist/assets/index-DPKbDxuB.css b/apps/web/dist/assets/index-DPKbDxuB.css deleted file mode 100644 index ac5a59a..0000000 --- a/apps/web/dist/assets/index-DPKbDxuB.css +++ /dev/null @@ -1 +0,0 @@ -@import"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap";/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-content:""}}}@layer theme{:root,:host{--font-sans:"Inter", ui-sans-serif, system-ui, sans-serif;--font-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-500:oklch(63.7% .237 25.331);--color-red-700:oklch(50.5% .213 27.518);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-600:oklch(66.6% .179 58.318);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-200:oklch(90.5% .093 164.15);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-700:oklch(50.8% .118 165.612);--color-emerald-900:oklch(37.8% .077 168.94);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-300:oklch(78.5% .115 274.713);--color-indigo-400:oklch(67.3% .182 276.935);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-600:oklch(51.1% .262 276.966);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-900:oklch(35.9% .144 278.697);--color-purple-600:oklch(55.8% .288 302.321);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--container-7xl:80rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--text-6xl:3.75rem;--text-6xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-bounce:bounce 1s infinite;--blur-sm:8px;--blur-md:12px;--blur-3xl:64px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}body{background-color:var(--color-slate-50);color:var(--color-slate-900);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}}@layer components;@layer utilities{.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.top-0{top:calc(var(--spacing) * 0)}.top-1\.5{top:calc(var(--spacing) * 1.5)}.top-1\/2{top:50%}.right-0{right:calc(var(--spacing) * 0)}.-bottom-6{bottom:calc(var(--spacing) * -6)}.-left-6{left:calc(var(--spacing) * -6)}.left-1\/2{left:50%}.left-2\.5{left:calc(var(--spacing) * 2.5)}.left-3{left:calc(var(--spacing) * 3)}.left-4{left:calc(var(--spacing) * 4)}.z-10{z-index:10}.z-50{z-index:50}.z-\[100\]{z-index:100}.col-span-1{grid-column:span 1/span 1}.mx-auto{margin-inline:auto}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-10{margin-top:calc(var(--spacing) * 10)}.mt-12{margin-top:calc(var(--spacing) * 12)}.mt-auto{margin-top:auto}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.mb-10{margin-bottom:calc(var(--spacing) * 10)}.mb-12{margin-bottom:calc(var(--spacing) * 12)}.mb-16{margin-bottom:calc(var(--spacing) * 16)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.aspect-square{aspect-ratio:1}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-20{height:calc(var(--spacing) * 20)}.h-full{height:100%}.min-h-\[400px\]{min-height:400px}.min-h-screen{min-height:100vh}.w-1\/2{width:50%}.w-2{width:calc(var(--spacing) * 2)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-7{width:calc(var(--spacing) * 7)}.w-8{width:calc(var(--spacing) * 8)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-7xl{max-width:var(--container-7xl)}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-xl{max-width:var(--container-xl)}.max-w-xs{max-width:var(--container-xs)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.translate-x-1\/2{--tw-translate-x: 50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.animate-bounce{animation:var(--animate-bounce)}.animate-ping{animation:var(--animate-ping)}.animate-spin{animation:var(--animate-spin)}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-8{gap:calc(var(--spacing) * 8)}.gap-12{gap:calc(var(--spacing) * 12)}.gap-16{gap:calc(var(--spacing) * 16)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-12>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 12) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 12) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-20>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 20) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 20) * calc(1 - var(--tw-space-y-reverse)))}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-slate-100>:not(:last-child)){border-color:var(--color-slate-100)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-\[2rem\]{border-radius:2rem}.rounded-\[3rem\]{border-radius:3rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-4{border-style:var(--tw-border-style);border-width:4px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-emerald-100{border-color:var(--color-emerald-100)}.border-indigo-100{border-color:var(--color-indigo-100)}.border-indigo-500{border-color:var(--color-indigo-500)}.border-indigo-500\/20{border-color:#625fff33}@supports (color:color-mix(in lab,red,red)){.border-indigo-500\/20{border-color:color-mix(in oklab,var(--color-indigo-500) 20%,transparent)}}.border-indigo-500\/30{border-color:#625fff4d}@supports (color:color-mix(in lab,red,red)){.border-indigo-500\/30{border-color:color-mix(in oklab,var(--color-indigo-500) 30%,transparent)}}.border-red-100{border-color:var(--color-red-100)}.border-slate-50{border-color:var(--color-slate-50)}.border-slate-100{border-color:var(--color-slate-100)}.border-slate-200{border-color:var(--color-slate-200)}.border-white\/5{border-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.border-white\/5{border-color:color-mix(in oklab,var(--color-white) 5%,transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.border-white\/10{border-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.border-white\/20{border-color:#fff3}@supports (color:color-mix(in lab,red,red)){.border-white\/20{border-color:color-mix(in oklab,var(--color-white) 20%,transparent)}}.border-white\/30{border-color:#ffffff4d}@supports (color:color-mix(in lab,red,red)){.border-white\/30{border-color:color-mix(in oklab,var(--color-white) 30%,transparent)}}.border-t-indigo-600{border-top-color:var(--color-indigo-600)}.border-t-white{border-top-color:var(--color-white)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-green-400{background-color:var(--color-green-400)}.bg-green-500{background-color:var(--color-green-500)}.bg-green-500\/20{background-color:#00c75833}@supports (color:color-mix(in lab,red,red)){.bg-green-500\/20{background-color:color-mix(in oklab,var(--color-green-500) 20%,transparent)}}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-indigo-100{background-color:var(--color-indigo-100)}.bg-indigo-400{background-color:var(--color-indigo-400)}.bg-indigo-500{background-color:var(--color-indigo-500)}.bg-indigo-500\/10{background-color:#625fff1a}@supports (color:color-mix(in lab,red,red)){.bg-indigo-500\/10{background-color:color-mix(in oklab,var(--color-indigo-500) 10%,transparent)}}.bg-indigo-500\/20{background-color:#625fff33}@supports (color:color-mix(in lab,red,red)){.bg-indigo-500\/20{background-color:color-mix(in oklab,var(--color-indigo-500) 20%,transparent)}}.bg-indigo-600{background-color:var(--color-indigo-600)}.bg-indigo-600\/10{background-color:#4f39f61a}@supports (color:color-mix(in lab,red,red)){.bg-indigo-600\/10{background-color:color-mix(in oklab,var(--color-indigo-600) 10%,transparent)}}.bg-red-50{background-color:var(--color-red-50)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-50\/50{background-color:#f8fafc80}@supports (color:color-mix(in lab,red,red)){.bg-slate-50\/50{background-color:color-mix(in oklab,var(--color-slate-50) 50%,transparent)}}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\/60{background-color:#0f172b99}@supports (color:color-mix(in lab,red,red)){.bg-slate-900\/60{background-color:color-mix(in oklab,var(--color-slate-900) 60%,transparent)}}.bg-white{background-color:var(--color-white)}.bg-white\/5{background-color:#ffffff0d}@supports (color:color-mix(in lab,red,red)){.bg-white\/5{background-color:color-mix(in oklab,var(--color-white) 5%,transparent)}}.bg-white\/10{background-color:#ffffff1a}@supports (color:color-mix(in lab,red,red)){.bg-white\/10{background-color:color-mix(in oklab,var(--color-white) 10%,transparent)}}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab,red,red)){.bg-white\/20{background-color:color-mix(in oklab,var(--color-white) 20%,transparent)}}.bg-white\/80{background-color:#fffc}@supports (color:color-mix(in lab,red,red)){.bg-white\/80{background-color:color-mix(in oklab,var(--color-white) 80%,transparent)}}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-\[url\(\'https\:\/\/www\.transparenttextures\.com\/patterns\/cubes\.png\'\)\]{background-image:url(https://www.transparenttextures.com/patterns/cubes.png)}.from-indigo-500{--tw-gradient-from:var(--color-indigo-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-purple-600{--tw-gradient-to:var(--color-purple-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.p-10{padding:calc(var(--spacing) * 10)}.p-12{padding:calc(var(--spacing) * 12)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.py-20{padding-block:calc(var(--spacing) * 20)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pt-12{padding-top:calc(var(--spacing) * 12)}.pr-4{padding-right:calc(var(--spacing) * 4)}.pb-20{padding-bottom:calc(var(--spacing) * 20)}.pl-10{padding-left:calc(var(--spacing) * 10)}.pl-16{padding-left:calc(var(--spacing) * 16)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.break-all{word-break:break-all}.text-amber-600{color:var(--color-amber-600)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-emerald-600{color:var(--color-emerald-600)}.text-emerald-700{color:var(--color-emerald-700)}.text-emerald-900{color:var(--color-emerald-900)}.text-green-400{color:var(--color-green-400)}.text-indigo-300{color:var(--color-indigo-300)}.text-indigo-400{color:var(--color-indigo-400)}.text-indigo-600{color:var(--color-indigo-600)}.text-red-500{color:var(--color-red-500)}.text-red-700{color:var(--color-red-700)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.opacity-20{opacity:.2}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-emerald-200{--tw-shadow-color:oklch(90.5% .093 164.15)}@supports (color:color-mix(in lab,red,red)){.shadow-emerald-200{--tw-shadow-color:color-mix(in oklab, var(--color-emerald-200) var(--tw-shadow-alpha), transparent)}}.shadow-indigo-100{--tw-shadow-color:oklch(93% .034 272.788)}@supports (color:color-mix(in lab,red,red)){.shadow-indigo-100{--tw-shadow-color:color-mix(in oklab, var(--color-indigo-100) var(--tw-shadow-alpha), transparent)}}.shadow-indigo-200{--tw-shadow-color:oklch(87% .065 274.039)}@supports (color:color-mix(in lab,red,red)){.shadow-indigo-200{--tw-shadow-color:color-mix(in oklab, var(--color-indigo-200) var(--tw-shadow-alpha), transparent)}}.shadow-indigo-900\/20{--tw-shadow-color:#312c8533}@supports (color:color-mix(in lab,red,red)){.shadow-indigo-900\/20{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-indigo-900) 20%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-red-50{--tw-shadow-color:oklch(97.1% .013 17.38)}@supports (color:color-mix(in lab,red,red)){.shadow-red-50{--tw-shadow-color:color-mix(in oklab, var(--color-red-50) var(--tw-shadow-alpha), transparent)}}.shadow-slate-200{--tw-shadow-color:oklch(92.9% .013 255.508)}@supports (color:color-mix(in lab,red,red)){.shadow-slate-200{--tw-shadow-color:color-mix(in oklab, var(--color-slate-200) var(--tw-shadow-alpha), transparent)}}.blur-3xl{--tw-blur:blur(var(--blur-3xl));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-md{--tw-backdrop-blur:blur(var(--blur-md));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media(hover:hover){.group-hover\:scale-105:is(:where(.group):hover *){--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x) var(--tw-scale-y)}.group-hover\:bg-indigo-600:is(:where(.group):hover *){background-color:var(--color-indigo-600)}.group-hover\:text-white:is(:where(.group):hover *){color:var(--color-white)}}.before\:absolute:before{content:var(--tw-content);position:absolute}.before\:top-2:before{content:var(--tw-content);top:calc(var(--spacing) * 2)}.before\:bottom-2:before{content:var(--tw-content);bottom:calc(var(--spacing) * 2)}.before\:left-4:before{content:var(--tw-content);left:calc(var(--spacing) * 4)}.before\:left-6:before{content:var(--tw-content);left:calc(var(--spacing) * 6)}.before\:w-0\.5:before{content:var(--tw-content);width:calc(var(--spacing) * .5)}.before\:bg-slate-100:before{content:var(--tw-content);background-color:var(--color-slate-100)}.last\:border-0:last-child{border-style:var(--tw-border-style);border-width:0}@media(hover:hover){.hover\:-translate-y-0\.5:hover{--tw-translate-y:calc(var(--spacing) * -.5);translate:var(--tw-translate-x) var(--tw-translate-y)}.hover\:bg-indigo-700:hover{background-color:var(--color-indigo-700)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-50\/50:hover{background-color:#f8fafc80}@supports (color:color-mix(in lab,red,red)){.hover\:bg-slate-50\/50:hover{background-color:color-mix(in oklab,var(--color-slate-50) 50%,transparent)}}.hover\:bg-slate-200:hover{background-color:var(--color-slate-200)}.hover\:bg-slate-800:hover{background-color:var(--color-slate-800)}.hover\:text-indigo-600:hover{color:var(--color-indigo-600)}.hover\:text-red-500:hover{color:var(--color-red-500)}.hover\:underline:hover{text-decoration-line:underline}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-indigo-500:focus{--tw-ring-color:var(--color-indigo-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:40rem){.sm\:px-6{padding-inline:calc(var(--spacing) * 6)}}@media(min-width:48rem){.md\:col-span-2{grid-column:span 2/span 2}.md\:flex{display:flex}.md\:hidden{display:none}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}}@media(min-width:64rem){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:p-20{padding:calc(var(--spacing) * 20)}.lg\:px-8{padding-inline:calc(var(--spacing) * 8)}.lg\:pt-20{padding-top:calc(var(--spacing) * 20)}.lg\:text-6xl{font-size:var(--text-6xl);line-height:var(--tw-leading,var(--text-6xl--line-height))}}}.qr-scanner-container video{border-radius:var(--radius-3xl);border-style:var(--tw-border-style);border-width:4px;border-color:var(--color-white);--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);overflow:hidden}.glass-card{border-style:var(--tw-border-style);border-width:1px;border-color:#fff3}@supports (color:color-mix(in lab,red,red)){.glass-card{border-color:color-mix(in oklab,var(--color-white) 20%,transparent)}}.glass-card{background-color:#fffc}@supports (color:color-mix(in lab,red,red)){.glass-card{background-color:color-mix(in oklab,var(--color-white) 80%,transparent)}}.glass-card{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);--tw-backdrop-blur:blur(var(--blur-md));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}@keyframes bounce{0%,to{animation-timing-function:cubic-bezier(.8,0,1,1);transform:translateY(-25%)}50%{animation-timing-function:cubic-bezier(0,0,.2,1);transform:none}} diff --git a/apps/web/dist/assets/index-Du-ayE4p.js b/apps/web/dist/assets/index-Du-ayE4p.js deleted file mode 100644 index 23695c4..0000000 --- a/apps/web/dist/assets/index-Du-ayE4p.js +++ /dev/null @@ -1,3275 +0,0 @@ -(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))r(o);new MutationObserver(o=>{for(const u of o)if(u.type==="childList")for(const m of u.addedNodes)m.tagName==="LINK"&&m.rel==="modulepreload"&&r(m)}).observe(document,{childList:!0,subtree:!0});function t(o){const u={};return o.integrity&&(u.integrity=o.integrity),o.referrerPolicy&&(u.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?u.credentials="include":o.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function r(o){if(o.ep)return;o.ep=!0;const u=t(o);fetch(o.href,u)}})();var Hf=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function v3(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var dg={exports:{}},ju={};/** - * @license React - * react-jsx-runtime.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var LE;function A3(){if(LE)return ju;LE=1;var n=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function t(r,o,u){var m=null;if(u!==void 0&&(m=""+u),o.key!==void 0&&(m=""+o.key),"key"in o){u={};for(var x in o)x!=="key"&&(u[x]=o[x])}else u=o;return o=u.ref,{$$typeof:n,type:r,key:m,ref:o!==void 0?o:null,props:u}}return ju.Fragment=e,ju.jsx=t,ju.jsxs=t,ju}var PE;function T3(){return PE||(PE=1,dg.exports=A3()),dg.exports}var O=T3(),gg={exports:{}},ft={};/** - * @license React - * react.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var kE;function _3(){if(kE)return ft;kE=1;var n=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),t=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),o=Symbol.for("react.profiler"),u=Symbol.for("react.consumer"),m=Symbol.for("react.context"),x=Symbol.for("react.forward_ref"),E=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),T=Symbol.for("react.lazy"),b=Symbol.for("react.activity"),R=Symbol.iterator;function P(ne){return ne===null||typeof ne!="object"?null:(ne=R&&ne[R]||ne["@@iterator"],typeof ne=="function"?ne:null)}var j={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Y=Object.assign,G={};function te(ne,we,De){this.props=ne,this.context=we,this.refs=G,this.updater=De||j}te.prototype.isReactComponent={},te.prototype.setState=function(ne,we){if(typeof ne!="object"&&typeof ne!="function"&&ne!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,ne,we,"setState")},te.prototype.forceUpdate=function(ne){this.updater.enqueueForceUpdate(this,ne,"forceUpdate")};function se(){}se.prototype=te.prototype;function K(ne,we,De){this.props=ne,this.context=we,this.refs=G,this.updater=De||j}var ue=K.prototype=new se;ue.constructor=K,Y(ue,te.prototype),ue.isPureReactComponent=!0;var Se=Array.isArray;function Me(){}var z={H:null,A:null,T:null,S:null},F=Object.prototype.hasOwnProperty;function V(ne,we,De){var Ue=De.ref;return{$$typeof:n,type:ne,key:we,ref:Ue!==void 0?Ue:null,props:De}}function Q(ne,we){return V(ne.type,we,ne.props)}function Z(ne){return typeof ne=="object"&&ne!==null&&ne.$$typeof===n}function J(ne){var we={"=":"=0",":":"=2"};return"$"+ne.replace(/[=:]/g,function(De){return we[De]})}var W=/\/+/g;function Qe(ne,we){return typeof ne=="object"&&ne!==null&&ne.key!=null?J(""+ne.key):we.toString(36)}function fe(ne){switch(ne.status){case"fulfilled":return ne.value;case"rejected":throw ne.reason;default:switch(typeof ne.status=="string"?ne.then(Me,Me):(ne.status="pending",ne.then(function(we){ne.status==="pending"&&(ne.status="fulfilled",ne.value=we)},function(we){ne.status==="pending"&&(ne.status="rejected",ne.reason=we)})),ne.status){case"fulfilled":return ne.value;case"rejected":throw ne.reason}}throw ne}function me(ne,we,De,Ue,it){var ke=typeof ne;(ke==="undefined"||ke==="boolean")&&(ne=null);var At=!1;if(ne===null)At=!0;else switch(ke){case"bigint":case"string":case"number":At=!0;break;case"object":switch(ne.$$typeof){case n:case e:At=!0;break;case T:return At=ne._init,me(At(ne._payload),we,De,Ue,it)}}if(At)return it=it(ne),At=Ue===""?"."+Qe(ne,0):Ue,Se(it)?(De="",At!=null&&(De=At.replace(W,"$&/")+"/"),me(it,we,De,"",function(Xi){return Xi})):it!=null&&(Z(it)&&(it=Q(it,De+(it.key==null||ne&&ne.key===it.key?"":(""+it.key).replace(W,"$&/")+"/")+At)),we.push(it)),1;At=0;var Rt=Ue===""?".":Ue+":";if(Se(ne))for(var en=0;en>>1,st=me[Ze];if(0>>1;Zeo(De,Fe))Ueo(it,De)?(me[Ze]=it,me[Ue]=Fe,Ze=Ue):(me[Ze]=De,me[we]=Fe,Ze=we);else if(Ueo(it,Fe))me[Ze]=it,me[Ue]=Fe,Ze=Ue;else break e}}return Ae}function o(me,Ae){var Fe=me.sortIndex-Ae.sortIndex;return Fe!==0?Fe:me.id-Ae.id}if(n.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var u=performance;n.unstable_now=function(){return u.now()}}else{var m=Date,x=m.now();n.unstable_now=function(){return m.now()-x}}var E=[],y=[],T=1,b=null,R=3,P=!1,j=!1,Y=!1,G=!1,te=typeof setTimeout=="function"?setTimeout:null,se=typeof clearTimeout=="function"?clearTimeout:null,K=typeof setImmediate<"u"?setImmediate:null;function ue(me){for(var Ae=t(y);Ae!==null;){if(Ae.callback===null)r(y);else if(Ae.startTime<=me)r(y),Ae.sortIndex=Ae.expirationTime,e(E,Ae);else break;Ae=t(y)}}function Se(me){if(Y=!1,ue(me),!j)if(t(E)!==null)j=!0,Me||(Me=!0,J());else{var Ae=t(y);Ae!==null&&fe(Se,Ae.startTime-me)}}var Me=!1,z=-1,F=5,V=-1;function Q(){return G?!0:!(n.unstable_now()-Vme&&Q());){var Ze=b.callback;if(typeof Ze=="function"){b.callback=null,R=b.priorityLevel;var st=Ze(b.expirationTime<=me);if(me=n.unstable_now(),typeof st=="function"){b.callback=st,ue(me),Ae=!0;break t}b===t(E)&&r(E),ue(me)}else r(E);b=t(E)}if(b!==null)Ae=!0;else{var ne=t(y);ne!==null&&fe(Se,ne.startTime-me),Ae=!1}}break e}finally{b=null,R=Fe,P=!1}Ae=void 0}}finally{Ae?J():Me=!1}}}var J;if(typeof K=="function")J=function(){K(Z)};else if(typeof MessageChannel<"u"){var W=new MessageChannel,Qe=W.port2;W.port1.onmessage=Z,J=function(){Qe.postMessage(null)}}else J=function(){te(Z,0)};function fe(me,Ae){z=te(function(){me(n.unstable_now())},Ae)}n.unstable_IdlePriority=5,n.unstable_ImmediatePriority=1,n.unstable_LowPriority=4,n.unstable_NormalPriority=3,n.unstable_Profiling=null,n.unstable_UserBlockingPriority=2,n.unstable_cancelCallback=function(me){me.callback=null},n.unstable_forceFrameRate=function(me){0>me||125Ze?(me.sortIndex=Fe,e(y,me),t(E)===null&&me===t(y)&&(Y?(se(z),z=-1):Y=!0,fe(Se,Fe-Ze))):(me.sortIndex=st,e(E,me),j||P||(j=!0,Me||(Me=!0,J()))),me},n.unstable_shouldYield=Q,n.unstable_wrapCallback=function(me){var Ae=R;return function(){var Fe=R;R=Ae;try{return me.apply(this,arguments)}finally{R=Fe}}}})(yg)),yg}var UE;function b3(){return UE||(UE=1,pg.exports=C3()),pg.exports}var xg={exports:{}},er={};/** - * @license React - * react-dom.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var FE;function S3(){if(FE)return er;FE=1;var n=Qm();function e(E){var y="https://react.dev/errors/"+E;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}return n(),xg.exports=S3(),xg.exports}/** - * @license React - * react-dom-client.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var zE;function R3(){if(zE)return zu;zE=1;var n=b3(),e=Qm(),t=I3();function r(i){var a="https://react.dev/errors/"+i;if(1st||(i.current=Ze[st],Ze[st]=null,st--)}function De(i,a){st++,Ze[st]=i.current,i.current=a}var Ue=ne(null),it=ne(null),ke=ne(null),At=ne(null);function Rt(i,a){switch(De(ke,a),De(it,i),De(Ue,null),a.nodeType){case 9:case 11:i=(i=a.documentElement)&&(i=i.namespaceURI)?iE(i):0;break;default:if(i=a.tagName,a=a.namespaceURI)a=iE(a),i=rE(a,i);else switch(i){case"svg":i=1;break;case"math":i=2;break;default:i=0}}we(Ue),De(Ue,i)}function en(){we(Ue),we(it),we(ke)}function Xi(i){i.memoizedState!==null&&De(At,i);var a=Ue.current,h=rE(a,i.type);a!==h&&(De(it,i),De(Ue,h))}function Mn(i){it.current===i&&(we(Ue),we(it)),At.current===i&&(we(At),Bu._currentValue=Fe)}var Jr,Tt;function Ti(i){if(Jr===void 0)try{throw Error()}catch(h){var a=h.stack.trim().match(/\n( *(at )?)/);Jr=a&&a[1]||"",Tt=-1)":-1A||$[g]!==ge[A]){var Te=` -`+$[g].replace(" at new "," at ");return i.displayName&&Te.includes("")&&(Te=Te.replace("",i.displayName)),Te}while(1<=g&&0<=A);break}}}finally{_i=!1,Error.prepareStackTrace=h}return(h=i?i.displayName||i.name:"")?Ti(h):""}function Zn(i,a){switch(i.tag){case 26:case 27:case 5:return Ti(i.type);case 16:return Ti("Lazy");case 13:return i.child!==a&&a!==null?Ti("Suspense Fallback"):Ti("Suspense");case 19:return Ti("SuspenseList");case 0:case 15:return $r(i.type,!1);case 11:return $r(i.type.render,!1);case 1:return $r(i.type,!0);case 31:return Ti("Activity");default:return""}}function Wt(i){try{var a="",h=null;do a+=Zn(i,h),h=i,i=i.return;while(i);return a}catch(g){return` -Error generating stack: `+g.message+` -`+g.stack}}var Et=Object.prototype.hasOwnProperty,es=n.unstable_scheduleCallback,ze=n.unstable_cancelCallback,qa=n.unstable_shouldYield,Ya=n.unstable_requestPaint,mn=n.unstable_now,Xa=n.unstable_getCurrentPriorityLevel,Kt=n.unstable_ImmediatePriority,Jn=n.unstable_UserBlockingPriority,Ci=n.unstable_NormalPriority,si=n.unstable_LowPriority,Wa=n.unstable_IdlePriority,Ka=n.log,oa=n.unstable_setDisableYieldValue,tn=null,Le=null;function Ht(i){if(typeof Ka=="function"&&oa(i),Le&&typeof Le.setStrictMode=="function")try{Le.setStrictMode(tn,i)}catch{}}var gt=Math.clz32?Math.clz32:Qa,wn=Math.log,xs=Math.LN2;function Qa(i){return i>>>=0,i===0?32:31-(wn(i)/xs|0)|0}var Ls=256,mt=262144,Wi=4194304;function mr(i){var a=i&42;if(a!==0)return a;switch(i&-i){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return i&261888;case 262144:case 524288:case 1048576:case 2097152:return i&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return i&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return i}}function sr(i,a,h){var g=i.pendingLanes;if(g===0)return 0;var A=0,C=i.suspendedLanes,M=i.pingedLanes;i=i.warmLanes;var U=g&134217727;return U!==0?(g=U&~C,g!==0?A=mr(g):(M&=U,M!==0?A=mr(M):h||(h=U&~i,h!==0&&(A=mr(h))))):(U=g&~C,U!==0?A=mr(U):M!==0?A=mr(M):h||(h=g&~i,h!==0&&(A=mr(h)))),A===0?0:a!==0&&a!==A&&(a&C)===0&&(C=A&-A,h=a&-a,C>=h||C===32&&(h&4194048)!==0)?a:A}function ai(i,a){return(i.pendingLanes&~(i.suspendedLanes&~i.pingedLanes)&a)===0}function Ps(i,a){switch(i){case 1:case 2:case 4:case 8:case 64:return a+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return a+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Un(){var i=Wi;return Wi<<=1,(Wi&62914560)===0&&(Wi=4194304),i}function Ki(i){for(var a=[],h=0;31>h;h++)a.push(i);return a}function Or(i,a){i.pendingLanes|=a,a!==268435456&&(i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0)}function ln(i,a,h,g,A,C){var M=i.pendingLanes;i.pendingLanes=h,i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0,i.expiredLanes&=h,i.entangledLanes&=h,i.errorRecoveryDisabledLanes&=h,i.shellSuspendCounter=0;var U=i.entanglements,$=i.expirationTimes,ge=i.hiddenUpdates;for(h=M&~h;0"u")return null;try{return i.activeElement||i.body}catch{return i.body}}var Ji=/[\n"\\]/g;function at(i){return i.replace(Ji,function(a){return"\\"+a.charCodeAt(0).toString(16)+" "})}function bn(i,a,h,g,A,C,M,U){i.name="",M!=null&&typeof M!="function"&&typeof M!="symbol"&&typeof M!="boolean"?i.type=M:i.removeAttribute("type"),a!=null?M==="number"?(a===0&&i.value===""||i.value!=a)&&(i.value=""+kt(a)):i.value!==""+kt(a)&&(i.value=""+kt(a)):M!=="submit"&&M!=="reset"||i.removeAttribute("value"),a!=null?q(i,M,kt(a)):h!=null?q(i,M,kt(h)):g!=null&&i.removeAttribute("value"),A==null&&C!=null&&(i.defaultChecked=!!C),A!=null&&(i.checked=A&&typeof A!="function"&&typeof A!="symbol"),U!=null&&typeof U!="function"&&typeof U!="symbol"&&typeof U!="boolean"?i.name=""+kt(U):i.removeAttribute("name")}function he(i,a,h,g,A,C,M,U){if(C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"&&(i.type=C),a!=null||h!=null){if(!(C!=="submit"&&C!=="reset"||a!=null)){cn(i);return}h=h!=null?""+kt(h):"",a=a!=null?""+kt(a):h,U||a===i.value||(i.value=a),i.defaultValue=a}g=g??A,g=typeof g!="function"&&typeof g!="symbol"&&!!g,i.checked=U?i.checked:!!g,i.defaultChecked=!!g,M!=null&&typeof M!="function"&&typeof M!="symbol"&&typeof M!="boolean"&&(i.name=M),cn(i)}function q(i,a,h){a==="number"&&Za(i.ownerDocument)===i||i.defaultValue===""+h||(i.defaultValue=""+h)}function Be(i,a,h,g){if(i=i.options,a){a={};for(var A=0;A"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Jo=!1;if(rn)try{var Er={};Object.defineProperty(Er,"passive",{get:function(){Jo=!0}}),window.addEventListener("test",Er,Er),window.removeEventListener("test",Er,Er)}catch{Jo=!1}var $i=null,wr=null,rs=null;function vr(){if(rs)return rs;var i,a=wr,h=a.length,g,A="value"in $i?$i.value:$i.textContent,C=A.length;for(i=0;i=D),Ee=" ",Ve=!1;function qt(i,a){switch(i){case"keyup":return v.indexOf(a.keyCode)!==-1;case"keydown":return a.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Tn(i){return i=i.detail,typeof i=="object"&&"data"in i?i.data:null}var yt=!1;function yn(i,a){switch(i){case"compositionend":return Tn(a);case"keypress":return a.which!==32?null:(Ve=!0,Ee);case"textInput":return i=a.data,i===Ee&&Ve?null:i;default:return null}}function Pn(i,a){if(yt)return i==="compositionend"||!I&&qt(i,a)?(i=vr(),rs=wr=$i=null,yt=!1,i):null;switch(i){case"paste":return null;case"keypress":if(!(a.ctrlKey||a.altKey||a.metaKey)||a.ctrlKey&&a.altKey){if(a.char&&1=a)return{node:h,offset:a-i};i=g}e:{for(;h;){if(h.nextSibling){h=h.nextSibling;break e}h=h.parentNode}h=void 0}h=_(h)}}function N(i,a){return i&&a?i===a?!0:i&&i.nodeType===3?!1:a&&a.nodeType===3?N(i,a.parentNode):"contains"in i?i.contains(a):i.compareDocumentPosition?!!(i.compareDocumentPosition(a)&16):!1:!1}function k(i){i=i!=null&&i.ownerDocument!=null&&i.ownerDocument.defaultView!=null?i.ownerDocument.defaultView:window;for(var a=Za(i.document);a instanceof i.HTMLIFrameElement;){try{var h=typeof a.contentWindow.location.href=="string"}catch{h=!1}if(h)i=a.contentWindow;else break;a=Za(i.document)}return a}function B(i){var a=i&&i.nodeName&&i.nodeName.toLowerCase();return a&&(a==="input"&&(i.type==="text"||i.type==="search"||i.type==="tel"||i.type==="url"||i.type==="password")||a==="textarea"||i.contentEditable==="true")}var X=rn&&"documentMode"in document&&11>=document.documentMode,ee=null,ie=null,le=null,xe=!1;function Pe(i,a,h){var g=h.window===h?h.document:h.nodeType===9?h:h.ownerDocument;xe||ee==null||ee!==Za(g)||(g=ee,"selectionStart"in g&&B(g)?g={start:g.selectionStart,end:g.selectionEnd}:(g=(g.ownerDocument&&g.ownerDocument.defaultView||window).getSelection(),g={anchorNode:g.anchorNode,anchorOffset:g.anchorOffset,focusNode:g.focusNode,focusOffset:g.focusOffset}),le&&w(le,g)||(le=g,g=If(ie,"onSelect"),0>=M,A-=M,zs=1<<32-gt(a)+A|h<xt?(Ot=We,We=null):Ot=We.sibling;var Xt=pe(oe,We,de[xt],_e);if(Xt===null){We===null&&(We=Ot);break}i&&We&&Xt.alternate===null&&a(oe,We),re=C(Xt,re,xt),Yt===null?tt=Xt:Yt.sibling=Xt,Yt=Xt,We=Ot}if(xt===de.length)return h(oe,We),Bt&&ya(oe,xt),tt;if(We===null){for(;xtxt?(Ot=We,We=null):Ot=We.sibling;var To=pe(oe,We,Xt.value,_e);if(To===null){We===null&&(We=Ot);break}i&&We&&To.alternate===null&&a(oe,We),re=C(To,re,xt),Yt===null?tt=To:Yt.sibling=To,Yt=To,We=Ot}if(Xt.done)return h(oe,We),Bt&&ya(oe,xt),tt;if(We===null){for(;!Xt.done;xt++,Xt=de.next())Xt=Ce(oe,Xt.value,_e),Xt!==null&&(re=C(Xt,re,xt),Yt===null?tt=Xt:Yt.sibling=Xt,Yt=Xt);return Bt&&ya(oe,xt),tt}for(We=g(We);!Xt.done;xt++,Xt=de.next())Xt=ve(We,oe,xt,Xt.value,_e),Xt!==null&&(i&&Xt.alternate!==null&&We.delete(Xt.key===null?xt:Xt.key),re=C(Xt,re,xt),Yt===null?tt=Xt:Yt.sibling=Xt,Yt=Xt);return i&&We.forEach(function(w3){return a(oe,w3)}),Bt&&ya(oe,xt),tt}function gn(oe,re,de,_e){if(typeof de=="object"&&de!==null&&de.type===Y&&de.key===null&&(de=de.props.children),typeof de=="object"&&de!==null){switch(de.$$typeof){case P:e:{for(var tt=de.key;re!==null;){if(re.key===tt){if(tt=de.type,tt===Y){if(re.tag===7){h(oe,re.sibling),_e=A(re,de.props.children),_e.return=oe,oe=_e;break e}}else if(re.elementType===tt||typeof tt=="object"&&tt!==null&&tt.$$typeof===F&&hl(tt)===re.type){h(oe,re.sibling),_e=A(re,de.props),gu(_e,de),_e.return=oe,oe=_e;break e}h(oe,re);break}else a(oe,re);re=re.sibling}de.type===Y?(_e=al(de.props.children,oe.mode,_e,de.key),_e.return=oe,oe=_e):(_e=Gh(de.type,de.key,de.props,null,oe.mode,_e),gu(_e,de),_e.return=oe,oe=_e)}return M(oe);case j:e:{for(tt=de.key;re!==null;){if(re.key===tt)if(re.tag===4&&re.stateNode.containerInfo===de.containerInfo&&re.stateNode.implementation===de.implementation){h(oe,re.sibling),_e=A(re,de.children||[]),_e.return=oe,oe=_e;break e}else{h(oe,re);break}else a(oe,re);re=re.sibling}_e=M0(de,oe.mode,_e),_e.return=oe,oe=_e}return M(oe);case F:return de=hl(de),gn(oe,re,de,_e)}if(fe(de))return Ye(oe,re,de,_e);if(J(de)){if(tt=J(de),typeof tt!="function")throw Error(r(150));return de=tt.call(de),rt(oe,re,de,_e)}if(typeof de.then=="function")return gn(oe,re,Zh(de),_e);if(de.$$typeof===K)return gn(oe,re,Xh(oe,de),_e);Jh(oe,de)}return typeof de=="string"&&de!==""||typeof de=="number"||typeof de=="bigint"?(de=""+de,re!==null&&re.tag===6?(h(oe,re.sibling),_e=A(re,de),_e.return=oe,oe=_e):(h(oe,re),_e=N0(de,oe.mode,_e),_e.return=oe,oe=_e),M(oe)):h(oe,re)}return function(oe,re,de,_e){try{du=0;var tt=gn(oe,re,de,_e);return nc=null,tt}catch(We){if(We===tc||We===Kh)throw We;var Yt=Fr(29,We,null,oe.mode);return Yt.lanes=_e,Yt.return=oe,Yt}finally{}}}var dl=Wy(!0),Ky=Wy(!1),so=!1;function H0(i){i.updateQueue={baseState:i.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function G0(i,a){i=i.updateQueue,a.updateQueue===i&&(a.updateQueue={baseState:i.baseState,firstBaseUpdate:i.firstBaseUpdate,lastBaseUpdate:i.lastBaseUpdate,shared:i.shared,callbacks:null})}function ao(i){return{lane:i,tag:0,payload:null,callback:null,next:null}}function oo(i,a,h){var g=i.updateQueue;if(g===null)return null;if(g=g.shared,(Qt&2)!==0){var A=g.pending;return A===null?a.next=a:(a.next=A.next,A.next=a),g.pending=a,a=Hh(i),Dy(i,null,h),a}return zh(i,g,a,h),Hh(i)}function mu(i,a,h){if(a=a.updateQueue,a!==null&&(a=a.shared,(h&4194048)!==0)){var g=a.lanes;g&=i.pendingLanes,h|=g,a.lanes=h,Qi(i,h)}}function q0(i,a){var h=i.updateQueue,g=i.alternate;if(g!==null&&(g=g.updateQueue,h===g)){var A=null,C=null;if(h=h.firstBaseUpdate,h!==null){do{var M={lane:h.lane,tag:h.tag,payload:h.payload,callback:null,next:null};C===null?A=C=M:C=C.next=M,h=h.next}while(h!==null);C===null?A=C=a:C=C.next=a}else A=C=a;h={baseState:g.baseState,firstBaseUpdate:A,lastBaseUpdate:C,shared:g.shared,callbacks:g.callbacks},i.updateQueue=h;return}i=h.lastBaseUpdate,i===null?h.firstBaseUpdate=a:i.next=a,h.lastBaseUpdate=a}var Y0=!1;function pu(){if(Y0){var i=ec;if(i!==null)throw i}}function yu(i,a,h,g){Y0=!1;var A=i.updateQueue;so=!1;var C=A.firstBaseUpdate,M=A.lastBaseUpdate,U=A.shared.pending;if(U!==null){A.shared.pending=null;var $=U,ge=$.next;$.next=null,M===null?C=ge:M.next=ge,M=$;var Te=i.alternate;Te!==null&&(Te=Te.updateQueue,U=Te.lastBaseUpdate,U!==M&&(U===null?Te.firstBaseUpdate=ge:U.next=ge,Te.lastBaseUpdate=$))}if(C!==null){var Ce=A.baseState;M=0,Te=ge=$=null,U=C;do{var pe=U.lane&-536870913,ve=pe!==U.lane;if(ve?(Dt&pe)===pe:(g&pe)===pe){pe!==0&&pe===$l&&(Y0=!0),Te!==null&&(Te=Te.next={lane:0,tag:U.tag,payload:U.payload,callback:null,next:null});e:{var Ye=i,rt=U;pe=a;var gn=h;switch(rt.tag){case 1:if(Ye=rt.payload,typeof Ye=="function"){Ce=Ye.call(gn,Ce,pe);break e}Ce=Ye;break e;case 3:Ye.flags=Ye.flags&-65537|128;case 0:if(Ye=rt.payload,pe=typeof Ye=="function"?Ye.call(gn,Ce,pe):Ye,pe==null)break e;Ce=b({},Ce,pe);break e;case 2:so=!0}}pe=U.callback,pe!==null&&(i.flags|=64,ve&&(i.flags|=8192),ve=A.callbacks,ve===null?A.callbacks=[pe]:ve.push(pe))}else ve={lane:pe,tag:U.tag,payload:U.payload,callback:U.callback,next:null},Te===null?(ge=Te=ve,$=Ce):Te=Te.next=ve,M|=pe;if(U=U.next,U===null){if(U=A.shared.pending,U===null)break;ve=U,U=ve.next,ve.next=null,A.lastBaseUpdate=ve,A.shared.pending=null}}while(!0);Te===null&&($=Ce),A.baseState=$,A.firstBaseUpdate=ge,A.lastBaseUpdate=Te,C===null&&(A.shared.lanes=0),fo|=M,i.lanes=M,i.memoizedState=Ce}}function Qy(i,a){if(typeof i!="function")throw Error(r(191,i));i.call(a)}function Zy(i,a){var h=i.callbacks;if(h!==null)for(i.callbacks=null,i=0;iC?C:8;var M=me.T,U={};me.T=U,h1(i,!1,a,h);try{var $=A(),ge=me.S;if(ge!==null&&ge(U,$),$!==null&&typeof $=="object"&&typeof $.then=="function"){var Te=cI($,g);wu(i,a,Te,qr(i))}else wu(i,a,g,qr(i))}catch(Ce){wu(i,a,{then:function(){},status:"rejected",reason:Ce},qr())}finally{Ae.p=C,M!==null&&U.types!==null&&(M.types=U.types),me.T=M}}function mI(){}function c1(i,a,h,g){if(i.tag!==5)throw Error(r(476));var A=R2(i).queue;I2(i,A,a,Fe,h===null?mI:function(){return N2(i),h(g)})}function R2(i){var a=i.memoizedState;if(a!==null)return a;a={memoizedState:Fe,baseState:Fe,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:va,lastRenderedState:Fe},next:null};var h={};return a.next={memoizedState:h,baseState:h,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:va,lastRenderedState:h},next:null},i.memoizedState=a,i=i.alternate,i!==null&&(i.memoizedState=a),a}function N2(i){var a=R2(i);a.next===null&&(a=i.alternate.memoizedState),wu(i,a.next.queue,{},qr())}function u1(){return Ui(Bu)}function M2(){return ii().memoizedState}function D2(){return ii().memoizedState}function pI(i){for(var a=i.return;a!==null;){switch(a.tag){case 24:case 3:var h=qr();i=ao(h);var g=oo(a,i,h);g!==null&&(Nr(g,a,h),mu(g,a,h)),a={cache:U0()},i.payload=a;return}a=a.return}}function yI(i,a,h){var g=qr();h={lane:g,revertLane:0,gesture:null,action:h,hasEagerState:!1,eagerState:null,next:null},cf(i)?L2(a,h):(h=I0(i,a,h,g),h!==null&&(Nr(h,i,g),P2(h,a,g)))}function O2(i,a,h){var g=qr();wu(i,a,h,g)}function wu(i,a,h,g){var A={lane:g,revertLane:0,gesture:null,action:h,hasEagerState:!1,eagerState:null,next:null};if(cf(i))L2(a,A);else{var C=i.alternate;if(i.lanes===0&&(C===null||C.lanes===0)&&(C=a.lastRenderedReducer,C!==null))try{var M=a.lastRenderedState,U=C(M,h);if(A.hasEagerState=!0,A.eagerState=U,p(U,M))return zh(i,a,A,0),xn===null&&jh(),!1}catch{}finally{}if(h=I0(i,a,A,g),h!==null)return Nr(h,i,g),P2(h,a,g),!0}return!1}function h1(i,a,h,g){if(g={lane:2,revertLane:H1(),gesture:null,action:g,hasEagerState:!1,eagerState:null,next:null},cf(i)){if(a)throw Error(r(479))}else a=I0(i,h,g,2),a!==null&&Nr(a,i,2)}function cf(i){var a=i.alternate;return i===pt||a!==null&&a===pt}function L2(i,a){rc=tf=!0;var h=i.pending;h===null?a.next=a:(a.next=h.next,h.next=a),i.pending=a}function P2(i,a,h){if((h&4194048)!==0){var g=a.lanes;g&=i.pendingLanes,h|=g,a.lanes=h,Qi(i,h)}}var vu={readContext:Ui,use:sf,useCallback:qn,useContext:qn,useEffect:qn,useImperativeHandle:qn,useLayoutEffect:qn,useInsertionEffect:qn,useMemo:qn,useReducer:qn,useRef:qn,useState:qn,useDebugValue:qn,useDeferredValue:qn,useTransition:qn,useSyncExternalStore:qn,useId:qn,useHostTransitionStatus:qn,useFormState:qn,useActionState:qn,useOptimistic:qn,useMemoCache:qn,useCacheRefresh:qn};vu.useEffectEvent=qn;var k2={readContext:Ui,use:sf,useCallback:function(i,a){return hr().memoizedState=[i,a===void 0?null:a],i},useContext:Ui,useEffect:E2,useImperativeHandle:function(i,a,h){h=h!=null?h.concat([i]):null,of(4194308,4,T2.bind(null,a,i),h)},useLayoutEffect:function(i,a){return of(4194308,4,i,a)},useInsertionEffect:function(i,a){of(4,2,i,a)},useMemo:function(i,a){var h=hr();a=a===void 0?null:a;var g=i();if(gl){Ht(!0);try{i()}finally{Ht(!1)}}return h.memoizedState=[g,a],g},useReducer:function(i,a,h){var g=hr();if(h!==void 0){var A=h(a);if(gl){Ht(!0);try{h(a)}finally{Ht(!1)}}}else A=a;return g.memoizedState=g.baseState=A,i={pending:null,lanes:0,dispatch:null,lastRenderedReducer:i,lastRenderedState:A},g.queue=i,i=i.dispatch=yI.bind(null,pt,i),[g.memoizedState,i]},useRef:function(i){var a=hr();return i={current:i},a.memoizedState=i},useState:function(i){i=r1(i);var a=i.queue,h=O2.bind(null,pt,a);return a.dispatch=h,[i.memoizedState,h]},useDebugValue:o1,useDeferredValue:function(i,a){var h=hr();return l1(h,i,a)},useTransition:function(){var i=r1(!1);return i=I2.bind(null,pt,i.queue,!0,!1),hr().memoizedState=i,[!1,i]},useSyncExternalStore:function(i,a,h){var g=pt,A=hr();if(Bt){if(h===void 0)throw Error(r(407));h=h()}else{if(h=a(),xn===null)throw Error(r(349));(Dt&127)!==0||i2(g,a,h)}A.memoizedState=h;var C={value:h,getSnapshot:a};return A.queue=C,E2(s2.bind(null,g,C,i),[i]),g.flags|=2048,ac(9,{destroy:void 0},r2.bind(null,g,C,h,a),null),h},useId:function(){var i=hr(),a=xn.identifierPrefix;if(Bt){var h=Hs,g=zs;h=(g&~(1<<32-gt(g)-1)).toString(32)+h,a="_"+a+"R_"+h,h=nf++,0<\/script>",C=C.removeChild(C.firstChild);break;case"select":C=typeof g.is=="string"?M.createElement("select",{is:g.is}):M.createElement("select"),g.multiple?C.multiple=!0:g.size&&(C.size=g.size);break;default:C=typeof g.is=="string"?M.createElement(A,{is:g.is}):M.createElement(A)}}C[vn]=a,C[Gt]=g;e:for(M=a.child;M!==null;){if(M.tag===5||M.tag===6)C.appendChild(M.stateNode);else if(M.tag!==4&&M.tag!==27&&M.child!==null){M.child.return=M,M=M.child;continue}if(M===a)break e;for(;M.sibling===null;){if(M.return===null||M.return===a)break e;M=M.return}M.sibling.return=M.return,M=M.sibling}a.stateNode=C;e:switch(ji(C,A,g),A){case"button":case"input":case"select":case"textarea":g=!!g.autoFocus;break e;case"img":g=!0;break e;default:g=!1}g&&Ta(a)}}return In(a),C1(a,a.type,i===null?null:i.memoizedProps,a.pendingProps,h),null;case 6:if(i&&a.stateNode!=null)i.memoizedProps!==g&&Ta(a);else{if(typeof g!="string"&&a.stateNode===null)throw Error(r(166));if(i=ke.current,Zl(a)){if(i=a.stateNode,h=a.memoizedProps,g=null,A=Vi,A!==null)switch(A.tag){case 27:case 5:g=A.memoizedProps}i[vn]=a,i=!!(i.nodeValue===h||g!==null&&g.suppressHydrationWarning===!0||tE(i.nodeValue,h)),i||io(a,!0)}else i=Rf(i).createTextNode(g),i[vn]=a,a.stateNode=i}return In(a),null;case 31:if(h=a.memoizedState,i===null||i.memoizedState!==null){if(g=Zl(a),h!==null){if(i===null){if(!g)throw Error(r(318));if(i=a.memoizedState,i=i!==null?i.dehydrated:null,!i)throw Error(r(557));i[vn]=a}else ol(),(a.flags&128)===0&&(a.memoizedState=null),a.flags|=4;In(a),i=!1}else h=P0(),i!==null&&i.memoizedState!==null&&(i.memoizedState.hydrationErrors=h),i=!0;if(!i)return a.flags&256?(zr(a),a):(zr(a),null);if((a.flags&128)!==0)throw Error(r(558))}return In(a),null;case 13:if(g=a.memoizedState,i===null||i.memoizedState!==null&&i.memoizedState.dehydrated!==null){if(A=Zl(a),g!==null&&g.dehydrated!==null){if(i===null){if(!A)throw Error(r(318));if(A=a.memoizedState,A=A!==null?A.dehydrated:null,!A)throw Error(r(317));A[vn]=a}else ol(),(a.flags&128)===0&&(a.memoizedState=null),a.flags|=4;In(a),A=!1}else A=P0(),i!==null&&i.memoizedState!==null&&(i.memoizedState.hydrationErrors=A),A=!0;if(!A)return a.flags&256?(zr(a),a):(zr(a),null)}return zr(a),(a.flags&128)!==0?(a.lanes=h,a):(h=g!==null,i=i!==null&&i.memoizedState!==null,h&&(g=a.child,A=null,g.alternate!==null&&g.alternate.memoizedState!==null&&g.alternate.memoizedState.cachePool!==null&&(A=g.alternate.memoizedState.cachePool.pool),C=null,g.memoizedState!==null&&g.memoizedState.cachePool!==null&&(C=g.memoizedState.cachePool.pool),C!==A&&(g.flags|=2048)),h!==i&&h&&(a.child.flags|=8192),gf(a,a.updateQueue),In(a),null);case 4:return en(),i===null&&X1(a.stateNode.containerInfo),In(a),null;case 10:return Ea(a.type),In(a),null;case 19:if(we(ni),g=a.memoizedState,g===null)return In(a),null;if(A=(a.flags&128)!==0,C=g.rendering,C===null)if(A)Tu(g,!1);else{if(Yn!==0||i!==null&&(i.flags&128)!==0)for(i=a.child;i!==null;){if(C=ef(i),C!==null){for(a.flags|=128,Tu(g,!1),i=C.updateQueue,a.updateQueue=i,gf(a,i),a.subtreeFlags=0,i=h,h=a.child;h!==null;)Oy(h,i),h=h.sibling;return De(ni,ni.current&1|2),Bt&&ya(a,g.treeForkCount),a.child}i=i.sibling}g.tail!==null&&mn()>Ef&&(a.flags|=128,A=!0,Tu(g,!1),a.lanes=4194304)}else{if(!A)if(i=ef(C),i!==null){if(a.flags|=128,A=!0,i=i.updateQueue,a.updateQueue=i,gf(a,i),Tu(g,!0),g.tail===null&&g.tailMode==="hidden"&&!C.alternate&&!Bt)return In(a),null}else 2*mn()-g.renderingStartTime>Ef&&h!==536870912&&(a.flags|=128,A=!0,Tu(g,!1),a.lanes=4194304);g.isBackwards?(C.sibling=a.child,a.child=C):(i=g.last,i!==null?i.sibling=C:a.child=C,g.last=C)}return g.tail!==null?(i=g.tail,g.rendering=i,g.tail=i.sibling,g.renderingStartTime=mn(),i.sibling=null,h=ni.current,De(ni,A?h&1|2:h&1),Bt&&ya(a,g.treeForkCount),i):(In(a),null);case 22:case 23:return zr(a),W0(),g=a.memoizedState!==null,i!==null?i.memoizedState!==null!==g&&(a.flags|=8192):g&&(a.flags|=8192),g?(h&536870912)!==0&&(a.flags&128)===0&&(In(a),a.subtreeFlags&6&&(a.flags|=8192)):In(a),h=a.updateQueue,h!==null&&gf(a,h.retryQueue),h=null,i!==null&&i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(h=i.memoizedState.cachePool.pool),g=null,a.memoizedState!==null&&a.memoizedState.cachePool!==null&&(g=a.memoizedState.cachePool.pool),g!==h&&(a.flags|=2048),i!==null&&we(ul),null;case 24:return h=null,i!==null&&(h=i.memoizedState.cache),a.memoizedState.cache!==h&&(a.flags|=2048),Ea(ci),In(a),null;case 25:return null;case 30:return null}throw Error(r(156,a.tag))}function AI(i,a){switch(O0(a),a.tag){case 1:return i=a.flags,i&65536?(a.flags=i&-65537|128,a):null;case 3:return Ea(ci),en(),i=a.flags,(i&65536)!==0&&(i&128)===0?(a.flags=i&-65537|128,a):null;case 26:case 27:case 5:return Mn(a),null;case 31:if(a.memoizedState!==null){if(zr(a),a.alternate===null)throw Error(r(340));ol()}return i=a.flags,i&65536?(a.flags=i&-65537|128,a):null;case 13:if(zr(a),i=a.memoizedState,i!==null&&i.dehydrated!==null){if(a.alternate===null)throw Error(r(340));ol()}return i=a.flags,i&65536?(a.flags=i&-65537|128,a):null;case 19:return we(ni),null;case 4:return en(),null;case 10:return Ea(a.type),null;case 22:case 23:return zr(a),W0(),i!==null&&we(ul),i=a.flags,i&65536?(a.flags=i&-65537|128,a):null;case 24:return Ea(ci),null;case 25:return null;default:return null}}function ax(i,a){switch(O0(a),a.tag){case 3:Ea(ci),en();break;case 26:case 27:case 5:Mn(a);break;case 4:en();break;case 31:a.memoizedState!==null&&zr(a);break;case 13:zr(a);break;case 19:we(ni);break;case 10:Ea(a.type);break;case 22:case 23:zr(a),W0(),i!==null&&we(ul);break;case 24:Ea(ci)}}function _u(i,a){try{var h=a.updateQueue,g=h!==null?h.lastEffect:null;if(g!==null){var A=g.next;h=A;do{if((h.tag&i)===i){g=void 0;var C=h.create,M=h.inst;g=C(),M.destroy=g}h=h.next}while(h!==A)}}catch(U){an(a,a.return,U)}}function uo(i,a,h){try{var g=a.updateQueue,A=g!==null?g.lastEffect:null;if(A!==null){var C=A.next;g=C;do{if((g.tag&i)===i){var M=g.inst,U=M.destroy;if(U!==void 0){M.destroy=void 0,A=a;var $=h,ge=U;try{ge()}catch(Te){an(A,$,Te)}}}g=g.next}while(g!==C)}}catch(Te){an(a,a.return,Te)}}function ox(i){var a=i.updateQueue;if(a!==null){var h=i.stateNode;try{Zy(a,h)}catch(g){an(i,i.return,g)}}}function lx(i,a,h){h.props=ml(i.type,i.memoizedProps),h.state=i.memoizedState;try{h.componentWillUnmount()}catch(g){an(i,a,g)}}function Cu(i,a){try{var h=i.ref;if(h!==null){switch(i.tag){case 26:case 27:case 5:var g=i.stateNode;break;case 30:g=i.stateNode;break;default:g=i.stateNode}typeof h=="function"?i.refCleanup=h(g):h.current=g}}catch(A){an(i,a,A)}}function Gs(i,a){var h=i.ref,g=i.refCleanup;if(h!==null)if(typeof g=="function")try{g()}catch(A){an(i,a,A)}finally{i.refCleanup=null,i=i.alternate,i!=null&&(i.refCleanup=null)}else if(typeof h=="function")try{h(null)}catch(A){an(i,a,A)}else h.current=null}function cx(i){var a=i.type,h=i.memoizedProps,g=i.stateNode;try{e:switch(a){case"button":case"input":case"select":case"textarea":h.autoFocus&&g.focus();break e;case"img":h.src?g.src=h.src:h.srcSet&&(g.srcset=h.srcSet)}}catch(A){an(i,i.return,A)}}function b1(i,a,h){try{var g=i.stateNode;GI(g,i.type,h,a),g[Gt]=a}catch(A){an(i,i.return,A)}}function ux(i){return i.tag===5||i.tag===3||i.tag===26||i.tag===27&&xo(i.type)||i.tag===4}function S1(i){e:for(;;){for(;i.sibling===null;){if(i.return===null||ux(i.return))return null;i=i.return}for(i.sibling.return=i.return,i=i.sibling;i.tag!==5&&i.tag!==6&&i.tag!==18;){if(i.tag===27&&xo(i.type)||i.flags&2||i.child===null||i.tag===4)continue e;i.child.return=i,i=i.child}if(!(i.flags&2))return i.stateNode}}function I1(i,a,h){var g=i.tag;if(g===5||g===6)i=i.stateNode,a?(h.nodeType===9?h.body:h.nodeName==="HTML"?h.ownerDocument.body:h).insertBefore(i,a):(a=h.nodeType===9?h.body:h.nodeName==="HTML"?h.ownerDocument.body:h,a.appendChild(i),h=h._reactRootContainer,h!=null||a.onclick!==null||(a.onclick=Ln));else if(g!==4&&(g===27&&xo(i.type)&&(h=i.stateNode,a=null),i=i.child,i!==null))for(I1(i,a,h),i=i.sibling;i!==null;)I1(i,a,h),i=i.sibling}function mf(i,a,h){var g=i.tag;if(g===5||g===6)i=i.stateNode,a?h.insertBefore(i,a):h.appendChild(i);else if(g!==4&&(g===27&&xo(i.type)&&(h=i.stateNode),i=i.child,i!==null))for(mf(i,a,h),i=i.sibling;i!==null;)mf(i,a,h),i=i.sibling}function hx(i){var a=i.stateNode,h=i.memoizedProps;try{for(var g=i.type,A=a.attributes;A.length;)a.removeAttributeNode(A[0]);ji(a,g,h),a[vn]=i,a[Gt]=h}catch(C){an(i,i.return,C)}}var _a=!1,fi=!1,R1=!1,fx=typeof WeakSet=="function"?WeakSet:Set,Ri=null;function TI(i,a){if(i=i.containerInfo,Q1=kf,i=k(i),B(i)){if("selectionStart"in i)var h={start:i.selectionStart,end:i.selectionEnd};else e:{h=(h=i.ownerDocument)&&h.defaultView||window;var g=h.getSelection&&h.getSelection();if(g&&g.rangeCount!==0){h=g.anchorNode;var A=g.anchorOffset,C=g.focusNode;g=g.focusOffset;try{h.nodeType,C.nodeType}catch{h=null;break e}var M=0,U=-1,$=-1,ge=0,Te=0,Ce=i,pe=null;t:for(;;){for(var ve;Ce!==h||A!==0&&Ce.nodeType!==3||(U=M+A),Ce!==C||g!==0&&Ce.nodeType!==3||($=M+g),Ce.nodeType===3&&(M+=Ce.nodeValue.length),(ve=Ce.firstChild)!==null;)pe=Ce,Ce=ve;for(;;){if(Ce===i)break t;if(pe===h&&++ge===A&&(U=M),pe===C&&++Te===g&&($=M),(ve=Ce.nextSibling)!==null)break;Ce=pe,pe=Ce.parentNode}Ce=ve}h=U===-1||$===-1?null:{start:U,end:$}}else h=null}h=h||{start:0,end:0}}else h=null;for(Z1={focusedElem:i,selectionRange:h},kf=!1,Ri=a;Ri!==null;)if(a=Ri,i=a.child,(a.subtreeFlags&1028)!==0&&i!==null)i.return=a,Ri=i;else for(;Ri!==null;){switch(a=Ri,C=a.alternate,i=a.flags,a.tag){case 0:if((i&4)!==0&&(i=a.updateQueue,i=i!==null?i.events:null,i!==null))for(h=0;h title"))),ji(C,g,h),C[vn]=i,Cn(C),g=C;break e;case"link":var M=xE("link","href",A).get(g+(h.href||""));if(M){for(var U=0;Ugn&&(M=gn,gn=rt,rt=M);var oe=S(U,rt),re=S(U,gn);if(oe&&re&&(ve.rangeCount!==1||ve.anchorNode!==oe.node||ve.anchorOffset!==oe.offset||ve.focusNode!==re.node||ve.focusOffset!==re.offset)){var de=Ce.createRange();de.setStart(oe.node,oe.offset),ve.removeAllRanges(),rt>gn?(ve.addRange(de),ve.extend(re.node,re.offset)):(de.setEnd(re.node,re.offset),ve.addRange(de))}}}}for(Ce=[],ve=U;ve=ve.parentNode;)ve.nodeType===1&&Ce.push({element:ve,left:ve.scrollLeft,top:ve.scrollTop});for(typeof U.focus=="function"&&U.focus(),U=0;Uh?32:h,me.T=null,h=k1,k1=null;var C=mo,M=Ra;if(Ei=0,hc=mo=null,Ra=0,(Qt&6)!==0)throw Error(r(331));var U=Qt;if(Qt|=4,Tx(C.current),wx(C,C.current,M,h),Qt=U,Mu(0,!1),Le&&typeof Le.onPostCommitFiberRoot=="function")try{Le.onPostCommitFiberRoot(tn,C)}catch{}return!0}finally{Ae.p=A,me.T=g,jx(i,a)}}function Hx(i,a,h){a=ls(h,a),a=m1(i.stateNode,a,2),i=oo(i,a,2),i!==null&&(Or(i,2),qs(i))}function an(i,a,h){if(i.tag===3)Hx(i,i,h);else for(;a!==null;){if(a.tag===3){Hx(a,i,h);break}else if(a.tag===1){var g=a.stateNode;if(typeof a.type.getDerivedStateFromError=="function"||typeof g.componentDidCatch=="function"&&(go===null||!go.has(g))){i=ls(h,i),h=G2(2),g=oo(a,h,2),g!==null&&(q2(h,g,a,i),Or(g,2),qs(g));break}}a=a.return}}function F1(i,a,h){var g=i.pingCache;if(g===null){g=i.pingCache=new bI;var A=new Set;g.set(a,A)}else A=g.get(a),A===void 0&&(A=new Set,g.set(a,A));A.has(h)||(D1=!0,A.add(h),i=MI.bind(null,i,a,h),a.then(i,i))}function MI(i,a,h){var g=i.pingCache;g!==null&&g.delete(a),i.pingedLanes|=i.suspendedLanes&h,i.warmLanes&=~h,xn===i&&(Dt&h)===h&&(Yn===4||Yn===3&&(Dt&62914560)===Dt&&300>mn()-xf?(Qt&2)===0&&fc(i,0):O1|=h,uc===Dt&&(uc=0)),qs(i)}function Gx(i,a){a===0&&(a=Un()),i=sl(i,a),i!==null&&(Or(i,a),qs(i))}function DI(i){var a=i.memoizedState,h=0;a!==null&&(h=a.retryLane),Gx(i,h)}function OI(i,a){var h=0;switch(i.tag){case 31:case 13:var g=i.stateNode,A=i.memoizedState;A!==null&&(h=A.retryLane);break;case 19:g=i.stateNode;break;case 22:g=i.stateNode._retryCache;break;default:throw Error(r(314))}g!==null&&g.delete(a),Gx(i,h)}function LI(i,a){return es(i,a)}var Cf=null,gc=null,j1=!1,bf=!1,z1=!1,yo=0;function qs(i){i!==gc&&i.next===null&&(gc===null?Cf=gc=i:gc=gc.next=i),bf=!0,j1||(j1=!0,kI())}function Mu(i,a){if(!z1&&bf){z1=!0;do for(var h=!1,g=Cf;g!==null;){if(i!==0){var A=g.pendingLanes;if(A===0)var C=0;else{var M=g.suspendedLanes,U=g.pingedLanes;C=(1<<31-gt(42|i)+1)-1,C&=A&~(M&~U),C=C&201326741?C&201326741|1:C?C|2:0}C!==0&&(h=!0,Wx(g,C))}else C=Dt,C=sr(g,g===xn?C:0,g.cancelPendingCommit!==null||g.timeoutHandle!==-1),(C&3)===0||ai(g,C)||(h=!0,Wx(g,C));g=g.next}while(h);z1=!1}}function PI(){qx()}function qx(){bf=j1=!1;var i=0;yo!==0&&YI()&&(i=yo);for(var a=mn(),h=null,g=Cf;g!==null;){var A=g.next,C=Yx(g,a);C===0?(g.next=null,h===null?Cf=A:h.next=A,A===null&&(gc=h)):(h=g,(i!==0||(C&3)!==0)&&(bf=!0)),g=A}Ei!==0&&Ei!==5||Mu(i),yo!==0&&(yo=0)}function Yx(i,a){for(var h=i.suspendedLanes,g=i.pingedLanes,A=i.expirationTimes,C=i.pendingLanes&-62914561;0U)break;var Te=$.transferSize,Ce=$.initiatorType;Te&&nE(Ce)&&($=$.responseEnd,M+=Te*($"u"?null:document;function gE(i,a,h){var g=mc;if(g&&typeof a=="string"&&a){var A=at(a);A='link[rel="'+i+'"][href="'+A+'"]',typeof h=="string"&&(A+='[crossorigin="'+h+'"]'),dE.has(A)||(dE.add(A),i={rel:i,crossOrigin:h,href:a},g.querySelector(A)===null&&(a=g.createElement("link"),ji(a,"link",i),Cn(a),g.head.appendChild(a)))}}function t3(i){Na.D(i),gE("dns-prefetch",i,null)}function n3(i,a){Na.C(i,a),gE("preconnect",i,a)}function i3(i,a,h){Na.L(i,a,h);var g=mc;if(g&&i&&a){var A='link[rel="preload"][as="'+at(a)+'"]';a==="image"&&h&&h.imageSrcSet?(A+='[imagesrcset="'+at(h.imageSrcSet)+'"]',typeof h.imageSizes=="string"&&(A+='[imagesizes="'+at(h.imageSizes)+'"]')):A+='[href="'+at(i)+'"]';var C=A;switch(a){case"style":C=pc(i);break;case"script":C=yc(i)}gs.has(C)||(i=b({rel:"preload",href:a==="image"&&h&&h.imageSrcSet?void 0:i,as:a},h),gs.set(C,i),g.querySelector(A)!==null||a==="style"&&g.querySelector(Pu(C))||a==="script"&&g.querySelector(ku(C))||(a=g.createElement("link"),ji(a,"link",i),Cn(a),g.head.appendChild(a)))}}function r3(i,a){Na.m(i,a);var h=mc;if(h&&i){var g=a&&typeof a.as=="string"?a.as:"script",A='link[rel="modulepreload"][as="'+at(g)+'"][href="'+at(i)+'"]',C=A;switch(g){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":C=yc(i)}if(!gs.has(C)&&(i=b({rel:"modulepreload",href:i},a),gs.set(C,i),h.querySelector(A)===null)){switch(g){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(h.querySelector(ku(C)))return}g=h.createElement("link"),ji(g,"link",i),Cn(g),h.head.appendChild(g)}}}function s3(i,a,h){Na.S(i,a,h);var g=mc;if(g&&i){var A=li(g).hoistableStyles,C=pc(i);a=a||"default";var M=A.get(C);if(!M){var U={loading:0,preload:null};if(M=g.querySelector(Pu(C)))U.loading=5;else{i=b({rel:"stylesheet",href:i,"data-precedence":a},h),(h=gs.get(C))&&rg(i,h);var $=M=g.createElement("link");Cn($),ji($,"link",i),$._p=new Promise(function(ge,Te){$.onload=ge,$.onerror=Te}),$.addEventListener("load",function(){U.loading|=1}),$.addEventListener("error",function(){U.loading|=2}),U.loading|=4,Mf(M,a,g)}M={type:"stylesheet",instance:M,count:1,state:U},A.set(C,M)}}}function a3(i,a){Na.X(i,a);var h=mc;if(h&&i){var g=li(h).hoistableScripts,A=yc(i),C=g.get(A);C||(C=h.querySelector(ku(A)),C||(i=b({src:i,async:!0},a),(a=gs.get(A))&&sg(i,a),C=h.createElement("script"),Cn(C),ji(C,"link",i),h.head.appendChild(C)),C={type:"script",instance:C,count:1,state:null},g.set(A,C))}}function o3(i,a){Na.M(i,a);var h=mc;if(h&&i){var g=li(h).hoistableScripts,A=yc(i),C=g.get(A);C||(C=h.querySelector(ku(A)),C||(i=b({src:i,async:!0,type:"module"},a),(a=gs.get(A))&&sg(i,a),C=h.createElement("script"),Cn(C),ji(C,"link",i),h.head.appendChild(C)),C={type:"script",instance:C,count:1,state:null},g.set(A,C))}}function mE(i,a,h,g){var A=(A=ke.current)?Nf(A):null;if(!A)throw Error(r(446));switch(i){case"meta":case"title":return null;case"style":return typeof h.precedence=="string"&&typeof h.href=="string"?(a=pc(h.href),h=li(A).hoistableStyles,g=h.get(a),g||(g={type:"style",instance:null,count:0,state:null},h.set(a,g)),g):{type:"void",instance:null,count:0,state:null};case"link":if(h.rel==="stylesheet"&&typeof h.href=="string"&&typeof h.precedence=="string"){i=pc(h.href);var C=li(A).hoistableStyles,M=C.get(i);if(M||(A=A.ownerDocument||A,M={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},C.set(i,M),(C=A.querySelector(Pu(i)))&&!C._p&&(M.instance=C,M.state.loading=5),gs.has(i)||(h={rel:"preload",as:"style",href:h.href,crossOrigin:h.crossOrigin,integrity:h.integrity,media:h.media,hrefLang:h.hrefLang,referrerPolicy:h.referrerPolicy},gs.set(i,h),C||l3(A,i,h,M.state))),a&&g===null)throw Error(r(528,""));return M}if(a&&g!==null)throw Error(r(529,""));return null;case"script":return a=h.async,h=h.src,typeof h=="string"&&a&&typeof a!="function"&&typeof a!="symbol"?(a=yc(h),h=li(A).hoistableScripts,g=h.get(a),g||(g={type:"script",instance:null,count:0,state:null},h.set(a,g)),g):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,i))}}function pc(i){return'href="'+at(i)+'"'}function Pu(i){return'link[rel="stylesheet"]['+i+"]"}function pE(i){return b({},i,{"data-precedence":i.precedence,precedence:null})}function l3(i,a,h,g){i.querySelector('link[rel="preload"][as="style"]['+a+"]")?g.loading=1:(a=i.createElement("link"),g.preload=a,a.addEventListener("load",function(){return g.loading|=1}),a.addEventListener("error",function(){return g.loading|=2}),ji(a,"link",h),Cn(a),i.head.appendChild(a))}function yc(i){return'[src="'+at(i)+'"]'}function ku(i){return"script[async]"+i}function yE(i,a,h){if(a.count++,a.instance===null)switch(a.type){case"style":var g=i.querySelector('style[data-href~="'+at(h.href)+'"]');if(g)return a.instance=g,Cn(g),g;var A=b({},h,{"data-href":h.href,"data-precedence":h.precedence,href:null,precedence:null});return g=(i.ownerDocument||i).createElement("style"),Cn(g),ji(g,"style",A),Mf(g,h.precedence,i),a.instance=g;case"stylesheet":A=pc(h.href);var C=i.querySelector(Pu(A));if(C)return a.state.loading|=4,a.instance=C,Cn(C),C;g=pE(h),(A=gs.get(A))&&rg(g,A),C=(i.ownerDocument||i).createElement("link"),Cn(C);var M=C;return M._p=new Promise(function(U,$){M.onload=U,M.onerror=$}),ji(C,"link",g),a.state.loading|=4,Mf(C,h.precedence,i),a.instance=C;case"script":return C=yc(h.src),(A=i.querySelector(ku(C)))?(a.instance=A,Cn(A),A):(g=h,(A=gs.get(C))&&(g=b({},h),sg(g,A)),i=i.ownerDocument||i,A=i.createElement("script"),Cn(A),ji(A,"link",g),i.head.appendChild(A),a.instance=A);case"void":return null;default:throw Error(r(443,a.type))}else a.type==="stylesheet"&&(a.state.loading&4)===0&&(g=a.instance,a.state.loading|=4,Mf(g,h.precedence,i));return a.instance}function Mf(i,a,h){for(var g=h.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),A=g.length?g[g.length-1]:null,C=A,M=0;M title"):null)}function c3(i,a,h){if(h===1||a.itemProp!=null)return!1;switch(i){case"meta":case"title":return!0;case"style":if(typeof a.precedence!="string"||typeof a.href!="string"||a.href==="")break;return!0;case"link":if(typeof a.rel!="string"||typeof a.href!="string"||a.href===""||a.onLoad||a.onError)break;switch(a.rel){case"stylesheet":return i=a.disabled,typeof a.precedence=="string"&&i==null;default:return!0}case"script":if(a.async&&typeof a.async!="function"&&typeof a.async!="symbol"&&!a.onLoad&&!a.onError&&a.src&&typeof a.src=="string")return!0}return!1}function wE(i){return!(i.type==="stylesheet"&&(i.state.loading&3)===0)}function u3(i,a,h,g){if(h.type==="stylesheet"&&(typeof g.media!="string"||matchMedia(g.media).matches!==!1)&&(h.state.loading&4)===0){if(h.instance===null){var A=pc(g.href),C=a.querySelector(Pu(A));if(C){a=C._p,a!==null&&typeof a=="object"&&typeof a.then=="function"&&(i.count++,i=Of.bind(i),a.then(i,i)),h.state.loading|=4,h.instance=C,Cn(C);return}C=a.ownerDocument||a,g=pE(g),(A=gs.get(A))&&rg(g,A),C=C.createElement("link"),Cn(C);var M=C;M._p=new Promise(function(U,$){M.onload=U,M.onerror=$}),ji(C,"link",g),h.instance=C}i.stylesheets===null&&(i.stylesheets=new Map),i.stylesheets.set(h,a),(a=h.state.preload)&&(h.state.loading&3)===0&&(i.count++,h=Of.bind(i),a.addEventListener("load",h),a.addEventListener("error",h))}}var ag=0;function h3(i,a){return i.stylesheets&&i.count===0&&Pf(i,i.stylesheets),0ag?50:800)+a);return i.unsuspend=h,function(){i.unsuspend=null,clearTimeout(g),clearTimeout(A)}}:null}function Of(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Pf(this,this.stylesheets);else if(this.unsuspend){var i=this.unsuspend;this.unsuspend=null,i()}}}var Lf=null;function Pf(i,a){i.stylesheets=null,i.unsuspend!==null&&(i.count++,Lf=new Map,a.forEach(f3,i),Lf=null,Of.call(i))}function f3(i,a){if(!(a.state.loading&4)){var h=Lf.get(i);if(h)var g=h.get(null);else{h=new Map,Lf.set(i,h);for(var A=i.querySelectorAll("link[data-precedence],style[data-precedence]"),C=0;C"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}return n(),mg.exports=R3(),mg.exports}var M3=N3();/** - * react-router v7.2.0 - * - * Copyright (c) Remix Software Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE.md file in the root directory of this source tree. - * - * @license MIT - */var GE="popstate";function D3(n={}){function e(r,o){let{pathname:u,search:m,hash:x}=r.location;return Kg("",{pathname:u,search:m,hash:x},o.state&&o.state.usr||null,o.state&&o.state.key||"default")}function t(r,o){return typeof o=="string"?o:ah(o)}return L3(e,t,null,n)}function Bn(n,e){if(n===!1||n===null||typeof n>"u")throw new Error(e)}function ta(n,e){if(!n){typeof console<"u"&&console.warn(e);try{throw new Error(e)}catch{}}}function O3(){return Math.random().toString(36).substring(2,10)}function qE(n,e){return{usr:n.state,key:n.key,idx:e}}function Kg(n,e,t=null,r){return{pathname:typeof n=="string"?n:n.pathname,search:"",hash:"",...typeof e=="string"?Xc(e):e,state:t,key:e&&e.key||r||O3()}}function ah({pathname:n="/",search:e="",hash:t=""}){return e&&e!=="?"&&(n+=e.charAt(0)==="?"?e:"?"+e),t&&t!=="#"&&(n+=t.charAt(0)==="#"?t:"#"+t),n}function Xc(n){let e={};if(n){let t=n.indexOf("#");t>=0&&(e.hash=n.substring(t),n=n.substring(0,t));let r=n.indexOf("?");r>=0&&(e.search=n.substring(r),n=n.substring(0,r)),n&&(e.pathname=n)}return e}function L3(n,e,t,r={}){let{window:o=document.defaultView,v5Compat:u=!1}=r,m=o.history,x="POP",E=null,y=T();y==null&&(y=0,m.replaceState({...m.state,idx:y},""));function T(){return(m.state||{idx:null}).idx}function b(){x="POP";let G=T(),te=G==null?null:G-y;y=G,E&&E({action:x,location:Y.location,delta:te})}function R(G,te){x="PUSH";let se=Kg(Y.location,G,te);y=T()+1;let K=qE(se,y),ue=Y.createHref(se);try{m.pushState(K,"",ue)}catch(Se){if(Se instanceof DOMException&&Se.name==="DataCloneError")throw Se;o.location.assign(ue)}u&&E&&E({action:x,location:Y.location,delta:1})}function P(G,te){x="REPLACE";let se=Kg(Y.location,G,te);y=T();let K=qE(se,y),ue=Y.createHref(se);m.replaceState(K,"",ue),u&&E&&E({action:x,location:Y.location,delta:0})}function j(G){let te=o.location.origin!=="null"?o.location.origin:o.location.href,se=typeof G=="string"?G:ah(G);return se=se.replace(/ $/,"%20"),Bn(te,`No window.location.(origin|href) available to create URL for href: ${se}`),new URL(se,te)}let Y={get action(){return x},get location(){return n(o,m)},listen(G){if(E)throw new Error("A history only accepts one active listener");return o.addEventListener(GE,b),E=G,()=>{o.removeEventListener(GE,b),E=null}},createHref(G){return e(o,G)},createURL:j,encodeLocation(G){let te=j(G);return{pathname:te.pathname,search:te.search,hash:te.hash}},push:R,replace:P,go(G){return m.go(G)}};return Y}function tT(n,e,t="/"){return P3(n,e,t,!1)}function P3(n,e,t,r){let o=typeof e=="string"?Xc(e):e,u=Vo(o.pathname||"/",t);if(u==null)return null;let m=nT(n);k3(m);let x=null;for(let E=0;x==null&&E{let E={relativePath:x===void 0?u.path||"":x,caseSensitive:u.caseSensitive===!0,childrenIndex:m,route:u};E.relativePath.startsWith("/")&&(Bn(E.relativePath.startsWith(r),`Absolute route path "${E.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),E.relativePath=E.relativePath.slice(r.length));let y=ka([r,E.relativePath]),T=t.concat(E);u.children&&u.children.length>0&&(Bn(u.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${y}".`),nT(u.children,e,T,y)),!(u.path==null&&!u.index)&&e.push({path:y,score:H3(y,u.index),routesMeta:T})};return n.forEach((u,m)=>{var x;if(u.path===""||!((x=u.path)!=null&&x.includes("?")))o(u,m);else for(let E of iT(u.path))o(u,m,E)}),e}function iT(n){let e=n.split("/");if(e.length===0)return[];let[t,...r]=e,o=t.endsWith("?"),u=t.replace(/\?$/,"");if(r.length===0)return o?[u,""]:[u];let m=iT(r.join("/")),x=[];return x.push(...m.map(E=>E===""?u:[u,E].join("/"))),o&&x.push(...m),x.map(E=>n.startsWith("/")&&E===""?"/":E)}function k3(n){n.sort((e,t)=>e.score!==t.score?t.score-e.score:G3(e.routesMeta.map(r=>r.childrenIndex),t.routesMeta.map(r=>r.childrenIndex)))}var B3=/^:[\w-]+$/,V3=3,U3=2,F3=1,j3=10,z3=-2,YE=n=>n==="*";function H3(n,e){let t=n.split("/"),r=t.length;return t.some(YE)&&(r+=z3),e&&(r+=U3),t.filter(o=>!YE(o)).reduce((o,u)=>o+(B3.test(u)?V3:u===""?F3:j3),r)}function G3(n,e){return n.length===e.length&&n.slice(0,-1).every((r,o)=>r===e[o])?n[n.length-1]-e[e.length-1]:0}function q3(n,e,t=!1){let{routesMeta:r}=n,o={},u="/",m=[];for(let x=0;x{if(T==="*"){let j=x[R]||"";m=u.slice(0,u.length-j.length).replace(/(.)\/+$/,"$1")}const P=x[R];return b&&!P?y[T]=void 0:y[T]=(P||"").replace(/%2F/g,"/"),y},{}),pathname:u,pathnameBase:m,pattern:n}}function Y3(n,e=!1,t=!0){ta(n==="*"||!n.endsWith("*")||n.endsWith("/*"),`Route path "${n}" will be treated as if it were "${n.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${n.replace(/\*$/,"/*")}".`);let r=[],o="^"+n.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(m,x,E)=>(r.push({paramName:x,isOptional:E!=null}),E?"/?([^\\/]+)?":"/([^\\/]+)"));return n.endsWith("*")?(r.push({paramName:"*"}),o+=n==="*"||n==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):t?o+="\\/*$":n!==""&&n!=="/"&&(o+="(?:(?=\\/|$))"),[new RegExp(o,e?void 0:"i"),r]}function X3(n){try{return n.split("/").map(e=>decodeURIComponent(e).replace(/\//g,"%2F")).join("/")}catch(e){return ta(!1,`The URL path "${n}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${e}).`),n}}function Vo(n,e){if(e==="/")return n;if(!n.toLowerCase().startsWith(e.toLowerCase()))return null;let t=e.endsWith("/")?e.length-1:e.length,r=n.charAt(t);return r&&r!=="/"?null:n.slice(t)||"/"}function W3(n,e="/"){let{pathname:t,search:r="",hash:o=""}=typeof n=="string"?Xc(n):n;return{pathname:t?t.startsWith("/")?t:K3(t,e):e,search:J3(r),hash:$3(o)}}function K3(n,e){let t=e.replace(/\/+$/,"").split("/");return n.split("/").forEach(o=>{o===".."?t.length>1&&t.pop():o!=="."&&t.push(o)}),t.length>1?t.join("/"):"/"}function Eg(n,e,t,r){return`Cannot include a '${n}' character in a manually specified \`to.${e}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${t}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function Q3(n){return n.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function rT(n){let e=Q3(n);return e.map((t,r)=>r===e.length-1?t.pathname:t.pathnameBase)}function sT(n,e,t,r=!1){let o;typeof n=="string"?o=Xc(n):(o={...n},Bn(!o.pathname||!o.pathname.includes("?"),Eg("?","pathname","search",o)),Bn(!o.pathname||!o.pathname.includes("#"),Eg("#","pathname","hash",o)),Bn(!o.search||!o.search.includes("#"),Eg("#","search","hash",o)));let u=n===""||o.pathname==="",m=u?"/":o.pathname,x;if(m==null)x=t;else{let b=e.length-1;if(!r&&m.startsWith("..")){let R=m.split("/");for(;R[0]==="..";)R.shift(),b-=1;o.pathname=R.join("/")}x=b>=0?e[b]:"/"}let E=W3(o,x),y=m&&m!=="/"&&m.endsWith("/"),T=(u||m===".")&&t.endsWith("/");return!E.pathname.endsWith("/")&&(y||T)&&(E.pathname+="/"),E}var ka=n=>n.join("/").replace(/\/\/+/g,"/"),Z3=n=>n.replace(/\/+$/,"").replace(/^\/*/,"/"),J3=n=>!n||n==="?"?"":n.startsWith("?")?n:"?"+n,$3=n=>!n||n==="#"?"":n.startsWith("#")?n:"#"+n;function e4(n){return n!=null&&typeof n.status=="number"&&typeof n.statusText=="string"&&typeof n.internal=="boolean"&&"data"in n}var aT=["POST","PUT","PATCH","DELETE"];new Set(aT);var t4=["GET",...aT];new Set(t4);var Wc=ae.createContext(null);Wc.displayName="DataRouter";var Jd=ae.createContext(null);Jd.displayName="DataRouterState";var oT=ae.createContext({isTransitioning:!1});oT.displayName="ViewTransition";var n4=ae.createContext(new Map);n4.displayName="Fetchers";var i4=ae.createContext(null);i4.displayName="Await";var sa=ae.createContext(null);sa.displayName="Navigation";var vh=ae.createContext(null);vh.displayName="Location";var aa=ae.createContext({outlet:null,matches:[],isDataRoute:!1});aa.displayName="Route";var Zm=ae.createContext(null);Zm.displayName="RouteError";function r4(n,{relative:e}={}){Bn(Ah(),"useHref() may be used only in the context of a component.");let{basename:t,navigator:r}=ae.useContext(sa),{hash:o,pathname:u,search:m}=Th(n,{relative:e}),x=u;return t!=="/"&&(x=u==="/"?t:ka([t,u])),r.createHref({pathname:x,search:m,hash:o})}function Ah(){return ae.useContext(vh)!=null}function kl(){return Bn(Ah(),"useLocation() may be used only in the context of a component."),ae.useContext(vh).location}var lT="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function cT(n){ae.useContext(sa).static||ae.useLayoutEffect(n)}function s4(){let{isDataRoute:n}=ae.useContext(aa);return n?E4():a4()}function a4(){Bn(Ah(),"useNavigate() may be used only in the context of a component.");let n=ae.useContext(Wc),{basename:e,navigator:t}=ae.useContext(sa),{matches:r}=ae.useContext(aa),{pathname:o}=kl(),u=JSON.stringify(rT(r)),m=ae.useRef(!1);return cT(()=>{m.current=!0}),ae.useCallback((E,y={})=>{if(ta(m.current,lT),!m.current)return;if(typeof E=="number"){t.go(E);return}let T=sT(E,JSON.parse(u),o,y.relative==="path");n==null&&e!=="/"&&(T.pathname=T.pathname==="/"?e:ka([e,T.pathname])),(y.replace?t.replace:t.push)(T,y.state,y)},[e,t,u,o,n])}ae.createContext(null);function o4(){let{matches:n}=ae.useContext(aa),e=n[n.length-1];return e?e.params:{}}function Th(n,{relative:e}={}){let{matches:t}=ae.useContext(aa),{pathname:r}=kl(),o=JSON.stringify(rT(t));return ae.useMemo(()=>sT(n,JSON.parse(o),r,e==="path"),[n,o,r,e])}function l4(n,e){return uT(n,e)}function uT(n,e,t,r){var se;Bn(Ah(),"useRoutes() may be used only in the context of a component.");let{navigator:o,static:u}=ae.useContext(sa),{matches:m}=ae.useContext(aa),x=m[m.length-1],E=x?x.params:{},y=x?x.pathname:"/",T=x?x.pathnameBase:"/",b=x&&x.route;{let K=b&&b.path||"";hT(y,!b||K.endsWith("*")||K.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${y}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. - -Please change the parent to .`)}let R=kl(),P;if(e){let K=typeof e=="string"?Xc(e):e;Bn(T==="/"||((se=K.pathname)==null?void 0:se.startsWith(T)),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${T}" but pathname "${K.pathname}" was given in the \`location\` prop.`),P=K}else P=R;let j=P.pathname||"/",Y=j;if(T!=="/"){let K=T.replace(/^\//,"").split("/");Y="/"+j.replace(/^\//,"").split("/").slice(K.length).join("/")}let G=!u&&t&&t.matches&&t.matches.length>0?t.matches:tT(n,{pathname:Y});ta(b||G!=null,`No routes matched location "${P.pathname}${P.search}${P.hash}" `),ta(G==null||G[G.length-1].route.element!==void 0||G[G.length-1].route.Component!==void 0||G[G.length-1].route.lazy!==void 0,`Matched leaf route at location "${P.pathname}${P.search}${P.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let te=d4(G&&G.map(K=>Object.assign({},K,{params:Object.assign({},E,K.params),pathname:ka([T,o.encodeLocation?o.encodeLocation(K.pathname).pathname:K.pathname]),pathnameBase:K.pathnameBase==="/"?T:ka([T,o.encodeLocation?o.encodeLocation(K.pathnameBase).pathname:K.pathnameBase])})),m,t,r);return e&&te?ae.createElement(vh.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...P},navigationType:"POP"}},te):te}function c4(){let n=x4(),e=e4(n)?`${n.status} ${n.statusText}`:n instanceof Error?n.message:JSON.stringify(n),t=n instanceof Error?n.stack:null,r="rgba(200,200,200, 0.5)",o={padding:"0.5rem",backgroundColor:r},u={padding:"2px 4px",backgroundColor:r},m=null;return console.error("Error handled by React Router default ErrorBoundary:",n),m=ae.createElement(ae.Fragment,null,ae.createElement("p",null,"πŸ’Ώ Hey developer πŸ‘‹"),ae.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",ae.createElement("code",{style:u},"ErrorBoundary")," or"," ",ae.createElement("code",{style:u},"errorElement")," prop on your route.")),ae.createElement(ae.Fragment,null,ae.createElement("h2",null,"Unexpected Application Error!"),ae.createElement("h3",{style:{fontStyle:"italic"}},e),t?ae.createElement("pre",{style:o},t):null,m)}var u4=ae.createElement(c4,null),h4=class extends ae.Component{constructor(n){super(n),this.state={location:n.location,revalidation:n.revalidation,error:n.error}}static getDerivedStateFromError(n){return{error:n}}static getDerivedStateFromProps(n,e){return e.location!==n.location||e.revalidation!=="idle"&&n.revalidation==="idle"?{error:n.error,location:n.location,revalidation:n.revalidation}:{error:n.error!==void 0?n.error:e.error,location:e.location,revalidation:n.revalidation||e.revalidation}}componentDidCatch(n,e){console.error("React Router caught the following error during render",n,e)}render(){return this.state.error!==void 0?ae.createElement(aa.Provider,{value:this.props.routeContext},ae.createElement(Zm.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function f4({routeContext:n,match:e,children:t}){let r=ae.useContext(Wc);return r&&r.static&&r.staticContext&&(e.route.errorElement||e.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=e.route.id),ae.createElement(aa.Provider,{value:n},t)}function d4(n,e=[],t=null,r=null){if(n==null){if(!t)return null;if(t.errors)n=t.matches;else if(e.length===0&&!t.initialized&&t.matches.length>0)n=t.matches;else return null}let o=n,u=t==null?void 0:t.errors;if(u!=null){let E=o.findIndex(y=>y.route.id&&(u==null?void 0:u[y.route.id])!==void 0);Bn(E>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(u).join(",")}`),o=o.slice(0,Math.min(o.length,E+1))}let m=!1,x=-1;if(t)for(let E=0;E=0?o=o.slice(0,x+1):o=[o[0]];break}}}return o.reduceRight((E,y,T)=>{let b,R=!1,P=null,j=null;t&&(b=u&&y.route.id?u[y.route.id]:void 0,P=y.route.errorElement||u4,m&&(x<0&&T===0?(hT("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),R=!0,j=null):x===T&&(R=!0,j=y.route.hydrateFallbackElement||null)));let Y=e.concat(o.slice(0,T+1)),G=()=>{let te;return b?te=P:R?te=j:y.route.Component?te=ae.createElement(y.route.Component,null):y.route.element?te=y.route.element:te=E,ae.createElement(f4,{match:y,routeContext:{outlet:E,matches:Y,isDataRoute:t!=null},children:te})};return t&&(y.route.ErrorBoundary||y.route.errorElement||T===0)?ae.createElement(h4,{location:t.location,revalidation:t.revalidation,component:P,error:b,children:G(),routeContext:{outlet:null,matches:Y,isDataRoute:!0}}):G()},null)}function Jm(n){return`${n} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function g4(n){let e=ae.useContext(Wc);return Bn(e,Jm(n)),e}function m4(n){let e=ae.useContext(Jd);return Bn(e,Jm(n)),e}function p4(n){let e=ae.useContext(aa);return Bn(e,Jm(n)),e}function $m(n){let e=p4(n),t=e.matches[e.matches.length-1];return Bn(t.route.id,`${n} can only be used on routes that contain a unique "id"`),t.route.id}function y4(){return $m("useRouteId")}function x4(){var r;let n=ae.useContext(Zm),e=m4("useRouteError"),t=$m("useRouteError");return n!==void 0?n:(r=e.errors)==null?void 0:r[t]}function E4(){let{router:n}=g4("useNavigate"),e=$m("useNavigate"),t=ae.useRef(!1);return cT(()=>{t.current=!0}),ae.useCallback(async(o,u={})=>{ta(t.current,lT),t.current&&(typeof o=="number"?n.navigate(o):await n.navigate(o,{fromRouteId:e,...u}))},[n,e])}var XE={};function hT(n,e,t){!e&&!XE[n]&&(XE[n]=!0,ta(!1,t))}ae.memo(w4);function w4({routes:n,future:e,state:t}){return uT(n,void 0,t,e)}function Ec(n){Bn(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function v4({basename:n="/",children:e=null,location:t,navigationType:r="POP",navigator:o,static:u=!1}){Bn(!Ah(),"You cannot render a inside another . You should never have more than one in your app.");let m=n.replace(/^\/*/,"/"),x=ae.useMemo(()=>({basename:m,navigator:o,static:u,future:{}}),[m,o,u]);typeof t=="string"&&(t=Xc(t));let{pathname:E="/",search:y="",hash:T="",state:b=null,key:R="default"}=t,P=ae.useMemo(()=>{let j=Vo(E,m);return j==null?null:{location:{pathname:j,search:y,hash:T,state:b,key:R},navigationType:r}},[m,E,y,T,b,R,r]);return ta(P!=null,` is not able to match the URL "${E}${y}${T}" because it does not start with the basename, so the won't render anything.`),P==null?null:ae.createElement(sa.Provider,{value:x},ae.createElement(vh.Provider,{children:e,value:P}))}function A4({children:n,location:e}){return l4(Qg(n),e)}function Qg(n,e=[]){let t=[];return ae.Children.forEach(n,(r,o)=>{if(!ae.isValidElement(r))return;let u=[...e,o];if(r.type===ae.Fragment){t.push.apply(t,Qg(r.props.children,u));return}Bn(r.type===Ec,`[${typeof r.type=="string"?r.type:r.type.name}] is not a component. All component children of must be a or `),Bn(!r.props.index||!r.props.children,"An index route cannot have child routes.");let m={id:r.props.id||u.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,loader:r.props.loader,action:r.props.action,hydrateFallbackElement:r.props.hydrateFallbackElement,HydrateFallback:r.props.HydrateFallback,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.hasErrorBoundary===!0||r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(m.children=Qg(r.props.children,u)),t.push(m)}),t}var nd="get",id="application/x-www-form-urlencoded";function $d(n){return n!=null&&typeof n.tagName=="string"}function T4(n){return $d(n)&&n.tagName.toLowerCase()==="button"}function _4(n){return $d(n)&&n.tagName.toLowerCase()==="form"}function C4(n){return $d(n)&&n.tagName.toLowerCase()==="input"}function b4(n){return!!(n.metaKey||n.altKey||n.ctrlKey||n.shiftKey)}function S4(n,e){return n.button===0&&(!e||e==="_self")&&!b4(n)}var Gf=null;function I4(){if(Gf===null)try{new FormData(document.createElement("form"),0),Gf=!1}catch{Gf=!0}return Gf}var R4=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function wg(n){return n!=null&&!R4.has(n)?(ta(!1,`"${n}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${id}"`),null):n}function N4(n,e){let t,r,o,u,m;if(_4(n)){let x=n.getAttribute("action");r=x?Vo(x,e):null,t=n.getAttribute("method")||nd,o=wg(n.getAttribute("enctype"))||id,u=new FormData(n)}else if(T4(n)||C4(n)&&(n.type==="submit"||n.type==="image")){let x=n.form;if(x==null)throw new Error('Cannot submit a - - ) : ( - - )} - - - {/* Mobile Menu Button */} -
- -
- - - - - {/* Mobile Menu */} - - {isMenuOpen && ( - -
- setIsMenuOpen(false)} className="text-base font-medium text-slate-600">Verify Product - setIsMenuOpen(false)} className="text-base font-medium text-slate-600">Manufacturer - setIsMenuOpen(false)} className="text-base font-medium text-slate-600">Supply Chain - {user ? ( - - ) : ( - - )} -
-
- )} -
- - {/* Main Content */} -
- - } /> - } /> - } /> - } /> - } /> - -
- - {/* Footer */} - - - - ); -} diff --git a/apps/web/src/components/ErrorBoundary.tsx b/apps/web/src/components/ErrorBoundary.tsx deleted file mode 100644 index 65b1389..0000000 --- a/apps/web/src/components/ErrorBoundary.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React, { ErrorInfo, ReactNode } from 'react'; -import { AlertCircle, RefreshCcw } from 'lucide-react'; - -interface Props { - children: ReactNode; -} - -interface State { - hasError: boolean; - error: Error | null; -} - -export default class ErrorBoundary extends React.Component { - constructor(props: Props) { - super(props); - this.state = { - hasError: false, - error: null, - }; - } - - static getDerivedStateFromError(error: Error): State { - return { hasError: true, error }; - } - - componentDidCatch(error: Error, errorInfo: ErrorInfo) { - console.error('Uncaught error:', error, errorInfo); - } - - handleReset = () => { - this.setState({ hasError: false, error: null }); - window.location.reload(); - }; - - render() { - if (this.state.hasError) { - let errorMessage = "An unexpected error occurred."; - - try { - const parsed = JSON.parse(this.state.error?.message || ""); - if (parsed.error && parsed.operationType) { - errorMessage = `Firestore ${parsed.operationType} error: ${parsed.error}`; - if (parsed.error.includes("insufficient permissions")) { - errorMessage = "You don't have permission to perform this action. Please check your role."; - } - } - } catch (e) { - if (this.state.error?.message) { - errorMessage = this.state.error.message; - } - } - - return ( -
-
-
- -
-

Something went wrong

-

- {errorMessage} -

- -
-
- ); - } - - return this.props.children; - } -} - diff --git a/apps/web/src/firebase.ts b/apps/web/src/firebase.ts deleted file mode 100644 index 82471d0..0000000 --- a/apps/web/src/firebase.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { initializeApp } from 'firebase/app'; -import { getAuth } from 'firebase/auth'; -import { getFirestore, doc, getDocFromServer } from 'firebase/firestore'; - -import firebaseConfig from '../../../config/firebase-applet-config.json'; - -// Initialize Firebase SDK -const app = initializeApp(firebaseConfig); -export const db = getFirestore(app, firebaseConfig.firestoreDatabaseId); -export const auth = getAuth(app); - -export enum OperationType { - CREATE = 'create', - UPDATE = 'update', - DELETE = 'delete', - LIST = 'list', - GET = 'get', - WRITE = 'write', -} - -export interface FirestoreErrorInfo { - error: string; - operationType: OperationType; - path: string | null; - authInfo: { - userId: string | undefined; - email: string | null | undefined; - emailVerified: boolean | undefined; - isAnonymous: boolean | undefined; - tenantId: string | null | undefined; - providerInfo: { - providerId: string; - displayName: string | null; - email: string | null; - photoUrl: string | null; - }[]; - } -} - -export function handleFirestoreError(error: unknown, operationType: OperationType, path: string | null) { - const errInfo: FirestoreErrorInfo = { - error: error instanceof Error ? error.message : String(error), - authInfo: { - userId: auth.currentUser?.uid, - email: auth.currentUser?.email, - emailVerified: auth.currentUser?.emailVerified, - isAnonymous: auth.currentUser?.isAnonymous, - tenantId: auth.currentUser?.tenantId, - providerInfo: auth.currentUser?.providerData.map(provider => ({ - providerId: provider.providerId, - displayName: provider.displayName, - email: provider.email, - photoUrl: provider.photoURL - })) || [] - }, - operationType, - path - } - console.error('Firestore Error: ', JSON.stringify(errInfo)); - throw new Error(JSON.stringify(errInfo)); -} - -// CRITICAL CONSTRAINT: When the application initially boots, call getFromServer to test the connection to Firestore. -async function testConnection() { - try { - await getDocFromServer(doc(db, 'test', 'connection')); - } catch (error) { - if(error instanceof Error && error.message.includes('the client is offline')) { - console.error("Please check your Firebase configuration. "); - } - } -} -testConnection(); diff --git a/apps/web/src/index.css b/apps/web/src/index.css deleted file mode 100644 index 60dc660..0000000 --- a/apps/web/src/index.css +++ /dev/null @@ -1,21 +0,0 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap'); -@import "tailwindcss"; - -@theme { - --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; - --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace; -} - -@layer base { - body { - @apply bg-slate-50 text-slate-900 antialiased; - } -} - -.qr-scanner-container video { - @apply rounded-3xl overflow-hidden shadow-2xl border-4 border-white; -} - -.glass-card { - @apply bg-white/80 backdrop-blur-md border border-white/20 shadow-xl; -} diff --git a/apps/web/src/lib/utils.ts b/apps/web/src/lib/utils.ts deleted file mode 100644 index a9c53e2..0000000 --- a/apps/web/src/lib/utils.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { clsx, type ClassValue } from "clsx"; -import { twMerge } from "tailwind-merge"; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} - -export function formatAddress(address: string) { - if (!address) return ""; - return `${address.slice(0, 6)}...${address.slice(-4)}`; -} - -export function generateNFTId(gtin: string, serial: string) { - // Simple hash simulation for NFT ID - return `0x${Buffer.from(gtin + serial).toString('hex').slice(0, 40)}`; -} - -export function formatFirestoreTimestamp(value: unknown): string { - if ( - value != null && - typeof value === 'object' && - 'toDate' in value && - typeof (value as { toDate: () => Date }).toDate === 'function' - ) { - return (value as { toDate: () => Date }).toDate().toLocaleDateString(); - } - if (typeof value === 'number' && !Number.isNaN(value)) { - return new Date(value).toLocaleDateString(); - } - return 'β€”'; -} diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx deleted file mode 100644 index 15a2627..0000000 --- a/apps/web/src/main.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import {StrictMode} from 'react'; -import {createRoot} from 'react-dom/client'; -import App from './App.tsx'; -import ErrorBoundary from './components/ErrorBoundary.tsx'; -import './index.css'; - -createRoot(document.getElementById('root')!).render( - - - - - , -); diff --git a/apps/web/src/pages/HomePage.tsx b/apps/web/src/pages/HomePage.tsx deleted file mode 100644 index b175011..0000000 --- a/apps/web/src/pages/HomePage.tsx +++ /dev/null @@ -1,189 +0,0 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; -import { motion } from 'motion/react'; -import { Shield, QrCode, Factory, Truck, Store, ChevronRight, CheckCircle2, History as HistoryIcon } from 'lucide-react'; - -export default function HomePage() { - return ( -
- {/* Hero Section */} -
-
- -
- - - - - Next-Gen Anti-Counterfeit -
-

- Every Product Has a Digital Twin. -

-

- AuthenTick uses blockchain and ZK-privacy to track ownership and verify authenticity across the entire supply chain. -

-
- - - Verify Product - - - Manufacturer Portal - - -
-
- - -
-
-
-
- -
-
Blockchain ID
-
0x8f2...e3a1
-
-
- -
-
-
- -
-
-
Authenticity Verified
-
GS1 EPCIS Standard Compliant
-
-
- -
-
Current Owner
-
0x71C7656EC7ab88b098defB751B7401B5f6d8976F
-
-
-
-
- - {/* Floating elements */} -
-
- -
-
-
Minted by
-
Rolex SA (GLN 7612345)
-
-
-
-
-
- - {/* Roles Section */} -
-
-

A Unified Ecosystem

-

- AuthenTick connects every stakeholder in the supply chain through a shared, immutable ledger. -

-
- -
- {[ - { icon: Factory, title: 'Manufacturers', desc: 'Mint digital twins and generate secure QR codes.', color: 'bg-blue-50 text-blue-600' }, - { icon: Truck, title: 'Distributors', desc: 'Verify and record transit events via GS1 EPCIS.', color: 'bg-amber-50 text-amber-600' }, - { icon: Store, title: 'Retailers', desc: 'Securely receive and sell authenticated inventory.', color: 'bg-emerald-50 text-emerald-600' }, - { icon: Shield, title: 'Consumers', desc: 'Verify authenticity and claim legal ownership.', color: 'bg-indigo-50 text-indigo-600' }, - ].map((role, i) => ( -
-
- -
-

{role.title}

-

{role.desc}

-
- ))} -
-
- - {/* Features Section */} -
-
- -
-
-

Privacy-First
Ownership Tracking

-
-
-
- 01 -
-
-

ZK-SNARK Privacy

-

Prove you own a product without revealing your identity on the public blockchain.

-
-
-
-
- 02 -
-
-

GS1 EPCIS Compliance

-

Seamlessly integrate with existing ERP systems using global supply chain standards.

-
-
-
-
- 03 -
-
-

Polygon L2 Scalability

-

High-throughput, low-cost transactions capable of handling 2000+ TPS via batching.

-
-
-
-
- -
-
-
Transaction Ledger
-
Live
-
-
- {[1, 2, 3, 4].map((_, i) => ( -
-
-
- -
-
-
Ownership Transfer
-
2 mins ago
-
-
-
0x4a...9b2
-
- ))} -
-
-
-
-
- ); -} diff --git a/apps/web/src/pages/ManufacturerPage.tsx b/apps/web/src/pages/ManufacturerPage.tsx deleted file mode 100644 index daa4053..0000000 --- a/apps/web/src/pages/ManufacturerPage.tsx +++ /dev/null @@ -1,270 +0,0 @@ -import React, { useState } from 'react'; -import { motion, AnimatePresence } from 'motion/react'; -import { Factory, Plus, Package, Database, Shield, CheckCircle2, ChevronRight, QrCode as QrIcon } from 'lucide-react'; -import { QRCodeSVG } from 'qrcode.react'; -import { db, auth, handleFirestoreError, OperationType } from '../firebase'; -import { doc, setDoc, collection, serverTimestamp } from 'firebase/firestore'; - -export default function ManufacturerPage() { - const [isMinting, setIsMinting] = useState(false); - const [mintedProduct, setMintedProduct] = useState(null); - const [formData, setFormData] = useState({ - name: '', - gtin: '', - serial: '', - batchId: '', - }); - - const handleMint = async (e: React.FormEvent) => { - e.preventDefault(); - if (!auth.currentUser) { - alert("Please login first"); - return; - } - setIsMinting(true); - - try { - // Simulate blockchain minting delay - await new Promise(resolve => setTimeout(resolve, 2000)); - - const nftId = `0x${Math.random().toString(16).substr(2, 40)}`; - const productData = { - id: nftId, - name: formData.name, - gtin: formData.gtin, - serial: formData.serial, - batchId: formData.batchId, - manufacturer: auth.currentUser.uid, - createdAt: serverTimestamp(), - currentOwner: auth.currentUser.uid, - status: 'PRODUCTION', - }; - - // Save to Firestore - const productRef = doc(db, 'products', nftId); - await setDoc(productRef, productData); - - // Add initial EPCIS event - const eventId = Math.random().toString(36).substr(2, 9); - const eventRef = doc(collection(productRef, 'events'), eventId); - await setDoc(eventRef, { - id: eventId, - productId: nftId, - type: 'OBJECT_EVENT', - action: 'ADD', - bizStep: 'commissioning', - disposition: 'active', - readPoint: 'GLN-FACTORY-001', - eventTime: serverTimestamp(), - recordedTime: serverTimestamp(), - actor: auth.currentUser.uid - }); - - setMintedProduct({ - ...formData, - nftId, - mintedAt: new Date().toISOString(), - }); - } catch (err) { - handleFirestoreError(err, OperationType.WRITE, 'products'); - } finally { - setIsMinting(false); - } - }; - - return ( -
-
-
-

Manufacturer Portal

-

Mint digital twins and manage product lifecycles.

-
-
-
-
- Polygon Mainnet -
-
-
- -
- {/* Minting Form */} -
-
-
-
- -
-

Mint Digital Twin

-
- - -
-
- - setFormData({...formData, name: e.target.value})} - /> -
-
- - setFormData({...formData, gtin: e.target.value})} - /> -
-
- - setFormData({...formData, serial: e.target.value})} - /> -
-
- - setFormData({...formData, batchId: e.target.value})} - /> -
-
- - - -
-
- - {/* Stats & Recent */} -
-
-

Production Stats

-
-
-
1,284
-
Total Minted
-
-
-
99.9%
-
Authenticity
-
-
-
- -
-

Recent Mints

-
- {[1, 2, 3].map((_, i) => ( -
-
-
- -
-
-
Batch #8291
-
12 mins ago
-
-
- -
- ))} -
-
-
-
- - {/* Minting Result Modal */} - - {mintedProduct && ( -
- -
-
- -
-

Successfully Minted

-

Digital Twin is now live on Polygon Mainnet

-
- -
-
-
- -
Secure QR Code
-
- -
-
-
NFT Token ID
-
- {mintedProduct.nftId} -
-
-
-
-
GTIN
-
{mintedProduct.gtin}
-
-
-
Serial
-
{mintedProduct.serial}
-
-
-
-
- -
- - -
-
-
-
- )} -
-
- ); -} diff --git a/apps/web/src/pages/ProductDetailsPage.tsx b/apps/web/src/pages/ProductDetailsPage.tsx deleted file mode 100644 index a86988b..0000000 --- a/apps/web/src/pages/ProductDetailsPage.tsx +++ /dev/null @@ -1,186 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { useParams, Link } from 'react-router-dom'; -import { motion } from 'motion/react'; -import { Shield, History as HistoryIcon, User, MapPin, CheckCircle2, ChevronLeft, ExternalLink } from 'lucide-react'; -import { db, handleFirestoreError, OperationType } from '../firebase'; -import { formatFirestoreTimestamp } from '../lib/utils'; -import { doc, getDoc, collection, getDocs, query, orderBy } from 'firebase/firestore'; - -export default function ProductDetailsPage() { - const { id } = useParams(); - const [product, setProduct] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - const fetchProduct = async () => { - if (!id) return; - try { - const productRef = doc(db, 'products', id); - const productSnap = await getDoc(productRef); - - if (productSnap.exists()) { - const data = productSnap.data(); - - // Fetch history - const eventsRef = collection(productRef, 'events'); - const q = query(eventsRef, orderBy('eventTime', 'desc')); - const eventsSnap = await getDocs(q); - const history = eventsSnap.docs.map(doc => ({ - ...doc.data(), - step: doc.data().bizStep, - location: doc.data().readPoint, - time: doc.data().eventTime?.toDate().toLocaleDateString() || 'Unknown', - actor: doc.data().actor - })); - - setProduct({ - ...data, - history - }); - } - } catch (err) { - handleFirestoreError(err, OperationType.GET, 'products'); - } finally { - setLoading(false); - } - }; - - fetchProduct(); - }, [id]); - - if (loading) { - return ( -
-
-
- ); - } - - if (!product) { - return ( -
-

Product Not Found

- Return Home -
- ); - } - - return ( -
- - - Back to Home - - -
-
- {/* Header */} -
-
-
- - Verified Authentic -
-
ID: {id?.slice(0, 12)}...
-
- -

{product.name}

-

Digital Twin of physical asset registered on Polygon.

- -
-
-
Manufacturer
-
{product.manufacturer}
-
-
-
Minted On
-
- {formatFirestoreTimestamp(product.mintedAt ?? product.createdAt)} -
-
-
-
- - {/* Provenance */} -
-
-

Provenance History

-
- - View on PolygonScan -
-
- -
- {product.history.map((event, i) => ( -
-
-
-
-
{event.step}
-
- - {event.location} -
-
-
-
{event.time}
-
by {event.actor}
-
-
-
- ))} -
-
-
- - {/* Sidebar */} -
-
-
-
- -
-

Ownership

-
- -
-
-
Current Owner
-
- {product.currentOwner ?? product.owner ?? 'β€”'} -
-
- -
- Ownership is verified using ZK-SNARKs to ensure privacy while maintaining a complete audit trail. -
- - -
-
- -
-

GS1 Identifiers

-
-
- GTIN - {product.gtin} -
-
- Serial - {product.serial} -
-
- Standard - EPCIS v2.0 -
-
-
-
-
-
- ); -} diff --git a/apps/web/src/pages/SupplyChainPage.tsx b/apps/web/src/pages/SupplyChainPage.tsx deleted file mode 100644 index 77f692c..0000000 --- a/apps/web/src/pages/SupplyChainPage.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import React from 'react'; -import { motion } from 'motion/react'; -import { Truck, Package, MapPin, ArrowRight, History as HistoryIcon, Search, Filter, ChevronRight } from 'lucide-react'; - -export default function SupplyChainPage() { - const shipments = [ - { id: 'SHP-9281', from: 'Geneva Factory', to: 'Zurich Hub', status: 'In Transit', date: '2024-04-03', items: 120 }, - { id: 'SHP-8172', from: 'Zurich Hub', to: 'London Distribution', status: 'Delivered', date: '2024-04-01', items: 45 }, - { id: 'SHP-7261', from: 'London Distribution', to: 'Mayfair Retail', status: 'Processing', date: '2024-04-04', items: 12 }, - ]; - - return ( -
-
-
-

Supply Chain Dashboard

-

Track GS1 EPCIS events and inventory movement.

-
-
- - -
-
- - {/* Stats Grid */} -
- {[ - { label: 'Active Shipments', value: '24', icon: Truck, color: 'text-blue-600', bg: 'bg-blue-50' }, - { label: 'Items in Transit', value: '1,482', icon: Package, color: 'text-amber-600', bg: 'bg-amber-50' }, - { label: 'Verified Locations', value: '12', icon: MapPin, color: 'text-emerald-600', bg: 'bg-emerald-50' }, - ].map((stat, i) => ( -
-
- -
-
-
{stat.label}
-
{stat.value}
-
-
- ))} -
- - {/* Shipments Table */} -
-
-

Recent Shipments

-
- - -
-
- -
- - - - - - - - - - - - - {shipments.map((shipment, i) => ( - - - - - - - - - ))} - -
Shipment IDRouteStatusItemsDate
-
{shipment.id}
-
GS1-EPCIS-v2.0
-
-
- {shipment.from} - - {shipment.to} -
-
- - {shipment.status} - - {shipment.items} units{shipment.date} - -
-
- -
- -
-
-
- ); -} diff --git a/apps/web/src/pages/VerificationPage.tsx b/apps/web/src/pages/VerificationPage.tsx deleted file mode 100644 index aa74f82..0000000 --- a/apps/web/src/pages/VerificationPage.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { Html5QrcodeScanner } from 'html5-qrcode'; -import { motion } from 'motion/react'; -import { QrCode, Shield, CheckCircle2, AlertCircle, Loader2, History as HistoryIcon, ChevronRight } from 'lucide-react'; -import { Link } from 'react-router-dom'; -import { db, handleFirestoreError, OperationType } from '../firebase'; -import { doc, getDoc, collection, getDocs, query, orderBy } from 'firebase/firestore'; - -export default function VerificationPage() { - const [scanResult, setScanResult] = useState(null); - const [isVerifying, setIsVerifying] = useState(false); - const [productData, setProductData] = useState(null); - const [error, setError] = useState(null); - - useEffect(() => { - const scanner = new Html5QrcodeScanner( - "reader", - { fps: 10, qrbox: { width: 250, height: 250 } }, - /* verbose= */ false - ); - - scanner.render(onScanSuccess, onScanFailure); - - function onScanSuccess(decodedText: string) { - scanner.clear(); - handleVerify(decodedText); - } - - function onScanFailure(error: any) { - // console.warn(`Code scan error = ${error}`); - } - - return () => { - scanner.clear().catch(e => console.error("Failed to clear scanner", e)); - }; - }, []); - - const handleVerify = async (id: string) => { - setScanResult(id); - setIsVerifying(true); - setError(null); - - try { - const productRef = doc(db, 'products', id); - const productSnap = await getDoc(productRef); - - if (!productSnap.exists()) { - setError("Product not found in the blockchain registry."); - return; - } - - const data = productSnap.data(); - - // Fetch history - const eventsRef = collection(productRef, 'events'); - const q = query(eventsRef, orderBy('eventTime', 'desc')); - const eventsSnap = await getDocs(q); - const history = eventsSnap.docs.map((d) => { - const ev = d.data(); - return { - ...ev, - step: ev.bizStep, - location: ev.readPoint, - time: ev.eventTime?.toDate().toLocaleDateString() || 'Unknown', - }; - }); - - setProductData({ - ...data, - history - }); - } catch (err) { - handleFirestoreError(err, OperationType.GET, 'products'); - setError("Failed to verify product. Please try again."); - } finally { - setIsVerifying(false); - } - }; - - return ( -
-
-

Product Verification

-

Scan the secure QR code on your product to verify its digital twin on the blockchain.

-
- - {!scanResult && !isVerifying && ( - -
-
- - Align QR code within the frame -
-
- )} - - {isVerifying && ( -
-
-
- -
-
-

Verifying Digital Twin...

-

Checking Polygon blockchain and ZK-proofs

-
-
- )} - - {productData && ( - - {/* Status Card */} -
-
- -
-
-

Authentic Product

-

This product is verified and registered on the blockchain.

-
-
- - {/* Product Info */} -
-
-

Product Details

-
-
-
Name
-
{productData.name}
-
-
-
Manufacturer
-
{productData.manufacturer}
-
-
-
-
GTIN
-
{productData.gtin}
-
-
-
Serial
-
{productData.serial}
-
-
-
-
- -
-

Ownership

-
-
-
Current Owner (ZK-Verified)
-
- {productData.currentOwner ?? productData.owner ?? 'β€”'} -
-
- -
-
-
- - {/* History */} -
-
-

Provenance History

-
- - GS1 EPCIS Log -
-
-
- {productData.history.map((event: any, i: number) => ( -
-
-
-
-
{event.step}
-
{event.location}
-
-
{event.time}
-
-
- ))} -
-
- -
- -
-
- )} - - {error && ( -
- -

{error}

-
- )} -
- ); -} diff --git a/apps/web/src/types.ts b/apps/web/src/types.ts deleted file mode 100644 index 6b568c2..0000000 --- a/apps/web/src/types.ts +++ /dev/null @@ -1,40 +0,0 @@ -export enum UserRole { - MANUFACTURER = 'MANUFACTURER', - DISTRIBUTOR = 'DISTRIBUTOR', - RETAILER = 'RETAILER', - CUSTOMER = 'CUSTOMER', - GUEST = 'GUEST', -} - -export interface Product { - id: string; // NFT Token ID - gtin: string; - serial: string; - name: string; - manufacturer: string; - batchId: string; - createdAt: number; - currentOwner: string; - status: 'PRODUCTION' | 'IN_TRANSIT' | 'RETAIL' | 'SOLD'; - imageUrl?: string; -} - -export interface EPCISEvent { - id: string; - productId: string; - type: 'OBJECT_EVENT' | 'AGGREGATION_EVENT' | 'TRANSACTION_EVENT'; - action: 'ADD' | 'OBSERVE' | 'DELETE'; - bizStep: string; // e.g., 'shipping', 'receiving', 'retail_selling' - disposition: string; // e.g., 'in_transit', 'sellable_not_yet_sold' - readPoint: string; // Location GLN - eventTime: number; - recordedTime: number; -} - -export interface UserProfile { - uid: string; - email: string; - role: UserRole; - organizationName?: string; - gln?: string; // Global Location Number for GS1 -} diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts deleted file mode 100644 index da73ebd..0000000 --- a/apps/web/vite.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -import tailwindcss from '@tailwindcss/vite'; -import react from '@vitejs/plugin-react'; -import path from 'path'; -import { defineConfig, loadEnv } from 'vite'; - -const repoRoot = path.resolve(__dirname, '../..'); - -export default defineConfig(({ mode }) => { - const env = loadEnv(mode, repoRoot, ''); - return { - root: __dirname, - plugins: [react(), tailwindcss()], - define: { - 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY), - }, - resolve: { - alias: { - '@': path.resolve(__dirname, 'src'), - }, - }, - server: { - hmr: process.env.DISABLE_HMR !== 'true', - fs: { - allow: [repoRoot, __dirname], - }, - }, - }; -}); diff --git a/backend/.env.example b/backend/.env.example index 3f13d24..5c69563 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,11 +1,17 @@ NODE_ENV=development PORT=4000 -MONGODB_URI=mongodb://localhost:27017/authentick CORS_ORIGIN=http://localhost:5173 -# Ethers / chain (optional for read-only product checks) -RPC_URL=http://127.0.0.1:8545 -NFT_CONTRACT_ADDRESS= +# Leave empty to use the in-memory store (data is lost on restart). +MONGODB_URI= + +# Wallet sign-in for writes. Defaults to on in production, off otherwise. +# AUTH_REQUIRED=true +# Required in production when AUTH_REQUIRED is on. Use 32+ random characters. +# JWT_SECRET= +# Comma separated wallet addresses that get the ADMIN role and can grant others. +# ADMIN_ADDRESSES=0x... -# Registrar wallet for on-chain stage updates (optional) -REGISTRAR_PRIVATE_KEY= +# Optional: read ownership from the NFT contract instead of the database. +RPC_URL= +NFT_CONTRACT_ADDRESS= diff --git a/backend/README.md b/backend/README.md index 74cc6cc..c4a4977 100644 --- a/backend/README.md +++ b/backend/README.md @@ -1,24 +1,41 @@ # AuthenTick API -Express service implementing architecture pieces: - -- **GS1 EPCIS ingestion** β€” `POST /api/events`, `GET /api/events/product/:productId` -- **Metadata API** β€” `GET /api/metadata/:tokenId` -- **ZK stub** β€” `POST /api/verify/ownership` -- **Products** β€” `POST /api/products`, `GET /api/products/:tokenId` (Mongo + optional on-chain read via Ethers) - -## Env - -Copy `.env.example` to `.env`. +Express + TypeScript service. See [docs/ARCHITECTURE.md](../docs/ARCHITECTURE.md) for how it fits together. ## Run ```bash -npm run dev +cp .env.example .env +npm run dev # from this folder, or: npm run dev -w backend from the repo root ``` -Build & run production bundle: +Without `MONGODB_URI` the API uses an in-memory store. Production build: ```bash npm run build && npm start ``` + +## Endpoints + +| Method | Path | Notes | +|---|---|---| +| GET | `/api/health` | Store, auth and chain status | +| POST | `/api/products` | Mint. Manufacturer role when auth is on | +| GET | `/api/products/:tokenId`, `/api/metadata/:tokenId` | `{ product, events, onChain? }` | +| POST | `/api/events` | `{ tokenId, bizStep, readPoint, actor? }`. Lifecycle and role checked | +| GET | `/api/events/product/:tokenId` | Event history | +| POST | `/api/verify/challenge` | `{ tokenId }` β†’ `{ message }` to sign | +| POST | `/api/verify/ownership` | `{ tokenId, owner, message, signature }` β†’ `{ verified, reason? }` | +| GET | `/api/auth/challenge` | Message to sign in with | +| POST | `/api/auth/login` | `{ message, signature }` β†’ `{ token, address, role }` | +| GET | `/api/auth/me` | Current user | +| PUT | `/api/users/:address/role` | Admin only | + +Errors are `{ "error": "message" }` with 400 (validation), 401/403 (auth), 404, or 409 (duplicate or out-of-order event). + +## Test + +```bash +npm test # memory repository +MONGODB_TEST_URI=mongodb://localhost:27017/authentick_test npm test # also runs the MongoDB tests +``` diff --git a/backend/dist/app.d.ts b/backend/dist/app.d.ts deleted file mode 100644 index 1bbc6a5..0000000 --- a/backend/dist/app.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import type { Env } from "./config/env.js"; -export declare function createApp(env: Env): import("express-serve-static-core").Express; diff --git a/backend/dist/app.js b/backend/dist/app.js deleted file mode 100644 index 8e080e0..0000000 --- a/backend/dist/app.js +++ /dev/null @@ -1,32 +0,0 @@ -import express from "express"; -import cors from "cors"; -import helmet from "helmet"; -import morgan from "morgan"; -import { createBlockchainClients } from "./config/blockchain.js"; -import { healthRouter } from "./routes/health.js"; -import { productsRouter } from "./routes/products.js"; -import { eventsRouter } from "./routes/events.js"; -import { metadataRouter } from "./routes/metadata.js"; -import { verifyRouter } from "./routes/verify.js"; -import { errorHandler } from "./middleware/errorHandler.js"; -import { notFound } from "./middleware/notFound.js"; -export function createApp(env) { - const app = express(); - const { nft } = createBlockchainClients(env); - app.use(helmet()); - app.use(cors({ - origin: env.CORS_ORIGIN.split(",").map((s) => s.trim()), - credentials: true, - })); - app.use(express.json({ limit: "1mb" })); - app.use(morgan(env.NODE_ENV === "production" ? "combined" : "dev")); - app.use("/api", healthRouter); - app.use("/api/products", productsRouter(nft)); - app.use("/api/events", eventsRouter); - app.use("/api/metadata", metadataRouter); - app.use("/api/verify", verifyRouter); - app.use(notFound); - app.use(errorHandler); - return app; -} -//# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/backend/dist/app.js.map b/backend/dist/app.js.map deleted file mode 100644 index 71857b2..0000000 --- a/backend/dist/app.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,MAAM,UAAU,SAAS,CAAC,GAAQ;IAChC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,MAAM,EAAE,GAAG,EAAE,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAE7C,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAClB,GAAG,CAAC,GAAG,CACL,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACvD,WAAW,EAAE,IAAI;KAClB,CAAC,CACH,CAAC;IACF,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACxC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAEpE,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC9B,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9C,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IACrC,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAErC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClB,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAEtB,OAAO,GAAG,CAAC;AACb,CAAC"} \ No newline at end of file diff --git a/backend/dist/config/blockchain.d.ts b/backend/dist/config/blockchain.d.ts deleted file mode 100644 index 8a3f380..0000000 --- a/backend/dist/config/blockchain.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { JsonRpcProvider, Contract } from "ethers"; -import type { Env } from "./env.js"; -export declare function createBlockchainClients(env: Env): { - provider: null; - nft: Contract | null; -} | { - provider: JsonRpcProvider; - nft: Contract; -}; diff --git a/backend/dist/config/blockchain.js b/backend/dist/config/blockchain.js deleted file mode 100644 index a9b470f..0000000 --- a/backend/dist/config/blockchain.js +++ /dev/null @@ -1,14 +0,0 @@ -import { JsonRpcProvider, Contract } from "ethers"; -const minimalNftAbi = [ - "function getProduct(uint256 tokenId) view returns (tuple(string gtin, string serial, uint256 batchId, uint256 createdAt, bool isVerified))", - "function ownerOf(uint256 tokenId) view returns (address)", -]; -export function createBlockchainClients(env) { - if (!env.RPC_URL || !env.NFT_CONTRACT_ADDRESS) { - return { provider: null, nft: null }; - } - const provider = new JsonRpcProvider(env.RPC_URL); - const nft = new Contract(env.NFT_CONTRACT_ADDRESS, minimalNftAbi, provider); - return { provider, nft }; -} -//# sourceMappingURL=blockchain.js.map \ No newline at end of file diff --git a/backend/dist/config/blockchain.js.map b/backend/dist/config/blockchain.js.map deleted file mode 100644 index a6bd628..0000000 --- a/backend/dist/config/blockchain.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"blockchain.js","sourceRoot":"","sources":["../../src/config/blockchain.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGnD,MAAM,aAAa,GAAG;IACpB,4IAA4I;IAC5I,0DAA0D;CAClD,CAAC;AAEX,MAAM,UAAU,uBAAuB,CAAC,GAAQ;IAC9C,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QAC9C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,IAAuB,EAAE,CAAC;IAC1D,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,oBAAoB,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC5E,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAC3B,CAAC"} \ No newline at end of file diff --git a/backend/dist/config/db.d.ts b/backend/dist/config/db.d.ts deleted file mode 100644 index abb73e6..0000000 --- a/backend/dist/config/db.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function connectDb(uri: string): Promise; -export declare function disconnectDb(): Promise; diff --git a/backend/dist/config/db.js b/backend/dist/config/db.js deleted file mode 100644 index 1041dbc..0000000 --- a/backend/dist/config/db.js +++ /dev/null @@ -1,9 +0,0 @@ -import mongoose from "mongoose"; -export async function connectDb(uri) { - mongoose.set("strictQuery", true); - await mongoose.connect(uri); -} -export async function disconnectDb() { - await mongoose.disconnect(); -} -//# sourceMappingURL=db.js.map \ No newline at end of file diff --git a/backend/dist/config/db.js.map b/backend/dist/config/db.js.map deleted file mode 100644 index 8c13a96..0000000 --- a/backend/dist/config/db.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/config/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;IAClC,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;AAC9B,CAAC"} \ No newline at end of file diff --git a/backend/dist/config/env.d.ts b/backend/dist/config/env.d.ts deleted file mode 100644 index 8dff7d8..0000000 --- a/backend/dist/config/env.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { z } from "zod"; -import "dotenv/config"; -declare const schema: z.ZodObject<{ - NODE_ENV: z.ZodDefault>; - PORT: z.ZodDefault; - MONGODB_URI: z.ZodDefault; - CORS_ORIGIN: z.ZodDefault; - RPC_URL: z.ZodOptional; - NFT_CONTRACT_ADDRESS: z.ZodOptional; - REGISTRAR_PRIVATE_KEY: z.ZodOptional; -}, "strip", z.ZodTypeAny, { - NODE_ENV: "development" | "test" | "production"; - PORT: number; - MONGODB_URI: string; - CORS_ORIGIN: string; - RPC_URL?: string | undefined; - NFT_CONTRACT_ADDRESS?: string | undefined; - REGISTRAR_PRIVATE_KEY?: string | undefined; -}, { - NODE_ENV?: "development" | "test" | "production" | undefined; - PORT?: number | undefined; - MONGODB_URI?: string | undefined; - CORS_ORIGIN?: string | undefined; - RPC_URL?: string | undefined; - NFT_CONTRACT_ADDRESS?: string | undefined; - REGISTRAR_PRIVATE_KEY?: string | undefined; -}>; -export type Env = z.infer; -export declare const env: Env; -export {}; diff --git a/backend/dist/config/env.js b/backend/dist/config/env.js deleted file mode 100644 index 3ee86d7..0000000 --- a/backend/dist/config/env.js +++ /dev/null @@ -1,13 +0,0 @@ -import { z } from "zod"; -import "dotenv/config"; -const schema = z.object({ - NODE_ENV: z.enum(["development", "test", "production"]).default("development"), - PORT: z.coerce.number().default(4000), - MONGODB_URI: z.string().default("mongodb://localhost:27017/authentick"), - CORS_ORIGIN: z.string().default("http://localhost:5173"), - RPC_URL: z.string().optional(), - NFT_CONTRACT_ADDRESS: z.string().optional(), - REGISTRAR_PRIVATE_KEY: z.string().optional(), -}); -export const env = schema.parse(process.env); -//# sourceMappingURL=env.js.map \ No newline at end of file diff --git a/backend/dist/config/env.js.map b/backend/dist/config/env.js.map deleted file mode 100644 index 1d49a69..0000000 --- a/backend/dist/config/env.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,eAAe,CAAC;AAEvB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IACtB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;IAC9E,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,sCAAsC,CAAC;IACvE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC;IACxD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3C,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,GAAG,GAAQ,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/index.d.ts b/backend/dist/index.d.ts deleted file mode 100644 index cb0ff5c..0000000 --- a/backend/dist/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export {}; diff --git a/backend/dist/index.js b/backend/dist/index.js deleted file mode 100644 index d6cba35..0000000 --- a/backend/dist/index.js +++ /dev/null @@ -1,15 +0,0 @@ -import { env } from "./config/env.js"; -import { connectDb } from "./config/db.js"; -import { createApp } from "./app.js"; -async function main() { - await connectDb(env.MONGODB_URI); - const app = createApp(env); - app.listen(env.PORT, () => { - console.log(`AuthenTick API listening on port ${env.PORT}`); - }); -} -main().catch((err) => { - console.error(err); - process.exit(1); -}); -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/backend/dist/index.js.map b/backend/dist/index.js.map deleted file mode 100644 index 253a5e5..0000000 --- a/backend/dist/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC3B,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,oCAAoC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/middleware/errorHandler.d.ts b/backend/dist/middleware/errorHandler.d.ts deleted file mode 100644 index e092c74..0000000 --- a/backend/dist/middleware/errorHandler.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import type { NextFunction, Request, Response } from "express"; -export declare function errorHandler(err: unknown, _req: Request, res: Response, _next: NextFunction): Response>; diff --git a/backend/dist/middleware/errorHandler.js b/backend/dist/middleware/errorHandler.js deleted file mode 100644 index b8b1a54..0000000 --- a/backend/dist/middleware/errorHandler.js +++ /dev/null @@ -1,10 +0,0 @@ -import { ZodError } from "zod"; -export function errorHandler(err, _req, res, _next) { - if (err instanceof ZodError) { - return res.status(400).json({ error: "Validation failed", details: err.flatten() }); - } - const message = err instanceof Error ? err.message : "Internal error"; - const status = err.status ?? 500; - return res.status(status).json({ error: message }); -} -//# sourceMappingURL=errorHandler.js.map \ No newline at end of file diff --git a/backend/dist/middleware/errorHandler.js.map b/backend/dist/middleware/errorHandler.js.map deleted file mode 100644 index 6670f6d..0000000 --- a/backend/dist/middleware/errorHandler.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../src/middleware/errorHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAE/B,MAAM,UAAU,YAAY,CAAC,GAAY,EAAE,IAAa,EAAE,GAAa,EAAE,KAAmB;IAC1F,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;IACtE,MAAM,MAAM,GAAI,GAA2B,CAAC,MAAM,IAAI,GAAG,CAAC;IAC1D,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AACrD,CAAC"} \ No newline at end of file diff --git a/backend/dist/middleware/notFound.d.ts b/backend/dist/middleware/notFound.d.ts deleted file mode 100644 index 2e992ea..0000000 --- a/backend/dist/middleware/notFound.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import type { Request, Response } from "express"; -export declare function notFound(_req: Request, res: Response): void; diff --git a/backend/dist/middleware/notFound.js b/backend/dist/middleware/notFound.js deleted file mode 100644 index 52c78c0..0000000 --- a/backend/dist/middleware/notFound.js +++ /dev/null @@ -1,4 +0,0 @@ -export function notFound(_req, res) { - res.status(404).json({ error: "Not found" }); -} -//# sourceMappingURL=notFound.js.map \ No newline at end of file diff --git a/backend/dist/middleware/notFound.js.map b/backend/dist/middleware/notFound.js.map deleted file mode 100644 index 6e03fcf..0000000 --- a/backend/dist/middleware/notFound.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"notFound.js","sourceRoot":"","sources":["../../src/middleware/notFound.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,QAAQ,CAAC,IAAa,EAAE,GAAa;IACnD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;AAC/C,CAAC"} \ No newline at end of file diff --git a/backend/dist/models/EpcisEvent.d.ts b/backend/dist/models/EpcisEvent.d.ts deleted file mode 100644 index 9eee7da..0000000 --- a/backend/dist/models/EpcisEvent.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import mongoose from "mongoose"; -export type EpcisEventType = "OBJECT_EVENT" | "AGGREGATION_EVENT" | "TRANSACTION_EVENT"; -export type EpcisAction = "ADD" | "OBSERVE" | "DELETE"; -export interface EpcisEventDoc { - productId: string; - type: EpcisEventType; - action: EpcisAction; - bizStep: string; - disposition: string; - readPoint: string; - eventTime: Date; - recordedTime: Date; - actor: string; -} -export declare const EpcisEvent: mongoose.Model; diff --git a/backend/dist/models/EpcisEvent.js b/backend/dist/models/EpcisEvent.js deleted file mode 100644 index 1e2b91b..0000000 --- a/backend/dist/models/EpcisEvent.js +++ /dev/null @@ -1,19 +0,0 @@ -import mongoose, { Schema } from "mongoose"; -const epcisEventSchema = new Schema({ - productId: { type: String, required: true, index: true }, - type: { - type: String, - enum: ["OBJECT_EVENT", "AGGREGATION_EVENT", "TRANSACTION_EVENT"], - required: true, - }, - action: { type: String, enum: ["ADD", "OBSERVE", "DELETE"], required: true }, - bizStep: { type: String, required: true }, - disposition: { type: String, required: true }, - readPoint: { type: String, required: true }, - eventTime: { type: Date, required: true }, - recordedTime: { type: Date, required: true }, - actor: { type: String, required: true }, -}, { timestamps: false }); -epcisEventSchema.index({ productId: 1, eventTime: -1 }); -export const EpcisEvent = mongoose.models.EpcisEvent ?? mongoose.model("EpcisEvent", epcisEventSchema); -//# sourceMappingURL=EpcisEvent.js.map \ No newline at end of file diff --git a/backend/dist/models/EpcisEvent.js.map b/backend/dist/models/EpcisEvent.js.map deleted file mode 100644 index 1e552a0..0000000 --- a/backend/dist/models/EpcisEvent.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"EpcisEvent.js","sourceRoot":"","sources":["../../src/models/EpcisEvent.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAiB5C,MAAM,gBAAgB,GAAG,IAAI,MAAM,CACjC;IACE,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACxD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,CAAC,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,CAAC;QAChE,QAAQ,EAAE,IAAI;KACf;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC5E,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzC,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC7C,SAAS,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC3C,SAAS,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzC,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC5C,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;CACxC,EACD,EAAE,UAAU,EAAE,KAAK,EAAE,CACtB,CAAC;AAEF,gBAAgB,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAExD,MAAM,CAAC,MAAM,UAAU,GACrB,QAAQ,CAAC,MAAM,CAAC,UAAU,IAAI,QAAQ,CAAC,KAAK,CAAgB,YAAY,EAAE,gBAAgB,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/models/Product.d.ts b/backend/dist/models/Product.d.ts deleted file mode 100644 index 0a2ad51..0000000 --- a/backend/dist/models/Product.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import mongoose from "mongoose"; -export type ProductStatus = "PRODUCTION" | "IN_TRANSIT" | "RETAIL" | "SOLD"; -export interface ProductDoc { - tokenId: string; - gtin: string; - serial: string; - name: string; - manufacturerId: string; - batchId: string; - currentOwner?: string; - status: ProductStatus; - imageUrl?: string; - createdAt: Date; - updatedAt: Date; -} -export declare const Product: mongoose.Model; diff --git a/backend/dist/models/Product.js b/backend/dist/models/Product.js deleted file mode 100644 index c856653..0000000 --- a/backend/dist/models/Product.js +++ /dev/null @@ -1,19 +0,0 @@ -import mongoose, { Schema } from "mongoose"; -const productSchema = new Schema({ - tokenId: { type: String, required: true, unique: true, index: true }, - gtin: { type: String, required: true, index: true }, - serial: { type: String, required: true }, - name: { type: String, required: true }, - manufacturerId: { type: String, required: true, index: true }, - batchId: { type: String, required: true }, - currentOwner: { type: String }, - status: { - type: String, - enum: ["PRODUCTION", "IN_TRANSIT", "RETAIL", "SOLD"], - default: "PRODUCTION", - }, - imageUrl: { type: String }, -}, { timestamps: true }); -productSchema.index({ gtin: 1, serial: 1 }, { unique: true }); -export const Product = mongoose.models.Product ?? mongoose.model("Product", productSchema); -//# sourceMappingURL=Product.js.map \ No newline at end of file diff --git a/backend/dist/models/Product.js.map b/backend/dist/models/Product.js.map deleted file mode 100644 index fe7fa89..0000000 --- a/backend/dist/models/Product.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"Product.js","sourceRoot":"","sources":["../../src/models/Product.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAkB5C,MAAM,aAAa,GAAG,IAAI,MAAM,CAC9B;IACE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACpE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACnD,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACxC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACtC,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IAC7D,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzC,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IAC9B,MAAM,EAAE;QACN,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC;QACpD,OAAO,EAAE,YAAY;KACtB;IACD,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;CAC3B,EACD,EAAE,UAAU,EAAE,IAAI,EAAE,CACrB,CAAC;AAEF,aAAa,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAE9D,MAAM,CAAC,MAAM,OAAO,GAClB,QAAQ,CAAC,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAa,SAAS,EAAE,aAAa,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/models/User.d.ts b/backend/dist/models/User.d.ts deleted file mode 100644 index b9de524..0000000 --- a/backend/dist/models/User.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -import mongoose from "mongoose"; -export type UserRole = "MANUFACTURER" | "DISTRIBUTOR" | "RETAILER" | "CUSTOMER" | "ADMIN"; -export interface UserDoc { - walletAddress: string; - email?: string; - role: UserRole; - organizationName?: string; - gln?: string; - createdAt: Date; - updatedAt: Date; -} -export declare const User: mongoose.Model; diff --git a/backend/dist/models/User.js b/backend/dist/models/User.js deleted file mode 100644 index ed20e46..0000000 --- a/backend/dist/models/User.js +++ /dev/null @@ -1,14 +0,0 @@ -import mongoose, { Schema } from "mongoose"; -const userSchema = new Schema({ - walletAddress: { type: String, required: true, unique: true, index: true }, - email: { type: String }, - role: { - type: String, - enum: ["MANUFACTURER", "DISTRIBUTOR", "RETAILER", "CUSTOMER", "ADMIN"], - default: "CUSTOMER", - }, - organizationName: { type: String }, - gln: { type: String }, -}, { timestamps: true }); -export const User = mongoose.models.User ?? mongoose.model("User", userSchema); -//# sourceMappingURL=User.js.map \ No newline at end of file diff --git a/backend/dist/models/User.js.map b/backend/dist/models/User.js.map deleted file mode 100644 index 92c0e9d..0000000 --- a/backend/dist/models/User.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"User.js","sourceRoot":"","sources":["../../src/models/User.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAc5C,MAAM,UAAU,GAAG,IAAI,MAAM,CAC3B;IACE,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IAC1E,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IACvB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,CAAC,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC;QACtE,OAAO,EAAE,UAAU;KACpB;IACD,gBAAgB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;IAClC,GAAG,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;CACtB,EACD,EAAE,UAAU,EAAE,IAAI,EAAE,CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAU,MAAM,EAAE,UAAU,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/events.d.ts b/backend/dist/routes/events.d.ts deleted file mode 100644 index 49f665b..0000000 --- a/backend/dist/routes/events.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const eventsRouter: import("express-serve-static-core").Router; diff --git a/backend/dist/routes/events.js b/backend/dist/routes/events.js deleted file mode 100644 index 8b63611..0000000 --- a/backend/dist/routes/events.js +++ /dev/null @@ -1,22 +0,0 @@ -import { Router } from "express"; -import { ingestEpcisEvent, listEventsForProduct } from "../services/epcisIngestion.js"; -export const eventsRouter = Router(); -eventsRouter.post("/", async (req, res, next) => { - try { - const doc = await ingestEpcisEvent(req.body); - res.status(201).json(doc); - } - catch (e) { - next(e); - } -}); -eventsRouter.get("/product/:productId", async (req, res, next) => { - try { - const rows = await listEventsForProduct(req.params.productId); - res.json(rows); - } - catch (e) { - next(e); - } -}); -//# sourceMappingURL=events.js.map \ No newline at end of file diff --git a/backend/dist/routes/events.js.map b/backend/dist/routes/events.js.map deleted file mode 100644 index 3d8b78d..0000000 --- a/backend/dist/routes/events.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/routes/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAEvF,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC;AAErC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,YAAY,CAAC,GAAG,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC;AACH,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/health.d.ts b/backend/dist/routes/health.d.ts deleted file mode 100644 index 0a69c1f..0000000 --- a/backend/dist/routes/health.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const healthRouter: import("express-serve-static-core").Router; diff --git a/backend/dist/routes/health.js b/backend/dist/routes/health.js deleted file mode 100644 index 4241f37..0000000 --- a/backend/dist/routes/health.js +++ /dev/null @@ -1,6 +0,0 @@ -import { Router } from "express"; -export const healthRouter = Router(); -healthRouter.get("/health", (_req, res) => { - res.json({ status: "ok", service: "authentick-api", timestamp: new Date().toISOString() }); -}); -//# sourceMappingURL=health.js.map \ No newline at end of file diff --git a/backend/dist/routes/health.js.map b/backend/dist/routes/health.js.map deleted file mode 100644 index 31d2b18..0000000 --- a/backend/dist/routes/health.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/routes/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC;AAErC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IACxC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AAC7F,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/metadata.d.ts b/backend/dist/routes/metadata.d.ts deleted file mode 100644 index 29bd2c6..0000000 --- a/backend/dist/routes/metadata.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const metadataRouter: import("express-serve-static-core").Router; diff --git a/backend/dist/routes/metadata.js b/backend/dist/routes/metadata.js deleted file mode 100644 index 3d31920..0000000 --- a/backend/dist/routes/metadata.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Router } from "express"; -import { getProductMetadata } from "../services/metadataService.js"; -export const metadataRouter = Router(); -metadataRouter.get("/:tokenId", async (req, res, next) => { - try { - const data = await getProductMetadata(req.params.tokenId); - if (!data) { - return res.status(404).json({ error: "Metadata not found" }); - } - res.json(data); - } - catch (e) { - next(e); - } -}); -//# sourceMappingURL=metadata.js.map \ No newline at end of file diff --git a/backend/dist/routes/metadata.js.map b/backend/dist/routes/metadata.js.map deleted file mode 100644 index 2009964..0000000 --- a/backend/dist/routes/metadata.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/routes/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,EAAE,CAAC;AAEvC,cAAc,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACvD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC;AACH,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/products.d.ts b/backend/dist/routes/products.d.ts deleted file mode 100644 index ea57578..0000000 --- a/backend/dist/routes/products.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import type { Contract } from "ethers"; -export declare function productsRouter(nft: Contract | null): import("express-serve-static-core").Router; diff --git a/backend/dist/routes/products.js b/backend/dist/routes/products.js deleted file mode 100644 index 967c3ee..0000000 --- a/backend/dist/routes/products.js +++ /dev/null @@ -1,58 +0,0 @@ -import { Router } from "express"; -import { z } from "zod"; -import { Product } from "../models/Product.js"; -import { ingestEpcisEvent } from "../services/epcisIngestion.js"; -import { readOnChainProduct } from "../services/blockchainService.js"; -const createBody = z.object({ - tokenId: z.string().min(1), - gtin: z.string().length(14), - serial: z.string().min(1), - name: z.string().min(1).max(200), - manufacturerId: z.string().min(1), - batchId: z.string().min(1), - currentOwner: z.string().optional(), - status: z.enum(["PRODUCTION", "IN_TRANSIT", "RETAIL", "SOLD"]).optional(), - imageUrl: z.string().max(2048).optional(), -}); -export function productsRouter(nft) { - const r = Router(); - r.post("/", async (req, res, next) => { - try { - const body = createBody.parse(req.body); - const product = await Product.create({ - ...body, - status: body.status ?? "PRODUCTION", - }); - await ingestEpcisEvent({ - productId: body.tokenId, - type: "OBJECT_EVENT", - action: "ADD", - bizStep: "commissioning", - disposition: "active", - readPoint: "GLN-FACTORY", - eventTime: new Date(), - actor: body.manufacturerId, - }); - res.status(201).json(product); - } - catch (e) { - next(e); - } - }); - r.get("/:tokenId", async (req, res, next) => { - try { - const { tokenId } = req.params; - const doc = await Product.findOne({ tokenId }).lean().exec(); - const chain = await readOnChainProduct(nft, tokenId); - if (!doc && !chain) { - return res.status(404).json({ error: "Product not found" }); - } - res.json({ offChain: doc, onChain: chain }); - } - catch (e) { - next(e); - } - }); - return r; -} -//# sourceMappingURL=products.js.map \ No newline at end of file diff --git a/backend/dist/routes/products.js.map b/backend/dist/routes/products.js.map deleted file mode 100644 index 7a3d83d..0000000 --- a/backend/dist/routes/products.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/routes/products.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;IAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAChC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE;IACzE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc,CAAC,GAAoB;IACjD,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;IAEnB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACnC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;gBACnC,GAAG,IAAI;gBACP,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,YAAY;aACpC,CAAC,CAAC;YACH,MAAM,gBAAgB,CAAC;gBACrB,SAAS,EAAE,IAAI,CAAC,OAAO;gBACvB,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE,eAAe;gBACxB,WAAW,EAAE,QAAQ;gBACrB,SAAS,EAAE,aAAa;gBACxB,SAAS,EAAE,IAAI,IAAI,EAAE;gBACrB,KAAK,EAAE,IAAI,CAAC,cAAc;aAC3B,CAAC,CAAC;YACH,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,CAAC,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC1C,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;YAC/B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YAC7D,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;YACrD,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;gBACnB,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;YAC9D,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,CAAC,CAAC,CAAC;QACV,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,CAAC;AACX,CAAC"} \ No newline at end of file diff --git a/backend/dist/routes/verify.d.ts b/backend/dist/routes/verify.d.ts deleted file mode 100644 index c246f41..0000000 --- a/backend/dist/routes/verify.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const verifyRouter: import("express-serve-static-core").Router; diff --git a/backend/dist/routes/verify.js b/backend/dist/routes/verify.js deleted file mode 100644 index a452909..0000000 --- a/backend/dist/routes/verify.js +++ /dev/null @@ -1,13 +0,0 @@ -import { Router } from "express"; -import { verifyOwnershipProof } from "../services/zkProverStub.js"; -export const verifyRouter = Router(); -verifyRouter.post("/ownership", (req, res, next) => { - try { - const result = verifyOwnershipProof(req.body); - res.json(result); - } - catch (e) { - next(e); - } -}); -//# sourceMappingURL=verify.js.map \ No newline at end of file diff --git a/backend/dist/routes/verify.js.map b/backend/dist/routes/verify.js.map deleted file mode 100644 index e41adde..0000000 --- a/backend/dist/routes/verify.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/routes/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC;AAErC,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACjD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,CAAC,CAAC,CAAC;IACV,CAAC;AACH,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/backend/dist/services/blockchainService.d.ts b/backend/dist/services/blockchainService.d.ts deleted file mode 100644 index 41fc02f..0000000 --- a/backend/dist/services/blockchainService.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Contract } from "ethers"; -type OnChainProduct = { - gtin: string; - serial: string; - batchId: string; - createdAt: number; - isVerified: boolean; - owner: string; -}; -export declare function readOnChainProduct(nft: Contract | null, tokenId: string): Promise; -export {}; diff --git a/backend/dist/services/blockchainService.js b/backend/dist/services/blockchainService.js deleted file mode 100644 index 59f07a6..0000000 --- a/backend/dist/services/blockchainService.js +++ /dev/null @@ -1,22 +0,0 @@ -export async function readOnChainProduct(nft, tokenId) { - if (!nft) - return null; - try { - const id = BigInt(tokenId); - const raw = await nft.getProduct(id); - const meta = raw; - const owner = (await nft.ownerOf(id)); - return { - gtin: meta.gtin, - serial: meta.serial, - batchId: meta.batchId.toString(), - createdAt: Number(meta.createdAt), - isVerified: meta.isVerified, - owner, - }; - } - catch { - return null; - } -} -//# sourceMappingURL=blockchainService.js.map \ No newline at end of file diff --git a/backend/dist/services/blockchainService.js.map b/backend/dist/services/blockchainService.js.map deleted file mode 100644 index b7ce856..0000000 --- a/backend/dist/services/blockchainService.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"blockchainService.js","sourceRoot":"","sources":["../../src/services/blockchainService.ts"],"names":[],"mappings":"AAWA,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAoB,EAAE,OAAe;IAC5E,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,GAMZ,CAAC;QACF,MAAM,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAW,CAAC;QAChD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;YAChC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;YACjC,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,KAAK;SACN,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/backend/dist/services/epcisIngestion.d.ts b/backend/dist/services/epcisIngestion.d.ts deleted file mode 100644 index 207d380..0000000 --- a/backend/dist/services/epcisIngestion.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { z } from "zod"; -declare const ingestSchema: z.ZodObject<{ - productId: z.ZodString; - type: z.ZodEnum<["OBJECT_EVENT", "AGGREGATION_EVENT", "TRANSACTION_EVENT"]>; - action: z.ZodEnum<["ADD", "OBSERVE", "DELETE"]>; - bizStep: z.ZodString; - disposition: z.ZodString; - readPoint: z.ZodString; - eventTime: z.ZodDate; - actor: z.ZodString; -}, "strip", z.ZodTypeAny, { - type: "OBJECT_EVENT" | "AGGREGATION_EVENT" | "TRANSACTION_EVENT"; - productId: string; - action: "ADD" | "OBSERVE" | "DELETE"; - bizStep: string; - disposition: string; - readPoint: string; - eventTime: Date; - actor: string; -}, { - type: "OBJECT_EVENT" | "AGGREGATION_EVENT" | "TRANSACTION_EVENT"; - productId: string; - action: "ADD" | "OBSERVE" | "DELETE"; - bizStep: string; - disposition: string; - readPoint: string; - eventTime: Date; - actor: string; -}>; -export type IngestPayload = z.infer; -export declare function ingestEpcisEvent(payload: unknown): Promise; -export declare function listEventsForProduct(productId: string): Promise<(import("mongoose").FlattenMaps & Required<{ - _id: unknown; -}> & { - __v: number; -})[]>; -export {}; diff --git a/backend/dist/services/epcisIngestion.js b/backend/dist/services/epcisIngestion.js deleted file mode 100644 index 9496ab3..0000000 --- a/backend/dist/services/epcisIngestion.js +++ /dev/null @@ -1,25 +0,0 @@ -import { z } from "zod"; -import { EpcisEvent } from "../models/EpcisEvent.js"; -const ingestSchema = z.object({ - productId: z.string().min(1), - type: z.enum(["OBJECT_EVENT", "AGGREGATION_EVENT", "TRANSACTION_EVENT"]), - action: z.enum(["ADD", "OBSERVE", "DELETE"]), - bizStep: z.string().min(1), - disposition: z.string().min(1), - readPoint: z.string().min(1), - eventTime: z.coerce.date(), - actor: z.string().min(1), -}); -export async function ingestEpcisEvent(payload) { - const data = ingestSchema.parse(payload); - const recordedTime = new Date(); - const doc = await EpcisEvent.create({ - ...data, - recordedTime, - }); - return doc; -} -export async function listEventsForProduct(productId) { - return EpcisEvent.find({ productId }).sort({ eventTime: -1 }).lean().exec(); -} -//# sourceMappingURL=epcisIngestion.js.map \ No newline at end of file diff --git a/backend/dist/services/epcisIngestion.js.map b/backend/dist/services/epcisIngestion.js.map deleted file mode 100644 index 8ad7042..0000000 --- a/backend/dist/services/epcisIngestion.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"epcisIngestion.js","sourceRoot":"","sources":["../../src/services/epcisIngestion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,CAAC,CAAC;IACxE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACzB,CAAC,CAAC;AAIH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAgB;IACrD,MAAM,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC;QAClC,GAAG,IAAI;QACP,YAAY;KACb,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,SAAiB;IAC1D,OAAO,UAAU,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;AAC9E,CAAC"} \ No newline at end of file diff --git a/backend/dist/services/metadataService.d.ts b/backend/dist/services/metadataService.d.ts deleted file mode 100644 index 7eecc30..0000000 --- a/backend/dist/services/metadataService.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -export declare function getProductMetadata(tokenId: string): Promise<{ - product: (import("mongoose").FlattenMaps & Required<{ - _id: unknown; - }> & { - __v: number; - })[] | (import("mongoose").FlattenMaps & Required<{ - _id: unknown; - }> & { - __v: number; - }); - events: (import("mongoose").FlattenMaps & Required<{ - _id: unknown; - }> & { - __v: number; - })[]; -} | null>; diff --git a/backend/dist/services/metadataService.js b/backend/dist/services/metadataService.js deleted file mode 100644 index fce4979..0000000 --- a/backend/dist/services/metadataService.js +++ /dev/null @@ -1,10 +0,0 @@ -import { Product } from "../models/Product.js"; -import { listEventsForProduct } from "./epcisIngestion.js"; -export async function getProductMetadata(tokenId) { - const product = await Product.findOne({ tokenId }).lean().exec(); - if (!product) - return null; - const events = await listEventsForProduct(tokenId); - return { product, events }; -} -//# sourceMappingURL=metadataService.js.map \ No newline at end of file diff --git a/backend/dist/services/metadataService.js.map b/backend/dist/services/metadataService.js.map deleted file mode 100644 index 6ea8608..0000000 --- a/backend/dist/services/metadataService.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"metadataService.js","sourceRoot":"","sources":["../../src/services/metadataService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAe;IACtD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;IACjE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC"} \ No newline at end of file diff --git a/backend/dist/services/zkProverStub.d.ts b/backend/dist/services/zkProverStub.d.ts deleted file mode 100644 index 313a7c6..0000000 --- a/backend/dist/services/zkProverStub.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Placeholder for a real ZK verifier (e.g. snarkjs). Replace with cryptographic verification in production. - */ -export declare function verifyOwnershipProof(payload: unknown): { - verified: boolean; - message: string; - productId: string; - timestamp: number; -}; diff --git a/backend/dist/services/zkProverStub.js b/backend/dist/services/zkProverStub.js deleted file mode 100644 index da053ef..0000000 --- a/backend/dist/services/zkProverStub.js +++ /dev/null @@ -1,20 +0,0 @@ -import { z } from "zod"; -const verifySchema = z.object({ - productId: z.string().min(1), - proof: z.unknown(), - ownerAddress: z.string().min(1), -}); -/** - * Placeholder for a real ZK verifier (e.g. snarkjs). Replace with cryptographic verification in production. - */ -export function verifyOwnershipProof(payload) { - const { productId, proof, ownerAddress } = verifySchema.parse(payload); - const ok = proof != null && ownerAddress.length > 0; - return { - verified: ok, - message: ok ? "Ownership proof accepted (stub verifier)" : "Invalid proof", - productId, - timestamp: Date.now(), - }; -} -//# sourceMappingURL=zkProverStub.js.map \ No newline at end of file diff --git a/backend/dist/services/zkProverStub.js.map b/backend/dist/services/zkProverStub.js.map deleted file mode 100644 index 384f77f..0000000 --- a/backend/dist/services/zkProverStub.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"zkProverStub.js","sourceRoot":"","sources":["../../src/services/zkProverStub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;IAClB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAChC,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvE,MAAM,EAAE,GAAG,KAAK,IAAI,IAAI,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;IACpD,OAAO;QACL,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,eAAe;QAC1E,SAAS;QACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAC;AACJ,CAAC"} \ No newline at end of file diff --git a/backend/node_modules/dotenv/CHANGELOG.md b/backend/node_modules/dotenv/CHANGELOG.md deleted file mode 100644 index 8b80dd6..0000000 --- a/backend/node_modules/dotenv/CHANGELOG.md +++ /dev/null @@ -1,520 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. - -## [Unreleased](https://github.com/motdotla/dotenv/compare/v16.6.1...master) - -## [16.6.1](https://github.com/motdotla/dotenv/compare/v16.6.0...v16.6.1) (2025-06-27) - -### Changed - -- Default `quiet` to true – hiding the runtime log message ([#874](https://github.com/motdotla/dotenv/pull/874)) -- NOTICE: 17.0.0 will be released with quiet defaulting to false. Use `config({ quiet: true })` to suppress. -- And check out the new [dotenvx](https://github.com/dotenvx/dotenvx). As coding workflows evolve and agents increasingly handle secrets, encrypted .env files offer a much safer way to deploy both agents and code together with secure secrets. Simply switch `require('dotenv').config()` for `require('@dotenvx/dotenvx').config()`. - -## [16.6.0](https://github.com/motdotla/dotenv/compare/v16.5.0...v16.6.0) (2025-06-26) - -### Added - -- Default log helpful message `[dotenv@16.6.0] injecting env (1) from .env` ([#870](https://github.com/motdotla/dotenv/pull/870)) -- Use `{ quiet: true }` to suppress -- Aligns dotenv more closely with [dotenvx](https://github.com/dotenvx/dotenvx). - -## [16.5.0](https://github.com/motdotla/dotenv/compare/v16.4.7...v16.5.0) (2025-04-07) - -### Added - -- πŸŽ‰ Added new sponsor [Graphite](https://graphite.dev/?utm_source=github&utm_medium=repo&utm_campaign=dotenv) - *the AI developer productivity platform helping teams on GitHub ship higher quality software, faster*. - -> [!TIP] -> **[Become a sponsor](https://github.com/sponsors/motdotla)** -> -> The dotenvx README is viewed thousands of times DAILY on GitHub and NPM. -> Sponsoring dotenv is a great way to get in front of developers and give back to the developer community at the same time. - -### Changed - -- Remove `_log` method. Use `_debug` [#862](https://github.com/motdotla/dotenv/pull/862) - -## [16.4.7](https://github.com/motdotla/dotenv/compare/v16.4.6...v16.4.7) (2024-12-03) - -### Changed - -- Ignore `.tap` folder when publishing. (oops, sorry about that everyone. - @motdotla) [#848](https://github.com/motdotla/dotenv/pull/848) - -## [16.4.6](https://github.com/motdotla/dotenv/compare/v16.4.5...v16.4.6) (2024-12-02) - -### Changed - -- Clean up stale dev dependencies [#847](https://github.com/motdotla/dotenv/pull/847) -- Various README updates clarifying usage and alternative solutions using [dotenvx](https://github.com/dotenvx/dotenvx) - -## [16.4.5](https://github.com/motdotla/dotenv/compare/v16.4.4...v16.4.5) (2024-02-19) - -### Changed - -- 🐞 Fix recent regression when using `path` option. return to historical behavior: do not attempt to auto find `.env` if `path` set. (regression was introduced in `16.4.3`) [#814](https://github.com/motdotla/dotenv/pull/814) - -## [16.4.4](https://github.com/motdotla/dotenv/compare/v16.4.3...v16.4.4) (2024-02-13) - -### Changed - -- 🐞 Replaced chaining operator `?.` with old school `&&` (fixing node 12 failures) [#812](https://github.com/motdotla/dotenv/pull/812) - -## [16.4.3](https://github.com/motdotla/dotenv/compare/v16.4.2...v16.4.3) (2024-02-12) - -### Changed - -- Fixed processing of multiple files in `options.path` [#805](https://github.com/motdotla/dotenv/pull/805) - -## [16.4.2](https://github.com/motdotla/dotenv/compare/v16.4.1...v16.4.2) (2024-02-10) - -### Changed - -- Changed funding link in package.json to [`dotenvx.com`](https://dotenvx.com) - -## [16.4.1](https://github.com/motdotla/dotenv/compare/v16.4.0...v16.4.1) (2024-01-24) - -- Patch support for array as `path` option [#797](https://github.com/motdotla/dotenv/pull/797) - -## [16.4.0](https://github.com/motdotla/dotenv/compare/v16.3.2...v16.4.0) (2024-01-23) - -- Add `error.code` to error messages around `.env.vault` decryption handling [#795](https://github.com/motdotla/dotenv/pull/795) -- Add ability to find `.env.vault` file when filename(s) passed as an array [#784](https://github.com/motdotla/dotenv/pull/784) - -## [16.3.2](https://github.com/motdotla/dotenv/compare/v16.3.1...v16.3.2) (2024-01-18) - -### Added - -- Add debug message when no encoding set [#735](https://github.com/motdotla/dotenv/pull/735) - -### Changed - -- Fix output typing for `populate` [#792](https://github.com/motdotla/dotenv/pull/792) -- Use subarray instead of slice [#793](https://github.com/motdotla/dotenv/pull/793) - -## [16.3.1](https://github.com/motdotla/dotenv/compare/v16.3.0...v16.3.1) (2023-06-17) - -### Added - -- Add missing type definitions for `processEnv` and `DOTENV_KEY` options. [#756](https://github.com/motdotla/dotenv/pull/756) - -## [16.3.0](https://github.com/motdotla/dotenv/compare/v16.2.0...v16.3.0) (2023-06-16) - -### Added - -- Optionally pass `DOTENV_KEY` to options rather than relying on `process.env.DOTENV_KEY`. Defaults to `process.env.DOTENV_KEY` [#754](https://github.com/motdotla/dotenv/pull/754) - -## [16.2.0](https://github.com/motdotla/dotenv/compare/v16.1.4...v16.2.0) (2023-06-15) - -### Added - -- Optionally write to your own target object rather than `process.env`. Defaults to `process.env`. [#753](https://github.com/motdotla/dotenv/pull/753) -- Add import type URL to types file [#751](https://github.com/motdotla/dotenv/pull/751) - -## [16.1.4](https://github.com/motdotla/dotenv/compare/v16.1.3...v16.1.4) (2023-06-04) - -### Added - -- Added `.github/` to `.npmignore` [#747](https://github.com/motdotla/dotenv/pull/747) - -## [16.1.3](https://github.com/motdotla/dotenv/compare/v16.1.2...v16.1.3) (2023-05-31) - -### Removed - -- Removed `browser` keys for `path`, `os`, and `crypto` in package.json. These were set to false incorrectly as of 16.1. Instead, if using dotenv on the front-end make sure to include polyfills for `path`, `os`, and `crypto`. [node-polyfill-webpack-plugin](https://github.com/Richienb/node-polyfill-webpack-plugin) provides these. - -## [16.1.2](https://github.com/motdotla/dotenv/compare/v16.1.1...v16.1.2) (2023-05-31) - -### Changed - -- Exposed private function `_configDotenv` as `configDotenv`. [#744](https://github.com/motdotla/dotenv/pull/744) - -## [16.1.1](https://github.com/motdotla/dotenv/compare/v16.1.0...v16.1.1) (2023-05-30) - -### Added - -- Added type definition for `decrypt` function - -### Changed - -- Fixed `{crypto: false}` in `packageJson.browser` - -## [16.1.0](https://github.com/motdotla/dotenv/compare/v16.0.3...v16.1.0) (2023-05-30) - -### Added - -- Add `populate` convenience method [#733](https://github.com/motdotla/dotenv/pull/733) -- Accept URL as path option [#720](https://github.com/motdotla/dotenv/pull/720) -- Add dotenv to `npm fund` command -- Spanish language README [#698](https://github.com/motdotla/dotenv/pull/698) -- Add `.env.vault` support. πŸŽ‰ ([#730](https://github.com/motdotla/dotenv/pull/730)) - -ℹ️ `.env.vault` extends the `.env` file format standard with a localized encrypted vault file. Package it securely with your production code deploys. It's cloud agnostic so that you can deploy your secrets anywhere – without [risky third-party integrations](https://techcrunch.com/2023/01/05/circleci-breach/). [read more](https://github.com/motdotla/dotenv#-deploying) - -### Changed - -- Fixed "cannot resolve 'fs'" error on tools like Replit [#693](https://github.com/motdotla/dotenv/pull/693) - -## [16.0.3](https://github.com/motdotla/dotenv/compare/v16.0.2...v16.0.3) (2022-09-29) - -### Changed - -- Added library version to debug logs ([#682](https://github.com/motdotla/dotenv/pull/682)) - -## [16.0.2](https://github.com/motdotla/dotenv/compare/v16.0.1...v16.0.2) (2022-08-30) - -### Added - -- Export `env-options.js` and `cli-options.js` in package.json for use with downstream [dotenv-expand](https://github.com/motdotla/dotenv-expand) module - -## [16.0.1](https://github.com/motdotla/dotenv/compare/v16.0.0...v16.0.1) (2022-05-10) - -### Changed - -- Minor README clarifications -- Development ONLY: updated devDependencies as recommended for development only security risks ([#658](https://github.com/motdotla/dotenv/pull/658)) - -## [16.0.0](https://github.com/motdotla/dotenv/compare/v15.0.1...v16.0.0) (2022-02-02) - -### Added - -- _Breaking:_ Backtick support πŸŽ‰ ([#615](https://github.com/motdotla/dotenv/pull/615)) - -If you had values containing the backtick character, please quote those values with either single or double quotes. - -## [15.0.1](https://github.com/motdotla/dotenv/compare/v15.0.0...v15.0.1) (2022-02-02) - -### Changed - -- Properly parse empty single or double quoted values 🐞 ([#614](https://github.com/motdotla/dotenv/pull/614)) - -## [15.0.0](https://github.com/motdotla/dotenv/compare/v14.3.2...v15.0.0) (2022-01-31) - -`v15.0.0` is a major new release with some important breaking changes. - -### Added - -- _Breaking:_ Multiline parsing support (just works. no need for the flag.) - -### Changed - -- _Breaking:_ `#` marks the beginning of a comment (UNLESS the value is wrapped in quotes. Please update your `.env` files to wrap in quotes any values containing `#`. For example: `SECRET_HASH="something-with-a-#-hash"`). - -..Understandably, (as some teams have noted) this is tedious to do across the entire team. To make it less tedious, we recommend using [dotenv cli](https://github.com/dotenv-org/cli) going forward. It's an optional plugin that will keep your `.env` files in sync between machines, environments, or team members. - -### Removed - -- _Breaking:_ Remove multiline option (just works out of the box now. no need for the flag.) - -## [14.3.2](https://github.com/motdotla/dotenv/compare/v14.3.1...v14.3.2) (2022-01-25) - -### Changed - -- Preserve backwards compatibility on values containing `#` 🐞 ([#603](https://github.com/motdotla/dotenv/pull/603)) - -## [14.3.1](https://github.com/motdotla/dotenv/compare/v14.3.0...v14.3.1) (2022-01-25) - -### Changed - -- Preserve backwards compatibility on exports by re-introducing the prior in-place exports 🐞 ([#606](https://github.com/motdotla/dotenv/pull/606)) - -## [14.3.0](https://github.com/motdotla/dotenv/compare/v14.2.0...v14.3.0) (2022-01-24) - -### Added - -- Add `multiline` option πŸŽ‰ ([#486](https://github.com/motdotla/dotenv/pull/486)) - -## [14.2.0](https://github.com/motdotla/dotenv/compare/v14.1.1...v14.2.0) (2022-01-17) - -### Added - -- Add `dotenv_config_override` cli option -- Add `DOTENV_CONFIG_OVERRIDE` command line env option - -## [14.1.1](https://github.com/motdotla/dotenv/compare/v14.1.0...v14.1.1) (2022-01-17) - -### Added - -- Add React gotcha to FAQ on README - -## [14.1.0](https://github.com/motdotla/dotenv/compare/v14.0.1...v14.1.0) (2022-01-17) - -### Added - -- Add `override` option πŸŽ‰ ([#595](https://github.com/motdotla/dotenv/pull/595)) - -## [14.0.1](https://github.com/motdotla/dotenv/compare/v14.0.0...v14.0.1) (2022-01-16) - -### Added - -- Log error on failure to load `.env` file ([#594](https://github.com/motdotla/dotenv/pull/594)) - -## [14.0.0](https://github.com/motdotla/dotenv/compare/v13.0.1...v14.0.0) (2022-01-16) - -### Added - -- _Breaking:_ Support inline comments for the parser πŸŽ‰ ([#568](https://github.com/motdotla/dotenv/pull/568)) - -## [13.0.1](https://github.com/motdotla/dotenv/compare/v13.0.0...v13.0.1) (2022-01-16) - -### Changed - -* Hide comments and newlines from debug output ([#404](https://github.com/motdotla/dotenv/pull/404)) - -## [13.0.0](https://github.com/motdotla/dotenv/compare/v12.0.4...v13.0.0) (2022-01-16) - -### Added - -* _Breaking:_ Add type file for `config.js` ([#539](https://github.com/motdotla/dotenv/pull/539)) - -## [12.0.4](https://github.com/motdotla/dotenv/compare/v12.0.3...v12.0.4) (2022-01-16) - -### Changed - -* README updates -* Minor order adjustment to package json format - -## [12.0.3](https://github.com/motdotla/dotenv/compare/v12.0.2...v12.0.3) (2022-01-15) - -### Changed - -* Simplified jsdoc for consistency across editors - -## [12.0.2](https://github.com/motdotla/dotenv/compare/v12.0.1...v12.0.2) (2022-01-15) - -### Changed - -* Improve embedded jsdoc type documentation - -## [12.0.1](https://github.com/motdotla/dotenv/compare/v12.0.0...v12.0.1) (2022-01-15) - -### Changed - -* README updates and clarifications - -## [12.0.0](https://github.com/motdotla/dotenv/compare/v11.0.0...v12.0.0) (2022-01-15) - -### Removed - -- _Breaking:_ drop support for Flow static type checker ([#584](https://github.com/motdotla/dotenv/pull/584)) - -### Changed - -- Move types/index.d.ts to lib/main.d.ts ([#585](https://github.com/motdotla/dotenv/pull/585)) -- Typescript cleanup ([#587](https://github.com/motdotla/dotenv/pull/587)) -- Explicit typescript inclusion in package.json ([#566](https://github.com/motdotla/dotenv/pull/566)) - -## [11.0.0](https://github.com/motdotla/dotenv/compare/v10.0.0...v11.0.0) (2022-01-11) - -### Changed - -- _Breaking:_ drop support for Node v10 ([#558](https://github.com/motdotla/dotenv/pull/558)) -- Patch debug option ([#550](https://github.com/motdotla/dotenv/pull/550)) - -## [10.0.0](https://github.com/motdotla/dotenv/compare/v9.0.2...v10.0.0) (2021-05-20) - -### Added - -- Add generic support to parse function -- Allow for import "dotenv/config.js" -- Add support to resolve home directory in path via ~ - -## [9.0.2](https://github.com/motdotla/dotenv/compare/v9.0.1...v9.0.2) (2021-05-10) - -### Changed - -- Support windows newlines with debug mode - -## [9.0.1](https://github.com/motdotla/dotenv/compare/v9.0.0...v9.0.1) (2021-05-08) - -### Changed - -- Updates to README - -## [9.0.0](https://github.com/motdotla/dotenv/compare/v8.6.0...v9.0.0) (2021-05-05) - -### Changed - -- _Breaking:_ drop support for Node v8 - -## [8.6.0](https://github.com/motdotla/dotenv/compare/v8.5.1...v8.6.0) (2021-05-05) - -### Added - -- define package.json in exports - -## [8.5.1](https://github.com/motdotla/dotenv/compare/v8.5.0...v8.5.1) (2021-05-05) - -### Changed - -- updated dev dependencies via npm audit - -## [8.5.0](https://github.com/motdotla/dotenv/compare/v8.4.0...v8.5.0) (2021-05-05) - -### Added - -- allow for `import "dotenv/config"` - -## [8.4.0](https://github.com/motdotla/dotenv/compare/v8.3.0...v8.4.0) (2021-05-05) - -### Changed - -- point to exact types file to work with VS Code - -## [8.3.0](https://github.com/motdotla/dotenv/compare/v8.2.0...v8.3.0) (2021-05-05) - -### Changed - -- _Breaking:_ drop support for Node v8 (mistake to be released as minor bump. later bumped to 9.0.0. see above.) - -## [8.2.0](https://github.com/motdotla/dotenv/compare/v8.1.0...v8.2.0) (2019-10-16) - -### Added - -- TypeScript types - -## [8.1.0](https://github.com/motdotla/dotenv/compare/v8.0.0...v8.1.0) (2019-08-18) - -### Changed - -- _Breaking:_ drop support for Node v6 ([#392](https://github.com/motdotla/dotenv/issues/392)) - -# [8.0.0](https://github.com/motdotla/dotenv/compare/v7.0.0...v8.0.0) (2019-05-02) - -### Changed - -- _Breaking:_ drop support for Node v6 ([#302](https://github.com/motdotla/dotenv/issues/392)) - -## [7.0.0] - 2019-03-12 - -### Fixed - -- Fix removing unbalanced quotes ([#376](https://github.com/motdotla/dotenv/pull/376)) - -### Removed - -- Removed `load` alias for `config` for consistency throughout code and documentation. - -## [6.2.0] - 2018-12-03 - -### Added - -- Support preload configuration via environment variables ([#351](https://github.com/motdotla/dotenv/issues/351)) - -## [6.1.0] - 2018-10-08 - -### Added - -- `debug` option for `config` and `parse` methods will turn on logging - -## [6.0.0] - 2018-06-02 - -### Changed - -- _Breaking:_ drop support for Node v4 ([#304](https://github.com/motdotla/dotenv/pull/304)) - -## [5.0.0] - 2018-01-29 - -### Added - -- Testing against Node v8 and v9 -- Documentation on trim behavior of values -- Documentation on how to use with `import` - -### Changed - -- _Breaking_: default `path` is now `path.resolve(process.cwd(), '.env')` -- _Breaking_: does not write over keys already in `process.env` if the key has a falsy value -- using `const` and `let` instead of `var` - -### Removed - -- Testing against Node v7 - -## [4.0.0] - 2016-12-23 - -### Changed - -- Return Object with parsed content or error instead of false ([#165](https://github.com/motdotla/dotenv/pull/165)). - -### Removed - -- `verbose` option removed in favor of returning result. - -## [3.0.0] - 2016-12-20 - -### Added - -- `verbose` option will log any error messages. Off by default. -- parses email addresses correctly -- allow importing config method directly in ES6 - -### Changed - -- Suppress error messages by default ([#154](https://github.com/motdotla/dotenv/pull/154)) -- Ignoring more files for NPM to make package download smaller - -### Fixed - -- False positive test due to case-sensitive variable ([#124](https://github.com/motdotla/dotenv/pull/124)) - -### Removed - -- `silent` option removed in favor of `verbose` - -## [2.0.0] - 2016-01-20 - -### Added - -- CHANGELOG to ["make it easier for users and contributors to see precisely what notable changes have been made between each release"](http://keepachangelog.com/). Linked to from README -- LICENSE to be more explicit about what was defined in `package.json`. Linked to from README -- Testing nodejs v4 on travis-ci -- added examples of how to use dotenv in different ways -- return parsed object on success rather than boolean true - -### Changed - -- README has shorter description not referencing ruby gem since we don't have or want feature parity - -### Removed - -- Variable expansion and escaping so environment variables are encouraged to be fully orthogonal - -## [1.2.0] - 2015-06-20 - -### Added - -- Preload hook to require dotenv without including it in your code - -### Changed - -- clarified license to be "BSD-2-Clause" in `package.json` - -### Fixed - -- retain spaces in string vars - -## [1.1.0] - 2015-03-31 - -### Added - -- Silent option to silence `console.log` when `.env` missing - -## [1.0.0] - 2015-03-13 - -### Removed - -- support for multiple `.env` files. should always use one `.env` file for the current environment - -[7.0.0]: https://github.com/motdotla/dotenv/compare/v6.2.0...v7.0.0 -[6.2.0]: https://github.com/motdotla/dotenv/compare/v6.1.0...v6.2.0 -[6.1.0]: https://github.com/motdotla/dotenv/compare/v6.0.0...v6.1.0 -[6.0.0]: https://github.com/motdotla/dotenv/compare/v5.0.0...v6.0.0 -[5.0.0]: https://github.com/motdotla/dotenv/compare/v4.0.0...v5.0.0 -[4.0.0]: https://github.com/motdotla/dotenv/compare/v3.0.0...v4.0.0 -[3.0.0]: https://github.com/motdotla/dotenv/compare/v2.0.0...v3.0.0 -[2.0.0]: https://github.com/motdotla/dotenv/compare/v1.2.0...v2.0.0 -[1.2.0]: https://github.com/motdotla/dotenv/compare/v1.1.0...v1.2.0 -[1.1.0]: https://github.com/motdotla/dotenv/compare/v1.0.0...v1.1.0 -[1.0.0]: https://github.com/motdotla/dotenv/compare/v0.4.0...v1.0.0 diff --git a/backend/node_modules/dotenv/LICENSE b/backend/node_modules/dotenv/LICENSE deleted file mode 100644 index c430ad8..0000000 --- a/backend/node_modules/dotenv/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2015, Scott Motte -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/backend/node_modules/dotenv/README-es.md b/backend/node_modules/dotenv/README-es.md deleted file mode 100644 index 5fc934d..0000000 --- a/backend/node_modules/dotenv/README-es.md +++ /dev/null @@ -1,411 +0,0 @@ -
-πŸŽ‰ announcing dotenvx. run anywhere, multi-environment, encrypted envs. -
- -  - - - -# dotenv [![NPM version](https://img.shields.io/npm/v/dotenv.svg?style=flat-square)](https://www.npmjs.com/package/dotenv) - -dotenv - -Dotenv es un mΓ³dulo de dependencia cero que carga las variables de entorno desde un archivo `.env` en [`process.env`](https://nodejs.org/docs/latest/api/process.html#process_process_env). El almacenamiento de la configuraciΓ³n del entorno separado del cΓ³digo estΓ‘ basado en la metodologΓ­a [The Twelve-Factor App](http://12factor.net/config). - -[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) -[![LICENSE](https://img.shields.io/github/license/motdotla/dotenv.svg)](LICENSE) - -## InstalaciΓ³n - -```bash -# instalaciΓ³n local (recomendado) -npm install dotenv --save -``` - -O installaciΓ³n con yarn? `yarn add dotenv` - -## Uso - -Cree un archivo `.env` en la raΓ­z de su proyecto: - -```dosini -S3_BUCKET="YOURS3BUCKET" -SECRET_KEY="YOURSECRETKEYGOESHERE" -``` - -Tan prΓ³nto como sea posible en su aplicaciΓ³n, importe y configure dotenv: - -```javascript -require('dotenv').config() -console.log(process.env) // elimine esto despuΓ©s que haya confirmado que esta funcionando -``` - -.. o usa ES6? - -```javascript -import * as dotenv from 'dotenv' // vea en https://github.com/motdotla/dotenv#como-uso-dotenv-con-import -// REVISAR LINK DE REFERENCIA DE IMPORTACIΓ“N -dotenv.config() -import express from 'express' -``` - -Eso es todo. `process.env` ahora tiene las claves y los valores que definiste en tu archivo `.env`: - -```javascript -require('dotenv').config() - -... - -s3.getBucketCors({Bucket: process.env.S3_BUCKET}, function(err, data) {}) -``` - -### Valores multilΓ­nea - -Si necesita variables de varias lΓ­neas, por ejemplo, claves privadas, ahora se admiten en la versiΓ³n (`>= v15.0.0`) con saltos de lΓ­nea: - -```dosini -PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- -... -Kh9NV... -... ------END RSA PRIVATE KEY-----" -``` - -Alternativamente, puede usar comillas dobles y usar el carΓ‘cter `\n`: - -```dosini -PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END RSA PRIVATE KEY-----\n" -``` - -### Comentarios - -Los comentarios pueden ser agregados en tu archivo o en la misma lΓ­nea: - -```dosini -# This is a comment -SECRET_KEY=YOURSECRETKEYGOESHERE # comment -SECRET_HASH="something-with-a-#-hash" -``` - -Los comentarios comienzan donde existe un `#`, entonces, si su valor contiene un `#`, enciΓ©rrelo entre comillas. Este es un cambio importante desde la versiΓ³n `>= v15.0.0` en adelante. - -### AnΓ‘lisis - -El motor que analiza el contenido de su archivo que contiene variables de entorno estΓ‘ disponible para su uso. Este Acepta una Cadena o un BΓΊfer y devolverΓ‘ un Objeto con las claves y los valores analizados. - -```javascript -const dotenv = require('dotenv') -const buf = Buffer.from('BASICO=basico') -const config = dotenv.parse(buf) // devolverΓ‘ un objeto -console.log(typeof config, config) // objeto { BASICO : 'basico' } -``` - -### Precarga - -Puede usar el `--require` (`-r`) [opciΓ³n de lΓ­nea de comando](https://nodejs.org/api/cli.html#-r---require-module) para precargar dotenv. Al hacer esto, no necesita requerir ni cargar dotnev en el cΓ³digo de su aplicaciΓ³n. - -```bash -$ node -r dotenv/config tu_script.js -``` - -Las opciones de configuraciΓ³n a continuaciΓ³n se admiten como argumentos de lΓ­nea de comandos en el formato `dotenv_config_