From 3d1a8ba07e923c6093e5139dd03e8969cd41e82a Mon Sep 17 00:00:00 2001 From: mdares Date: Tue, 7 Apr 2026 08:54:41 -0600 Subject: [PATCH] first commit --- .env.example | 1 + .eslintrc.json | 3 + .gitignore | 11 + North_star.md | 164 + README.md | 40 + docs/DEPLOYMENT.md | 34 + docs/RUNBOOK.md | 33 + docs/pricing.md | 137 + next-env.d.ts | 6 + next.config.ts | 14 + package-lock.json | 8986 +++++++++++++++++ package.json | 46 + playwright.config.ts | 15 + postcss.config.mjs | 6 + .../20260406193800_init/migration.sql | 121 + .../migration.sql | 31 + .../migration.sql | 157 + .../migration.sql | 1 + prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 162 + prisma/seed.ts | 76 + scripts/start-local.ps1 | 11 + src/app/api/auth/change-pin/route.ts | 43 + src/app/api/auth/pin/route.ts | 24 + src/app/api/customers/route.ts | 52 + src/app/api/machines/[id]/route.ts | 32 + src/app/api/machines/bulk/route.ts | 27 + src/app/api/machines/route.ts | 35 + src/app/api/reports/export/route.ts | 24 + src/app/api/reports/summary/route.ts | 18 + src/app/api/reports/utilization/route.ts | 18 + src/app/api/settings/business/route.ts | 38 + src/app/api/settings/employees/[id]/route.ts | 33 + src/app/api/settings/employees/route.ts | 40 + src/app/api/settings/pricing/route.ts | 78 + src/app/api/settings/serial/route.ts | 44 + src/app/api/shifts/active/route.ts | 17 + src/app/api/shifts/close/route.ts | 22 + src/app/api/shifts/history/route.ts | 18 + src/app/api/shifts/movements/route.ts | 24 + src/app/api/shifts/open/route.ts | 21 + src/app/api/system/relay/route.ts | 38 + src/app/api/transactions/[id]/extend/route.ts | 31 + .../transactions/[id]/retry-relay/route.ts | 18 + src/app/api/transactions/[id]/void/route.ts | 28 + src/app/api/transactions/route.ts | 70 + src/app/globals.css | 21 + src/app/layout.tsx | 16 + src/app/page.tsx | 5 + src/components/POSDashboard.tsx | 401 + src/components/pos/LoginScreen.tsx | 31 + src/components/pos/PanelTab.tsx | 103 + src/components/pos/ReportsTab.tsx | 100 + src/components/pos/SettingsTab.tsx | 672 ++ src/components/pos/ShiftTab.tsx | 161 + src/components/pos/api.ts | 34 + src/components/pos/modals/ActivateModal.tsx | 461 + src/components/pos/modals/ChangePinModal.tsx | 103 + src/components/pos/modals/RunningModal.tsx | 78 + .../pos/modals/TicketPreviewModal.tsx | 228 + src/components/pos/types.ts | 136 + src/lib/config.ts | 21 + src/lib/db.ts | 16 + src/lib/format.ts | 36 + src/lib/http.ts | 15 + src/lib/logger.ts | 21 + src/lib/relay/mockRelayController.ts | 37 + src/lib/relay/protocol.ts | 13 + src/lib/relay/serialRelayController.ts | 91 + src/lib/relay/types.ts | 14 + src/lib/time.ts | 16 + src/server/api/dateRange.ts | 21 + src/server/domain/constants.ts | 34 + src/server/relay/relayManager.ts | 152 + src/server/services/activationService.ts | 307 + src/server/services/authService.ts | 34 + src/server/services/calculations.ts | 38 + src/server/services/customerService.ts | 153 + src/server/services/machineService.ts | 248 + src/server/services/recoveryService.ts | 58 + src/server/services/reportService.ts | 142 + src/server/services/shiftService.ts | 171 + src/server/services/timerService.ts | 150 + src/server/system/bootstrap.ts | 15 + tailwind.config.ts | 25 + tests/e2e/smoke.spec.ts | 7 + tests/unit/calculations.test.ts | 51 + tests/unit/dateRange.test.ts | 23 + tests/unit/time.test.ts | 23 + tsconfig.json | 44 + tsconfig.tsbuildinfo | 1 + vitest.config.ts | 14 + 92 files changed, 15392 insertions(+) create mode 100644 .env.example create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 North_star.md create mode 100644 README.md create mode 100644 docs/DEPLOYMENT.md create mode 100644 docs/RUNBOOK.md create mode 100644 docs/pricing.md create mode 100644 next-env.d.ts create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 playwright.config.ts create mode 100644 postcss.config.mjs create mode 100644 prisma/migrations/20260406193800_init/migration.sql create mode 100644 prisma/migrations/20260406205909_pricing_variables/migration.sql create mode 100644 prisma/migrations/20260406230249_customer_loyalty_addons/migration.sql create mode 100644 prisma/migrations/20260407001000_transaction_service_type/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 prisma/schema.prisma create mode 100644 prisma/seed.ts create mode 100644 scripts/start-local.ps1 create mode 100644 src/app/api/auth/change-pin/route.ts create mode 100644 src/app/api/auth/pin/route.ts create mode 100644 src/app/api/customers/route.ts create mode 100644 src/app/api/machines/[id]/route.ts create mode 100644 src/app/api/machines/bulk/route.ts create mode 100644 src/app/api/machines/route.ts create mode 100644 src/app/api/reports/export/route.ts create mode 100644 src/app/api/reports/summary/route.ts create mode 100644 src/app/api/reports/utilization/route.ts create mode 100644 src/app/api/settings/business/route.ts create mode 100644 src/app/api/settings/employees/[id]/route.ts create mode 100644 src/app/api/settings/employees/route.ts create mode 100644 src/app/api/settings/pricing/route.ts create mode 100644 src/app/api/settings/serial/route.ts create mode 100644 src/app/api/shifts/active/route.ts create mode 100644 src/app/api/shifts/close/route.ts create mode 100644 src/app/api/shifts/history/route.ts create mode 100644 src/app/api/shifts/movements/route.ts create mode 100644 src/app/api/shifts/open/route.ts create mode 100644 src/app/api/system/relay/route.ts create mode 100644 src/app/api/transactions/[id]/extend/route.ts create mode 100644 src/app/api/transactions/[id]/retry-relay/route.ts create mode 100644 src/app/api/transactions/[id]/void/route.ts create mode 100644 src/app/api/transactions/route.ts create mode 100644 src/app/globals.css create mode 100644 src/app/layout.tsx create mode 100644 src/app/page.tsx create mode 100644 src/components/POSDashboard.tsx create mode 100644 src/components/pos/LoginScreen.tsx create mode 100644 src/components/pos/PanelTab.tsx create mode 100644 src/components/pos/ReportsTab.tsx create mode 100644 src/components/pos/SettingsTab.tsx create mode 100644 src/components/pos/ShiftTab.tsx create mode 100644 src/components/pos/api.ts create mode 100644 src/components/pos/modals/ActivateModal.tsx create mode 100644 src/components/pos/modals/ChangePinModal.tsx create mode 100644 src/components/pos/modals/RunningModal.tsx create mode 100644 src/components/pos/modals/TicketPreviewModal.tsx create mode 100644 src/components/pos/types.ts create mode 100644 src/lib/config.ts create mode 100644 src/lib/db.ts create mode 100644 src/lib/format.ts create mode 100644 src/lib/http.ts create mode 100644 src/lib/logger.ts create mode 100644 src/lib/relay/mockRelayController.ts create mode 100644 src/lib/relay/protocol.ts create mode 100644 src/lib/relay/serialRelayController.ts create mode 100644 src/lib/relay/types.ts create mode 100644 src/lib/time.ts create mode 100644 src/server/api/dateRange.ts create mode 100644 src/server/domain/constants.ts create mode 100644 src/server/relay/relayManager.ts create mode 100644 src/server/services/activationService.ts create mode 100644 src/server/services/authService.ts create mode 100644 src/server/services/calculations.ts create mode 100644 src/server/services/customerService.ts create mode 100644 src/server/services/machineService.ts create mode 100644 src/server/services/recoveryService.ts create mode 100644 src/server/services/reportService.ts create mode 100644 src/server/services/shiftService.ts create mode 100644 src/server/services/timerService.ts create mode 100644 src/server/system/bootstrap.ts create mode 100644 tailwind.config.ts create mode 100644 tests/e2e/smoke.spec.ts create mode 100644 tests/unit/calculations.test.ts create mode 100644 tests/unit/dateRange.test.ts create mode 100644 tests/unit/time.test.ts create mode 100644 tsconfig.json create mode 100644 tsconfig.tsbuildinfo create mode 100644 vitest.config.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d91f958 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +DATABASE_URL="file:./dev.db" diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..3722418 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["next/core-web-vitals", "next/typescript"] +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d3cebe --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +.next +node_modules +.env +.env.local +coverage +dist +*.log +playwright-report +test-results +prisma/*.db +prisma/*.db-journal diff --git a/North_star.md b/North_star.md new file mode 100644 index 0000000..aaae3bc --- /dev/null +++ b/North_star.md @@ -0,0 +1,164 @@ +# La Burbuja — Laundry POS System Specification + +## Project North Star + +This is a **local-first POS system** for a single-location attended laundromat. A cashier operates the system from a touchscreen PC or tablet. The software controls power to residential washing machines and dryers via USB relay board (connected to a Raspberry Pi or mini PC). The system does NOT need internet to function — it runs on localhost. Keep it simple, reliable, and fast. + +**If a feature doesn't directly help the cashier process a transaction or help the owner see how the business is doing, it probably doesn't belong in v1.** + +--- + +## Tech Stack + +- **Frontend + Backend:** Next.js with TypeScript (App Router) +- **Database:** SQLite (via Prisma or Drizzle) — single file, no external DB server +- **Relay Communication:** Serial (USB) to relay board — simple write commands via `serialport` npm package +- **Runs on:** Raspberry Pi 4/5 or any mini PC running Node.js, serving on `localhost:3000` +- **UI:** Tailwind CSS, optimized for touch (large buttons, clear status colors) + +--- + +## Architecture Overview + +``` +[Touchscreen / Browser] + | + localhost:3000 + | + [Next.js App on Raspi / Mini PC] + | + [SQLite DB] [USB Serial → Relay Board] + | + [12 Contactors → Machine Power Lines] +``` + +There is ONE user interface. The cashier sees everything on one screen or minimal navigation. No customer-facing UI in v1. + +--- + +## Core Concepts + +### Machines +- Each machine has: `id`, `name` (e.g., "Lavadora 1", "Secadora 3"), `type` (washer | dryer), `status` (available | running | out_of_service), `relayChannel` (0-15), `defaultPrice`, `defaultDurationMinutes` +- Machines are configured once at setup, rarely changed +- Status is derived: if a timer is active → running. If not → available. Manual override for out_of_service. + +### Transactions +- Each transaction records: `id`, `machineId`, `amount`, `paymentMethod` (cash | card | transfer), `startedAt`, `expectedEndAt`, `employeeId`, `createdAt` +- A transaction = one machine activation. If a customer uses 1 washer + 1 dryer, that's 2 transactions. +- Transactions are immutable once created (no editing, only voiding with reason). + +### Employees / Shifts +- Simple employee list with PIN login (4-digit) +- Shift = period between cash register open and close (corte de caja) +- Each shift tracks: `employeeId`, `startTime`, `endTime`, `startingCash`, `cashDeposits`, `cashWithdrawals`, `expectedCash` (calculated), `actualCash` (entered at corte) + +--- + +## Screens + +### 1. Main Dashboard (primary screen — cashier lives here) +- Grid of all 12 machines as large, tappable cards +- Each card shows: machine name, type icon (washer/dryer), status color (green=available, blue=running with countdown timer, red=out of service), remaining time if running +- Tapping an available machine opens the **Activate Modal** +- Tapping a running machine shows transaction details + option to add time +- This screen should feel like a control panel, not a spreadsheet + +### 2. Activate Modal +- Shows: machine name, default price (editable), default duration (editable), payment method selector (cash / card / transfer) +- Big "ACTIVAR" button +- On confirm: creates transaction, sends relay command to power on the machine, starts countdown timer +- Timer runs in the app — when it hits zero, relay command powers off the machine +- **Keep this to 2 taps maximum: select machine → confirm activation** + +### 3. Cash Register / Corte de Caja +- Current shift summary: total sales, breakdown by payment method, number of transactions +- Button to register cash deposit or withdrawal (with reason field) +- "Cerrar Turno" button: prompts for actual cash count, calculates difference vs expected, prints/saves corte summary +- Historical cortes viewable by date + +### 4. Reports / Metrics +- Date range selector (today / this week / this month / custom) +- Key metrics: total revenue, transaction count, average ticket, revenue by machine, revenue by payment method +- Machine utilization: % of operating hours each machine was running +- Simple bar charts or summary cards — no complex dashboards +- Export to CSV option + +### 5. Settings +- Machine configuration (add/edit/disable machines, assign relay channels, set prices) +- Employee management (add/remove, reset PIN) +- Serial port configuration (select USB port for relay board) +- Business info (store name, for receipt headers) + +--- + +## Relay Board Communication + +- The relay board connects via USB and appears as a serial port (e.g., `/dev/ttyUSB0`) +- Communication is simple serial write commands — the exact protocol depends on the board chosen, but typically: + - Turn on relay N: send a specific byte sequence + - Turn off relay N: send a different byte sequence + - Some boards use ASCII commands like `relay on 3\n` +- **Abstract this behind a simple interface:** + ```typescript + interface RelayController { + connect(port: string, baudRate: number): Promise + turnOn(channel: number): Promise + turnOff(channel: number): Promise + getStatus(channel: number): Promise + disconnect(): Promise + } + ``` +- Include a **mock/simulator mode** for development and testing without hardware +- On application startup, restore state: check DB for any transactions with unexpired timers and re-activate those relays +- On unexpected shutdown/restart: same recovery logic — check timers, restore relay states +- **Timer expiration must trigger relay off even if nobody is looking at the screen.** Use a server-side interval/scheduler, not just frontend timers. + +--- + +## Critical Reliability Rules + +1. **The relay off-command on timer expiry is the most important operation in the system.** If the app crashes, the machine keeps running on the owner's dime. Use a server-side scheduler (e.g., `node-cron` or `setTimeout` with persistence) and verify relay state on restart. +2. **Database writes before relay commands.** Always save the transaction first, then activate the relay. If the relay command fails, the transaction exists and can be retried. Never the reverse. +3. **No internet dependency.** Everything works offline. The clock is the Raspi's system clock. +4. **Graceful serial port handling.** If the relay board disconnects, show a clear error on screen but don't crash the app. Allow reconnection without restart. + +--- + +## What This Project is NOT + +- NOT a customer-facing self-service kiosk (cashier operates everything) +- NOT a multi-location system (single store, single database) +- NOT a billing/invoicing system (no CFDI, no tax calculations in v1) +- NOT an inventory management system +- NOT connected to the internet for operation (metrics export is manual/CSV) +- NOT integrated with a bill acceptor in v1 (cash is handled by the cashier physically, software just records the payment method) + +--- + +## Language & Locale + +- UI text in **Spanish (Mexico)** +- Currency: **MXN**, formatted as `$XX.XX` +- Dates: `DD/MMM/YYYY` format +- Timezone: `America/Monterrey` (CST/CDT) + +--- + +## v2 Ideas (do NOT build these now, but don't make architecture decisions that prevent them) + +- Bill acceptor integration (USB serial, similar to relay board) +- Customer-facing status screen (second monitor showing machine availability) +- SMS/WhatsApp notification when cycle is done +- Remote monitoring dashboard (simple web view of today's metrics, requires internet) +- NFC loyalty card system +- Multi-store support +- Washer/dryer current sensing for actual cycle-complete detection instead of timer-only + +--- + +## Summary for the AI + +You are building a laundry POS that controls washing machines via relay. Think of it as a **timer-based power switch with a cash register attached.** The cashier taps a machine, confirms payment, and the machine gets power for X minutes. When time is up, power cuts. Everything is logged. At end of shift, cashier counts cash and closes out. Owner can see reports. + +Keep the codebase small. Keep the UI obvious. Keep the system reliable. That's it. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d252b6 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# La Burbuja POS + +Sistema local-first para lavanderia atendida, construido con Next.js + TypeScript + SQLite (Prisma), siguiendo [`North_star.md`](./North_star.md). + +## Stack +- Next.js (App Router) + TypeScript +- SQLite + Prisma +- Tailwind CSS +- Relay USB serial (`serialport`) + simulador + +## Quick Start +```powershell +npm install +Copy-Item .env.example .env +npm run prisma:migrate +npm run prisma:generate +npm run prisma:seed +npm run dev +``` + +## Comandos +- `npm run dev` desarrollo +- `npm run build` build produccion +- `npm run start` servidor produccion +- `npm run test` tests unitarios +- `npm run test:e2e` tests e2e + +## Cobertura funcional implementada +- Panel principal de maquinas (disponible/running/fuera de servicio) +- Activacion con orden critico: DB antes de relay +- Scheduler server-side para expiracion y apagado relay +- Recovery al reiniciar para timers/transacciones activas +- Agregar tiempo a transacciones activas +- Apertura/cierre de turno, movimientos de caja y calculo de esperado vs real +- Reportes con resumen, utilizacion y export CSV +- Configuracion basica de maquinas, empleados, serial y modo simulador + +## Operacion y despliegue +- Ver [`docs/DEPLOYMENT.md`](./docs/DEPLOYMENT.md) +- Ver [`docs/RUNBOOK.md`](./docs/RUNBOOK.md) diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 0000000..6cab86f --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,34 @@ +# Deployment Guide (Raspberry Pi / Mini PC) + +## 1. Requisitos +- Node.js 20+ (LTS recomendado). +- `npm` disponible. +- Puerto USB del relay identificado. +- Sistema operativo con zona horaria `America/Monterrey`. + +## 2. Instalacion +```powershell +npm install +Copy-Item .env.example .env +npm run prisma:migrate +npm run prisma:generate +npm run prisma:seed +``` + +## 3. Arranque en produccion +```powershell +npm run build +npm run start +``` + +## 4. Verificaciones de salida +- Abrir `http://localhost:3000`. +- Validar banner de relay conectado (mock o serial). +- Activar una maquina en mock mode y revisar countdown. +- Esperar expiracion y confirmar que transaccion pasa a `completed`. + +## 5. Reconexion serial +- Ir a `Configuracion`. +- Capturar puerto (`COMx` o `/dev/ttyUSB0`) y baud rate. +- Desactivar modo simulador. +- Ejecutar `Reconectar relay`. diff --git a/docs/RUNBOOK.md b/docs/RUNBOOK.md new file mode 100644 index 0000000..78ac3af --- /dev/null +++ b/docs/RUNBOOK.md @@ -0,0 +1,33 @@ +# Offline Operations Runbook + +## Inicio diario +1. Encender equipo local. +2. Ejecutar `npm run start` (o servicio equivalente). +3. Entrar al POS con PIN. +4. Abrir turno con efectivo inicial. + +## Operacion normal +1. Seleccionar maquina disponible. +2. Confirmar importe, tiempo y metodo de pago. +3. Verificar que el estado cambie a `running`. + +## Incidencias +### Relay desconectado +1. Revisar cable USB y alimentacion. +2. Ir a `Configuracion > Serial / Relay`. +3. Ejecutar `Reconectar relay`. +4. Si falla, activar `Modo simulador` temporalmente para seguir cobrando y registrar manualmente encendidos. + +### Reinicio inesperado +1. Reiniciar aplicacion. +2. Validar que timers activos fueron recuperados. +3. Confirmar que transacciones vencidas quedaron en `completed`. + +## Corte de caja +1. En `Corte`, registrar depositos/retiros con motivo. +2. Capturar efectivo contado al cierre. +3. Ejecutar `Cerrar Turno`. +4. Descargar CSV de reportes si se requiere respaldo manual. + +## Respaldo +- Respaldar archivo SQLite (`prisma/dev.db`) al cierre del dia en USB o carpeta segura. diff --git a/docs/pricing.md b/docs/pricing.md new file mode 100644 index 0000000..0797027 --- /dev/null +++ b/docs/pricing.md @@ -0,0 +1,137 @@ +# La Burbuja — Pricing System Prompt + +## Business context + +La Burbuja is a laundromat in Santa Catarina, Nuevo León (Monterrey metro). It operates three service lines: self-service, drop-off (encargo), and dry cleaning (tintorería). The POS system must handle all three with distinct pricing logic. + +--- + +## Machine inventory + +| Machine ID | Type | Service line | Notes | +|---|---|---|---| +| Lavadora 1–12 | LG WM22VV2S6R combo (washer + dryer stacked) | Self-service | Client-facing, coin/app activated | +| Lavadora 13–15 | LG WM22VV2S6R combo | Drop-off (encargo) | Staff-operated, back room | +| Lavadora 16 | XL combo (larger capacity) | Edredones / bulky items | Staff-operated, back room | + +--- + +## Service line 1: Self-service (autoservicio) + +**Pricing model:** Fixed price per cycle. Customer activates machine directly. + +| Service | Price (MXN) | Duration | Machine | +|---|---|---|---| +| Wash | $45 | 50 min | Lavadora 1–12 | +| Dry | $45 | 50 min | Lavadora 1–12 | + +- **Total per load:** $90 (wash + dry) +- **Payment methods:** Cash (coin changer), card, app (future) +- **Detergent/softener:** Included in price OR vending machine add-on (TBD) + +--- + +## Service line 2: Drop-off / encargo + +**Pricing model:** Per-kilogram, with minimum charge. Staff weighs intake, calculates price, activates machine at that price. + +| Parameter | Value | +|---|---| +| Price per kg | $33 MXN | +| Minimum charge | $120 MXN (~3.6 kg) | +| Service includes | Wash + dry + fold | +| Turnaround | 24 hours standard | + +### Activation logic + +1. Staff receives customer's bag +2. Weigh on scale → get weight in kg +3. Calculate: `price = max(weight × $33, $120)` +4. Enter calculated price in POS activation field +5. Activate encargo machine (Lavadora 13–15) at that price +6. Price recorded in POS = actual revenue for that order + +### Simulated weight (pre-scale) + +Until a physical scale is purchased/connected, the system can generate a simulated weight for testing purposes: + +- Random weight between 1–10 kg (uniform distribution) +- Display simulated weight to staff for confirmation +- Staff can override manually +- Flag all simulated-weight transactions for later reconciliation + +### Edredones / bulky items (Lavadora 16 — XL) + +**Pricing model:** Fixed price per item (premium, not per-kg). + +| Item | Price (MXN) | Notes | +|---|---|---| +| Edredón individual | $150 | Single/twin comforter | +| Edredón matrimonial | $180 | Queen size | +| Edredón king | $200 | King size | +| Cobija gruesa | $120 | Heavy blanket | +| Almohada (par) | $80 | Pillow pair | + +- These are drop-off only (staff-operated) +- Machine activated at the fixed item price +- If customer brings multiple items, sum the individual prices + +--- + +## Service line 3: Dry cleaning / tintorería + +**Pricing model:** Per-piece, fixed price by garment type. This is a future service line — prices are estimates based on Monterrey market research and will be confirmed before launch. Dry cleaning will likely be outsourced to a partner tintorería initially, with La Burbuja acting as a drop-off/pick-up point and adding a margin. + +### Estimated price list (MXN) + +| Category | Item | Estimated price | +|---|---|---| +| **Básico** | Camisa / blusa | $65 | +| | Pantalón | $65 | +| | Falda | $65 | +| | Suéter / sudadera | $75 | +| **Formal** | Saco | $80 | +| | Traje 2 piezas | $150 | +| | Traje 3 piezas | $200 | +| | Corbata | $55 | +| | Chaleco | $65 | +| **Vestidos** | Vestido sencillo | $100 | +| | Vestido de noche | $150 | +| | Vestido con aplicaciones | $200 | +| **Abrigos** | Chamarra ligera | $100 | +| | Chamarra gruesa / pluma | $180 | +| | Abrigo / gabardina | $130 | +| **Hogar** | Mantel (pieza) | $60 | +| | Juego de sábanas | $80 | +| | Cortinas (por metro) | $50 | +| **Especial** | Tenis / zapatos | $120 | +| | Vestido de novia (consultar) | $500+ | + +### Operational notes + +- Turnaround: 48–72 hours (dependent on outsource partner schedule) +- Minimum order: 3 pieces or $150 MXN +- Urgent service (24 hrs): +50% surcharge +- Items received with visible stains: customer notified, desmanchado quoted separately +- Items received on hangers with plastic cover (cubre polvo) + +--- + +## Pricing summary by service line + +| Service | Pricing logic | Who operates | Where | +|---|---|---|---| +| Self-service | Fixed per cycle ($45 wash / $45 dry) | Customer | Main floor, Lavadoras 1–12 | +| Drop-off (ropa) | Per-kg ($33/kg, min $120) | Staff | Back room, Lavadoras 13–15 | +| Drop-off (edredones) | Fixed per item ($120–$200) | Staff | Back room, Lavadora 16 XL | +| Dry cleaning | Fixed per piece ($55–$200+) | Staff (outsourced) | Reception at cashier | + +--- + +## Future considerations + +- **Loyalty / frequency discounts:** e.g., 10th wash free, or bulk kg discount for encargo regulars +- **Express encargo:** 4-hour turnaround at +30% premium +- **Detergent upsell:** premium detergent/softener options at $15–25 per dose via vending +- **Scale integration:** digital scale connected to POS for automatic weight → price calculation +- **Seasonal pricing:** edredón wash promotions in spring/fall (seasonal demand spikes) \ No newline at end of file diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..830fb59 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..7f80ca8 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,14 @@ +import type { NextConfig } from "next"; + +const useStandaloneOutput = process.env.NEXT_OUTPUT_STANDALONE === "1"; + +const nextConfig: NextConfig = { + ...(useStandaloneOutput ? { output: "standalone" } : {}), + experimental: { + serverActions: { + bodySizeLimit: "2mb" + } + } +}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7e2462b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8986 @@ +{ + "name": "lavanderia-checo-sistema", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "lavanderia-checo-sistema", + "version": "0.1.0", + "dependencies": { + "@prisma/client": "^6.19.3", + "clsx": "^2.1.1", + "date-fns": "^4.1.0", + "date-fns-tz": "^3.1.3", + "next": "^15.1.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "serialport": "^13.0.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@playwright/test": "^1.48.0", + "@types/node": "^22.10.2", + "@types/react": "^19.0.2", + "@types/react-dom": "^19.0.2", + "autoprefixer": "^10.4.20", + "eslint": "^8.57.1", + "eslint-config-next": "^15.5.14", + "postcss": "^8.4.49", + "prisma": "^6.19.3", + "tailwindcss": "^3.4.16", + "tsx": "^4.19.2", + "typescript": "^5.7.2", + "vitest": "^2.1.8" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.14.tgz", + "integrity": "sha512-aXeirLYuASxEgi4X4WhfXsShCFxWDfNn/8ZeC5YXAS2BB4A8FJi1kwwGL6nvMVboE7fZCzmJPNdMvVHc8JpaiA==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.14.tgz", + "integrity": "sha512-ogBjgsFrPPz19abP3VwcYSahbkUOMMvJjxCOYWYndw+PydeMuLuB4XrvNkNutFrTjC9St2KFULRdKID8Sd/CMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@next/eslint-plugin-next/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.14.tgz", + "integrity": "sha512-Y9K6SPzobnZvrRDPO2s0grgzC+Egf0CqfbdvYmQVaztV890zicw8Z8+4Vqw8oPck8r1TjUHxVh8299Cg4TrxXg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.14.tgz", + "integrity": "sha512-aNnkSMjSFRTOmkd7qoNI2/rETQm/vKD6c/Ac9BZGa9CtoOzy3c2njgz7LvebQJ8iPxdeTuGnAjagyis8a9ifBw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.14.tgz", + "integrity": "sha512-tjlpia+yStPRS//6sdmlVwuO1Rioern4u2onafa5n+h2hCS9MAvMXqpVbSrjgiEOoCs0nJy7oPOmWgtRRNSM5Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.14.tgz", + "integrity": "sha512-8B8cngBaLadl5lbDRdxGCP1Lef8ipD6KlxS3v0ElDAGil6lafrAM3B258p1KJOglInCVFUjk751IXMr2ixeQOQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.14.tgz", + "integrity": "sha512-bAS6tIAg8u4Gn3Nz7fCPpSoKAexEt2d5vn1mzokcqdqyov6ZJ6gu6GdF9l8ORFrBuRHgv3go/RfzYz5BkZ6YSQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.14.tgz", + "integrity": "sha512-mMxv/FcrT7Gfaq4tsR22l17oKWXZmH/lVqcvjX0kfp5I0lKodHYLICKPoX1KRnnE+ci6oIUdriUhuA3rBCDiSw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.14.tgz", + "integrity": "sha512-OTmiBlYThppnvnsqx0rBqjDRemlmIeZ8/o4zI7veaXoeO1PVHoyj2lfTfXTiiGjCyRDhA10y4h6ZvZvBiynr2g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.14.tgz", + "integrity": "sha512-+W7eFf3RS7m4G6tppVTOSyP9Y6FsJXfOuKzav1qKniiFm3KFByQfPEcouHdjlZmysl4zJGuGLQ/M9XyVeyeNEg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@playwright/test": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz", + "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "playwright": "1.59.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@prisma/client": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.19.3.tgz", + "integrity": "sha512-mKq3jQFhjvko5LTJFHGilsuQs+W+T3Gm451NzuTDGQxwCzwXHYnIu2zGkRoW+Exq3Rob7yp2MfzSrdIiZVhrBg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "prisma": "*", + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@prisma/config": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.19.3.tgz", + "integrity": "sha512-CBPT44BjlQxEt8kiMEauji2WHTDoVBOKl7UlewXmUgBPnr/oPRZC3psci5chJnYmH0ivEIog2OU9PGWoki3DLQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "c12": "3.1.0", + "deepmerge-ts": "7.1.5", + "effect": "3.21.0", + "empathic": "2.0.0" + } + }, + "node_modules/@prisma/debug": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.19.3.tgz", + "integrity": "sha512-ljkJ+SgpXNktLG0Q/n4JGYCkKf0f8oYLyjImS2I8e2q2WCfdRRtWER062ZV/ixaNP2M2VKlWXVJiGzZaUgbKZw==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.19.3.tgz", + "integrity": "sha512-RSYxtlYFl5pJ8ZePgMv0lZ9IzVCOdTPOegrs2qcbAEFrBI1G33h6wyC9kjQvo0DnYEhEVY0X4LsuFHXLKQk88g==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.3", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/fetch-engine": "6.19.3", + "@prisma/get-platform": "6.19.3" + } + }, + "node_modules/@prisma/engines-version": { + "version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7.tgz", + "integrity": "sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==", + "devOptional": true, + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.19.3.tgz", + "integrity": "sha512-tKtl/qco9Nt7LU5iKhpultD8O4vMCZcU2CHjNTnRrL1QvSUr5W/GcyFPjNL87GtRrwBc7ubXXD9xy4EvLvt8JA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.3", + "@prisma/engines-version": "7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7", + "@prisma/get-platform": "6.19.3" + } + }, + "node_modules/@prisma/get-platform": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.19.3.tgz", + "integrity": "sha512-xFj1VcJ1N3MKooOQAGO0W5tsd0W2QzIvW7DD7c/8H14Zmp4jseeWAITm+w2LLoLrlhoHdPPh0NMZ8mfL6puoHA==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "6.19.3" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.16.1.tgz", + "integrity": "sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@serialport/binding-mock": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz", + "integrity": "sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==", + "license": "MIT", + "dependencies": { + "@serialport/bindings-interface": "^1.2.1", + "debug": "^4.3.3" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@serialport/bindings-cpp": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/bindings-cpp/-/bindings-cpp-13.0.0.tgz", + "integrity": "sha512-r25o4Bk/vaO1LyUfY/ulR6hCg/aWiN6Wo2ljVlb4Pj5bqWGcSRC4Vse4a9AcapuAu/FeBzHCbKMvRQeCuKjzIQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@serialport/bindings-interface": "1.2.2", + "@serialport/parser-readline": "12.0.0", + "debug": "4.4.0", + "node-addon-api": "8.3.0", + "node-gyp-build": "4.8.4" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-delimiter": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-12.0.0.tgz", + "integrity": "sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-readline": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-12.0.0.tgz", + "integrity": "sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==", + "license": "MIT", + "dependencies": { + "@serialport/parser-delimiter": "12.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings-interface": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@serialport/bindings-interface/-/bindings-interface-1.2.2.tgz", + "integrity": "sha512-CJaUd5bLvtM9c5dmO9rPBHPXTa9R2UwpkJ0wdh9JCYcbrPWsKz+ErvR0hBLeo7NPeiFdjFO4sonRljiw4d2XiA==", + "license": "MIT", + "engines": { + "node": "^12.22 || ^14.13 || >=16" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-13.0.0.tgz", + "integrity": "sha512-32yvqeTAqJzAEtX5zCrN1Mej56GJ5h/cVFsCDPbF9S1ZSC9FWjOqNAgtByseHfFTSTs/4ZBQZZcZBpolt8sUng==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-13.0.0.tgz", + "integrity": "sha512-RErAe57g9gvnlieVYGIn1xymb1bzNXb2QtUQd14FpmbQQYlcrmuRnJwKa1BgTCujoCkhtaTtgHlbBWOxm8U2uA==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-13.0.0.tgz", + "integrity": "sha512-Qqyb0FX1avs3XabQqNaZSivyVbl/yl0jywImp7ePvfZKLwx7jBZjvL+Hawt9wIG6tfq6zbFM24vzCCK7REMUig==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-13.0.0.tgz", + "integrity": "sha512-a0w0WecTW7bD2YHWrpTz1uyiWA2fDNym0kjmPeNSwZ2XCP+JbirZt31l43m2ey6qXItTYVuQBthm75sPVeHnGA==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-packet-length": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-packet-length/-/parser-packet-length-13.0.0.tgz", + "integrity": "sha512-60ZDDIqYRi0Xs2SPZUo4Jr5LLIjtb+rvzPKMJCohrO6tAqSDponcNpcB1O4W21mKTxYjqInSz+eMrtk0LLfZIg==", + "license": "MIT", + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-13.0.0.tgz", + "integrity": "sha512-dov3zYoyf0dt1Sudd1q42VVYQ4WlliF0MYvAMA3MOyiU1IeG4hl0J6buBA2w4gl3DOCC05tGgLDN/3yIL81gsA==", + "license": "MIT", + "dependencies": { + "@serialport/parser-delimiter": "13.0.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-13.0.0.tgz", + "integrity": "sha512-JNUQA+y2Rfs4bU+cGYNqOPnNMAcayhhW+XJZihSLQXOHcZsFnOa2F9YtMg9VXRWIcnHldHYtisp62Etjlw24bw==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-13.0.0.tgz", + "integrity": "sha512-m7HpIf56G5XcuDdA3DB34Z0pJiwxNRakThEHjSa4mG05OnWYv0IG8l2oUyYfuGMowQWaVnQ+8r+brlPxGVH+eA==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-slip-encoder": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-slip-encoder/-/parser-slip-encoder-13.0.0.tgz", + "integrity": "sha512-fUHZEExm6izJ7rg0A1yjXwu4sOzeBkPAjDZPfb+XQoqgtKAk+s+HfICiYn7N2QU9gyaeCO8VKgWwi+b/DowYOg==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-spacepacket": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/parser-spacepacket/-/parser-spacepacket-13.0.0.tgz", + "integrity": "sha512-DoXJ3mFYmyD8X/8931agJvrBPxqTaYDsPoly9/cwQSeh/q4EjQND9ySXBxpWz5WcpyCU4jOuusqCSAPsbB30Eg==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-13.0.0.tgz", + "integrity": "sha512-F7xLJKsjGo2WuEWMSEO1SimRcOA+WtWICsY13r0ahx8s2SecPQH06338g28OT7cW7uRXI7oEQAk62qh5gHJW3g==", + "license": "MIT", + "dependencies": { + "@serialport/bindings-interface": "1.2.2", + "debug": "4.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.19.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", + "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.0.tgz", + "integrity": "sha512-RLkVSiNuUP1C2ROIWfqX+YcUfLaSnxGE/8M+Y57lopVwg9VTYYfhuz15Yf1IzCKgZj6/rIbYTmJCUSqr76r0Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.58.0", + "@typescript-eslint/type-utils": "8.58.0", + "@typescript-eslint/utils": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.58.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.0.tgz", + "integrity": "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.58.0", + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/typescript-estree": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.0.tgz", + "integrity": "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.58.0", + "@typescript-eslint/types": "^8.58.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.0.tgz", + "integrity": "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.0.tgz", + "integrity": "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.0.tgz", + "integrity": "sha512-aGsCQImkDIqMyx1u4PrVlbi/krmDsQUs4zAcCV6M7yPcPev+RqVlndsJy9kJ8TLihW9TZ0kbDAzctpLn5o+lOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/typescript-estree": "8.58.0", + "@typescript-eslint/utils": "8.58.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.0.tgz", + "integrity": "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.0.tgz", + "integrity": "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.58.0", + "@typescript-eslint/tsconfig-utils": "8.58.0", + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/visitor-keys": "8.58.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.0.tgz", + "integrity": "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.58.0", + "@typescript-eslint/types": "8.58.0", + "@typescript-eslint/typescript-estree": "8.58.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.58.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.0.tgz", + "integrity": "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.58.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@vitest/expect": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", + "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", + "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", + "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.9", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", + "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "magic-string": "^0.30.12", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", + "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", + "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.27", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1", + "caniuse-lite": "^1.0.30001774", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.2.tgz", + "integrity": "sha512-byD6KPdvo72y/wj2T/4zGEvvlis+PsZsn/yPS3pEO+sFpcrqRpX/TJCxvVaEsNeMrfQbCr7w163YqoD9IYwHXw==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.16", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.16.tgz", + "integrity": "sha512-Lyf3aK28zpsD1yQMiiHD4RvVb6UdMoo8xzG2XzFIfR9luPzOpcBlAsT/qfB1XWS1bxWT+UtE4WmQgsp297FYOA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/c12": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", + "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^16.6.1", + "exsolve": "^1.0.7", + "giget": "^2.0.0", + "jiti": "^2.4.2", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^1.0.0", + "pkg-types": "^2.2.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "^0.3.5" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/c12/node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/c12/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/c12/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001786", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001786.tgz", + "integrity": "sha512-4oxTZEvqmLLrERwxO76yfKM7acZo310U+v4kqexI2TL1DkkUEMT8UijrxxcnVdxR3qkVf5awGRX+4Z6aPHVKrA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/date-fns-tz": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-3.2.0.tgz", + "integrity": "sha512-sg8HqoTEulcbbbVXeg84u5UnlsQa8GS5QXMqjjYIhS4abEVVKIUwe0/l/UhrZdKaL/W5eWZNlbTeEIiOXTcsBQ==", + "license": "MIT", + "peerDependencies": { + "date-fns": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge-ts": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", + "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.6.tgz", + "integrity": "sha512-f8mefEW4WIVg4LckePx3mALjQSPQgFlg9U8yaPdlsbdYcHQyj9n2zL2LJEA52smeYxOvmd/nB7TpMtHGMTHcug==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/effect": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.21.0.tgz", + "integrity": "sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "fast-check": "^3.23.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.331", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.331.tgz", + "integrity": "sha512-IbxXrsTlD3hRodkLnbxAPP4OuJYdWCeM3IOdT+CpcMoIwIoDfCmRpEtSPfwBXxVkg9xmBeY7Lz2Eo2TDn/HC3Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/empathic": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", + "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.1.tgz", + "integrity": "sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.1", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.14.tgz", + "integrity": "sha512-lmJ5F8ZgOYogq0qtH4L5SpxuASY2SPdOzqUprN2/56+P3GPsIpXaUWIJC66kYIH+yZdsM4nkHE5MIBP6s1NiBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "15.5.14", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.0.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "2.0.0-next.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", + "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz", + "integrity": "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/exsolve": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fast-check": { + "version": "3.23.2", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", + "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^6.1.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/giget/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "15.5.14", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.14.tgz", + "integrity": "sha512-M6S+4JyRjmKic2Ssm7jHUPkE6YUJ6lv4507jprsSZLulubz0ihO2E+S4zmQK3JZ2ov81JrugukKU4Tz0ivgqqQ==", + "license": "MIT", + "dependencies": { + "@next/env": "15.5.14", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.5.14", + "@next/swc-darwin-x64": "15.5.14", + "@next/swc-linux-arm64-gnu": "15.5.14", + "@next/swc-linux-arm64-musl": "15.5.14", + "@next/swc-linux-x64-gnu": "15.5.14", + "@next/swc-linux-x64-musl": "15.5.14", + "@next/swc-win32-arm64-msvc": "15.5.14", + "@next/swc-win32-x64-msvc": "15.5.14", + "sharp": "^0.34.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-addon-api": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz", + "integrity": "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.37", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", + "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nypm": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz", + "integrity": "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "citty": "^0.2.0", + "pathe": "^2.0.3", + "tinyexec": "^1.0.2" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/nypm/node_modules/citty": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz", + "integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/nypm/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/nypm/node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/playwright": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", + "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.59.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.59.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", + "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prisma": { + "version": "6.19.3", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.3.tgz", + "integrity": "sha512-++ZJ0ijLrDJF6hNB4t4uxg2br3fC4H9Yc9tcbjr2fcNFP3rh/SBNrAgjhsqBU4Ght8JPrVofG/ZkXfnSfnYsFg==", + "devOptional": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@prisma/config": "6.19.3", + "@prisma/engines": "6.19.3" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=18.18" + }, + "peerDependencies": { + "typescript": ">=5.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "devOptional": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialport": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-13.0.0.tgz", + "integrity": "sha512-PHpnTd8isMGPfFTZNCzOZp9m4mAJSNWle9Jxu6BPTcWq7YXl5qN7tp8Sgn0h+WIGcD6JFz5QDgixC2s4VW7vzg==", + "license": "MIT", + "dependencies": { + "@serialport/binding-mock": "10.2.2", + "@serialport/bindings-cpp": "13.0.0", + "@serialport/parser-byte-length": "13.0.0", + "@serialport/parser-cctalk": "13.0.0", + "@serialport/parser-delimiter": "13.0.0", + "@serialport/parser-inter-byte-timeout": "13.0.0", + "@serialport/parser-packet-length": "13.0.0", + "@serialport/parser-readline": "13.0.0", + "@serialport/parser-ready": "13.0.0", + "@serialport/parser-regex": "13.0.0", + "@serialport/parser-slip-encoder": "13.0.0", + "@serialport/parser-spacepacket": "13.0.0", + "@serialport/stream": "13.0.0", + "debug": "4.4.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", + "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vitest": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", + "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.9", + "@vitest/mocker": "2.1.9", + "@vitest/pretty-format": "^2.1.9", + "@vitest/runner": "2.1.9", + "@vitest/snapshot": "2.1.9", + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", + "pathe": "^1.1.2", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.9", + "@vitest/ui": "2.1.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..18644e3 --- /dev/null +++ b/package.json @@ -0,0 +1,46 @@ +{ + "name": "lavanderia-checo-sistema", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", + "test": "vitest run", + "test:watch": "vitest", + "test:e2e": "playwright test", + "prisma:generate": "prisma generate", + "prisma:migrate": "prisma migrate dev", + "prisma:seed": "prisma db seed" + }, + "prisma": { + "seed": "tsx prisma/seed.ts" + }, + "dependencies": { + "@prisma/client": "^6.19.3", + "clsx": "^2.1.1", + "date-fns": "^4.1.0", + "date-fns-tz": "^3.1.3", + "next": "^15.1.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "serialport": "^13.0.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@playwright/test": "^1.48.0", + "@types/node": "^22.10.2", + "@types/react": "^19.0.2", + "@types/react-dom": "^19.0.2", + "autoprefixer": "^10.4.20", + "eslint": "^8.57.1", + "eslint-config-next": "^15.5.14", + "postcss": "^8.4.49", + "prisma": "^6.19.3", + "tailwindcss": "^3.4.16", + "tsx": "^4.19.2", + "typescript": "^5.7.2", + "vitest": "^2.1.8" + } +} diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..9a6eaf9 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from "@playwright/test"; + +export default defineConfig({ + testDir: "./tests/e2e", + timeout: 60_000, + use: { + baseURL: "http://127.0.0.1:3000", + headless: true + }, + webServer: { + command: "npm run dev", + port: 3000, + reuseExistingServer: !process.env.CI + } +}); diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..ba80730 --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +}; diff --git a/prisma/migrations/20260406193800_init/migration.sql b/prisma/migrations/20260406193800_init/migration.sql new file mode 100644 index 0000000..7b2e4ee --- /dev/null +++ b/prisma/migrations/20260406193800_init/migration.sql @@ -0,0 +1,121 @@ +-- CreateTable +CREATE TABLE "Machine" ( + "id" TEXT NOT NULL PRIMARY KEY, + "name" TEXT NOT NULL, + "type" TEXT NOT NULL, + "relayChannel" INTEGER NOT NULL, + "defaultPriceCents" INTEGER NOT NULL, + "defaultDurationMinutes" INTEGER NOT NULL, + "outOfService" BOOLEAN NOT NULL DEFAULT false, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); + +-- CreateTable +CREATE TABLE "Employee" ( + "id" TEXT NOT NULL PRIMARY KEY, + "name" TEXT NOT NULL, + "pin" TEXT NOT NULL, + "isAdmin" BOOLEAN NOT NULL DEFAULT false, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); + +-- CreateTable +CREATE TABLE "Transaction" ( + "id" TEXT NOT NULL PRIMARY KEY, + "machineId" TEXT NOT NULL, + "employeeId" TEXT NOT NULL, + "amountCents" INTEGER NOT NULL, + "paymentMethod" TEXT NOT NULL, + "startedAt" DATETIME NOT NULL, + "expectedEndAt" DATETIME NOT NULL, + "status" TEXT NOT NULL DEFAULT 'pending_relay', + "endedAt" DATETIME, + "relayOnAttemptedAt" DATETIME, + "relayTurnedOnAt" DATETIME, + "relayOffAttemptedAt" DATETIME, + "relayTurnedOffAt" DATETIME, + "relayFailureReason" TEXT, + "voidReason" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "Transaction_machineId_fkey" FOREIGN KEY ("machineId") REFERENCES "Machine" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "Transaction_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "TransactionExtension" ( + "id" TEXT NOT NULL PRIMARY KEY, + "transactionId" TEXT NOT NULL, + "employeeId" TEXT NOT NULL, + "extraMinutes" INTEGER NOT NULL, + "extraAmountCents" INTEGER NOT NULL, + "reason" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "TransactionExtension_transactionId_fkey" FOREIGN KEY ("transactionId") REFERENCES "Transaction" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "TransactionExtension_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "Shift" ( + "id" TEXT NOT NULL PRIMARY KEY, + "employeeId" TEXT NOT NULL, + "startTime" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "endTime" DATETIME, + "startingCashCents" INTEGER NOT NULL, + "expectedCashCents" INTEGER, + "actualCashCents" INTEGER, + "differenceCashCents" INTEGER, + "notes" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "Shift_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "CashMovement" ( + "id" TEXT NOT NULL PRIMARY KEY, + "shiftId" TEXT NOT NULL, + "employeeId" TEXT NOT NULL, + "type" TEXT NOT NULL, + "amountCents" INTEGER NOT NULL, + "reason" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "CashMovement_shiftId_fkey" FOREIGN KEY ("shiftId") REFERENCES "Shift" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "CashMovement_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "AppConfig" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT DEFAULT 1, + "businessName" TEXT NOT NULL DEFAULT 'La Burbuja', + "timezone" TEXT NOT NULL DEFAULT 'America/Monterrey', + "currency" TEXT NOT NULL DEFAULT 'MXN', + "serialPortPath" TEXT NOT NULL DEFAULT 'COM3', + "serialBaudRate" INTEGER NOT NULL DEFAULT 9600, + "relayMockMode" BOOLEAN NOT NULL DEFAULT true, + "relayConnected" BOOLEAN NOT NULL DEFAULT false, + "updatedAt" DATETIME NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "Machine_name_key" ON "Machine"("name"); + +-- CreateIndex +CREATE UNIQUE INDEX "Machine_relayChannel_key" ON "Machine"("relayChannel"); + +-- CreateIndex +CREATE INDEX "Transaction_expectedEndAt_idx" ON "Transaction"("expectedEndAt"); + +-- CreateIndex +CREATE INDEX "Transaction_status_idx" ON "Transaction"("status"); + +-- CreateIndex +CREATE INDEX "Shift_startTime_idx" ON "Shift"("startTime"); + +-- CreateIndex +CREATE INDEX "CashMovement_createdAt_idx" ON "CashMovement"("createdAt"); + diff --git a/prisma/migrations/20260406205909_pricing_variables/migration.sql b/prisma/migrations/20260406205909_pricing_variables/migration.sql new file mode 100644 index 0000000..fb0ef66 --- /dev/null +++ b/prisma/migrations/20260406205909_pricing_variables/migration.sql @@ -0,0 +1,31 @@ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_AppConfig" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT DEFAULT 1, + "businessName" TEXT NOT NULL DEFAULT 'La Burbuja', + "timezone" TEXT NOT NULL DEFAULT 'America/Monterrey', + "currency" TEXT NOT NULL DEFAULT 'MXN', + "serialPortPath" TEXT NOT NULL DEFAULT 'COM3', + "serialBaudRate" INTEGER NOT NULL DEFAULT 9600, + "relayMockMode" BOOLEAN NOT NULL DEFAULT true, + "relayConnected" BOOLEAN NOT NULL DEFAULT false, + "selfServiceWashPriceCents" INTEGER NOT NULL DEFAULT 4500, + "selfServiceDryPriceCents" INTEGER NOT NULL DEFAULT 4500, + "selfServiceCycleMinutes" INTEGER NOT NULL DEFAULT 50, + "encargoPricePerKgCents" INTEGER NOT NULL DEFAULT 3300, + "encargoMinimumChargeCents" INTEGER NOT NULL DEFAULT 12000, + "xlEdredonIndividualCents" INTEGER NOT NULL DEFAULT 15000, + "xlEdredonMatrimonialCents" INTEGER NOT NULL DEFAULT 18000, + "xlEdredonKingCents" INTEGER NOT NULL DEFAULT 20000, + "xlCobijaGruesaCents" INTEGER NOT NULL DEFAULT 12000, + "xlAlmohadaParCents" INTEGER NOT NULL DEFAULT 8000, + "dryCleaningMinimumCents" INTEGER NOT NULL DEFAULT 15000, + "dryCleaningUrgentSurchargePct" INTEGER NOT NULL DEFAULT 50, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "new_AppConfig" ("businessName", "currency", "id", "relayConnected", "relayMockMode", "serialBaudRate", "serialPortPath", "timezone", "updatedAt") SELECT "businessName", "currency", "id", "relayConnected", "relayMockMode", "serialBaudRate", "serialPortPath", "timezone", "updatedAt" FROM "AppConfig"; +DROP TABLE "AppConfig"; +ALTER TABLE "new_AppConfig" RENAME TO "AppConfig"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/migrations/20260406230249_customer_loyalty_addons/migration.sql b/prisma/migrations/20260406230249_customer_loyalty_addons/migration.sql new file mode 100644 index 0000000..a13fe8f --- /dev/null +++ b/prisma/migrations/20260406230249_customer_loyalty_addons/migration.sql @@ -0,0 +1,157 @@ +/* + Warnings: + + - Added the required column `baseAmountCents` to the `Transaction` table without a default value. This is not possible if the table is not empty. + - Added the required column `customerId` to the `Transaction` table without a default value. This is not possible if the table is not empty. + - Added the required column `ticketNumber` to the `Transaction` table without a default value. This is not possible if the table is not empty. + +*/ +-- CreateTable +CREATE TABLE "Customer" ( + "id" TEXT NOT NULL PRIMARY KEY, + "firstName" TEXT NOT NULL, + "lastName" TEXT NOT NULL, + "phone" TEXT NOT NULL, + "email" TEXT, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "Customer" ("id", "firstName", "lastName", "phone", "email", "isActive", "createdAt", "updatedAt") +VALUES ('legacy-customer', 'Cliente', 'Mostrador', 'LEGACY-UNASSIGNED', NULL, true, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); + +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_AppConfig" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT DEFAULT 1, + "businessName" TEXT NOT NULL DEFAULT 'La Burbuja', + "timezone" TEXT NOT NULL DEFAULT 'America/Monterrey', + "currency" TEXT NOT NULL DEFAULT 'MXN', + "serialPortPath" TEXT NOT NULL DEFAULT 'COM3', + "serialBaudRate" INTEGER NOT NULL DEFAULT 9600, + "relayMockMode" BOOLEAN NOT NULL DEFAULT true, + "relayConnected" BOOLEAN NOT NULL DEFAULT false, + "selfServiceWashPriceCents" INTEGER NOT NULL DEFAULT 4500, + "selfServiceDryPriceCents" INTEGER NOT NULL DEFAULT 4500, + "selfServiceCycleMinutes" INTEGER NOT NULL DEFAULT 50, + "encargoPricePerKgCents" INTEGER NOT NULL DEFAULT 3300, + "encargoMinimumChargeCents" INTEGER NOT NULL DEFAULT 12000, + "xlEdredonIndividualCents" INTEGER NOT NULL DEFAULT 15000, + "xlEdredonMatrimonialCents" INTEGER NOT NULL DEFAULT 18000, + "xlEdredonKingCents" INTEGER NOT NULL DEFAULT 20000, + "xlCobijaGruesaCents" INTEGER NOT NULL DEFAULT 12000, + "xlAlmohadaParCents" INTEGER NOT NULL DEFAULT 8000, + "dryCleaningMinimumCents" INTEGER NOT NULL DEFAULT 15000, + "dryCleaningUrgentSurchargePct" INTEGER NOT NULL DEFAULT 50, + "detergentAddonCents" INTEGER NOT NULL DEFAULT 500, + "softenerAddonCents" INTEGER NOT NULL DEFAULT 500, + "bleachAddonCents" INTEGER NOT NULL DEFAULT 500, + "loyaltyEveryNTransactions" INTEGER NOT NULL DEFAULT 10, + "loyaltyDiscountPct" INTEGER NOT NULL DEFAULT 50, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "new_AppConfig" ("businessName", "currency", "dryCleaningMinimumCents", "dryCleaningUrgentSurchargePct", "encargoMinimumChargeCents", "encargoPricePerKgCents", "id", "relayConnected", "relayMockMode", "selfServiceCycleMinutes", "selfServiceDryPriceCents", "selfServiceWashPriceCents", "serialBaudRate", "serialPortPath", "timezone", "updatedAt", "xlAlmohadaParCents", "xlCobijaGruesaCents", "xlEdredonIndividualCents", "xlEdredonKingCents", "xlEdredonMatrimonialCents") SELECT "businessName", "currency", "dryCleaningMinimumCents", "dryCleaningUrgentSurchargePct", "encargoMinimumChargeCents", "encargoPricePerKgCents", "id", "relayConnected", "relayMockMode", "selfServiceCycleMinutes", "selfServiceDryPriceCents", "selfServiceWashPriceCents", "serialBaudRate", "serialPortPath", "timezone", "updatedAt", "xlAlmohadaParCents", "xlCobijaGruesaCents", "xlEdredonIndividualCents", "xlEdredonKingCents", "xlEdredonMatrimonialCents" FROM "AppConfig"; +DROP TABLE "AppConfig"; +ALTER TABLE "new_AppConfig" RENAME TO "AppConfig"; +CREATE TABLE "new_Transaction" ( + "id" TEXT NOT NULL PRIMARY KEY, + "ticketNumber" INTEGER NOT NULL, + "machineId" TEXT NOT NULL, + "employeeId" TEXT NOT NULL, + "customerId" TEXT NOT NULL, + "baseAmountCents" INTEGER NOT NULL, + "discountCents" INTEGER NOT NULL DEFAULT 0, + "loyaltyDiscountApplied" BOOLEAN NOT NULL DEFAULT false, + "addonDetergentQty" INTEGER NOT NULL DEFAULT 0, + "addonSoftenerQty" INTEGER NOT NULL DEFAULT 0, + "addonBleachQty" INTEGER NOT NULL DEFAULT 0, + "addonAmountCents" INTEGER NOT NULL DEFAULT 0, + "amountCents" INTEGER NOT NULL, + "paymentMethod" TEXT NOT NULL, + "startedAt" DATETIME NOT NULL, + "expectedEndAt" DATETIME NOT NULL, + "status" TEXT NOT NULL DEFAULT 'pending_relay', + "endedAt" DATETIME, + "relayOnAttemptedAt" DATETIME, + "relayTurnedOnAt" DATETIME, + "relayOffAttemptedAt" DATETIME, + "relayTurnedOffAt" DATETIME, + "relayFailureReason" TEXT, + "voidReason" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "Transaction_machineId_fkey" FOREIGN KEY ("machineId") REFERENCES "Machine" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "Transaction_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee" ("id") ON DELETE RESTRICT ON UPDATE CASCADE, + CONSTRAINT "Transaction_customerId_fkey" FOREIGN KEY ("customerId") REFERENCES "Customer" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); +INSERT INTO "new_Transaction" ( + "id", + "ticketNumber", + "machineId", + "employeeId", + "customerId", + "baseAmountCents", + "discountCents", + "loyaltyDiscountApplied", + "addonDetergentQty", + "addonSoftenerQty", + "addonBleachQty", + "addonAmountCents", + "amountCents", + "paymentMethod", + "startedAt", + "expectedEndAt", + "status", + "endedAt", + "relayOnAttemptedAt", + "relayTurnedOnAt", + "relayOffAttemptedAt", + "relayTurnedOffAt", + "relayFailureReason", + "voidReason", + "createdAt", + "updatedAt" +) +SELECT + "id", + ROW_NUMBER() OVER (ORDER BY "createdAt", "id") AS "ticketNumber", + "machineId", + "employeeId", + 'legacy-customer' AS "customerId", + "amountCents" AS "baseAmountCents", + 0 AS "discountCents", + false AS "loyaltyDiscountApplied", + 0 AS "addonDetergentQty", + 0 AS "addonSoftenerQty", + 0 AS "addonBleachQty", + 0 AS "addonAmountCents", + "amountCents", + "paymentMethod", + "startedAt", + "expectedEndAt", + "status", + "endedAt", + "relayOnAttemptedAt", + "relayTurnedOnAt", + "relayOffAttemptedAt", + "relayTurnedOffAt", + "relayFailureReason", + "voidReason", + "createdAt", + "updatedAt" +FROM "Transaction"; +DROP TABLE "Transaction"; +ALTER TABLE "new_Transaction" RENAME TO "Transaction"; +CREATE UNIQUE INDEX "Transaction_ticketNumber_key" ON "Transaction"("ticketNumber"); +CREATE INDEX "Transaction_expectedEndAt_idx" ON "Transaction"("expectedEndAt"); +CREATE INDEX "Transaction_status_idx" ON "Transaction"("status"); +CREATE INDEX "Transaction_customerId_idx" ON "Transaction"("customerId"); +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; + +-- CreateIndex +CREATE UNIQUE INDEX "Customer_phone_key" ON "Customer"("phone"); + +-- CreateIndex +CREATE INDEX "Customer_lastName_firstName_idx" ON "Customer"("lastName", "firstName"); diff --git a/prisma/migrations/20260407001000_transaction_service_type/migration.sql b/prisma/migrations/20260407001000_transaction_service_type/migration.sql new file mode 100644 index 0000000..d3e5934 --- /dev/null +++ b/prisma/migrations/20260407001000_transaction_service_type/migration.sql @@ -0,0 +1 @@ +ALTER TABLE "Transaction" ADD COLUMN "serviceType" TEXT NOT NULL DEFAULT 'autoservicio'; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..2a5a444 --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "sqlite" diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..80c22c1 --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,162 @@ +generator client { + provider = "prisma-client-js" + engineType = "binary" +} + +datasource db { + provider = "sqlite" + url = env("DATABASE_URL") +} + +model Machine { + id String @id @default(cuid()) + name String @unique + type String + relayChannel Int @unique + defaultPriceCents Int + defaultDurationMinutes Int + outOfService Boolean @default(false) + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + transactions Transaction[] +} + +model Employee { + id String @id @default(cuid()) + name String + pin String + isAdmin Boolean @default(false) + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + shifts Shift[] + transactions Transaction[] + cashMovements CashMovement[] + extensions TransactionExtension[] +} + +model Customer { + id String @id @default(cuid()) + firstName String + lastName String + phone String @unique + email String? + isActive Boolean @default(true) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + transactions Transaction[] + + @@index([lastName, firstName]) +} + +model Transaction { + id String @id @default(cuid()) + ticketNumber Int @unique + machineId String + machine Machine @relation(fields: [machineId], references: [id]) + employeeId String + employee Employee @relation(fields: [employeeId], references: [id]) + customerId String + customer Customer @relation(fields: [customerId], references: [id]) + baseAmountCents Int + discountCents Int @default(0) + loyaltyDiscountApplied Boolean @default(false) + addonDetergentQty Int @default(0) + addonSoftenerQty Int @default(0) + addonBleachQty Int @default(0) + addonAmountCents Int @default(0) + serviceType String @default("autoservicio") + amountCents Int + paymentMethod String + startedAt DateTime + expectedEndAt DateTime + status String @default("pending_relay") + endedAt DateTime? + relayOnAttemptedAt DateTime? + relayTurnedOnAt DateTime? + relayOffAttemptedAt DateTime? + relayTurnedOffAt DateTime? + relayFailureReason String? + voidReason String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + extensions TransactionExtension[] + + @@index([expectedEndAt]) + @@index([status]) + @@index([customerId]) +} + +model TransactionExtension { + id String @id @default(cuid()) + transactionId String + transaction Transaction @relation(fields: [transactionId], references: [id]) + employeeId String + employee Employee @relation(fields: [employeeId], references: [id]) + extraMinutes Int + extraAmountCents Int + reason String? + createdAt DateTime @default(now()) +} + +model Shift { + id String @id @default(cuid()) + employeeId String + employee Employee @relation(fields: [employeeId], references: [id]) + startTime DateTime @default(now()) + endTime DateTime? + startingCashCents Int + expectedCashCents Int? + actualCashCents Int? + differenceCashCents Int? + notes String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + cashMovements CashMovement[] + + @@index([startTime]) +} + +model CashMovement { + id String @id @default(cuid()) + shiftId String + shift Shift @relation(fields: [shiftId], references: [id]) + employeeId String + employee Employee @relation(fields: [employeeId], references: [id]) + type String + amountCents Int + reason String + createdAt DateTime @default(now()) + + @@index([createdAt]) +} + +model AppConfig { + id Int @id @default(1) + businessName String @default("La Burbuja") + timezone String @default("America/Monterrey") + currency String @default("MXN") + serialPortPath String @default("COM3") + serialBaudRate Int @default(9600) + relayMockMode Boolean @default(true) + relayConnected Boolean @default(false) + selfServiceWashPriceCents Int @default(4500) + selfServiceDryPriceCents Int @default(4500) + selfServiceCycleMinutes Int @default(50) + encargoPricePerKgCents Int @default(3300) + encargoMinimumChargeCents Int @default(12000) + xlEdredonIndividualCents Int @default(15000) + xlEdredonMatrimonialCents Int @default(18000) + xlEdredonKingCents Int @default(20000) + xlCobijaGruesaCents Int @default(12000) + xlAlmohadaParCents Int @default(8000) + dryCleaningMinimumCents Int @default(15000) + dryCleaningUrgentSurchargePct Int @default(50) + detergentAddonCents Int @default(500) + softenerAddonCents Int @default(500) + bleachAddonCents Int @default(500) + loyaltyEveryNTransactions Int @default(10) + loyaltyDiscountPct Int @default(50) + updatedAt DateTime @updatedAt +} diff --git a/prisma/seed.ts b/prisma/seed.ts new file mode 100644 index 0000000..2107b73 --- /dev/null +++ b/prisma/seed.ts @@ -0,0 +1,76 @@ +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); + +type ComboLabel = "Encargo" | "XL"; + +function buildMachineName(type: "washer" | "dryer", number: number, label?: ComboLabel) { + const base = type === "washer" ? `Lavadora ${number}` : `Secadora ${number}`; + return label ? `${base} (${label})` : base; +} + +async function main() { + await prisma.appConfig.upsert({ + where: { id: 1 }, + update: {}, + create: { + id: 1, + businessName: "La Burbuja", + timezone: "America/Monterrey", + currency: "MXN", + serialPortPath: "COM3", + serialBaudRate: 9600, + relayMockMode: true + } + }); + + await prisma.employee.upsert({ + where: { id: "admin-default" }, + update: {}, + create: { + id: "admin-default", + name: "Administrador", + pin: "1234", + isAdmin: true + } + }); + + const existingMachineCount = await prisma.machine.count(); + + if (existingMachineCount === 0) { + const combos = [ + ...Array.from({ length: 12 }, (_, index) => ({ number: index + 1 as number, label: undefined as ComboLabel | undefined })), + { number: 13, label: "Encargo" as const }, + { number: 14, label: "Encargo" as const }, + { number: 15, label: "Encargo" as const }, + { number: 16, label: "XL" as const } + ]; + + const washers = combos.map((combo, index) => ({ + name: buildMachineName("washer", combo.number, combo.label), + type: "washer" as const, + relayChannel: index, + defaultPriceCents: 8000, + defaultDurationMinutes: 35 + })); + const dryers = combos.map((combo, index) => ({ + name: buildMachineName("dryer", combo.number, combo.label), + type: "dryer" as const, + relayChannel: index + combos.length, + defaultPriceCents: 6000, + defaultDurationMinutes: 45 + })); + const machines = [...washers, ...dryers]; + await prisma.machine.createMany({ data: machines }); + } +} + +main() + .then(async () => { + await prisma.$disconnect(); + }) + .catch(async (error) => { + console.error(error); + await prisma.$disconnect(); + process.exit(1); + }); diff --git a/scripts/start-local.ps1 b/scripts/start-local.ps1 new file mode 100644 index 0000000..784bd09 --- /dev/null +++ b/scripts/start-local.ps1 @@ -0,0 +1,11 @@ +param( + [switch]$Migrate +) + +if ($Migrate) { + npm run prisma:migrate +} + +npm run prisma:generate +npm run prisma:seed +npm run dev diff --git a/src/app/api/auth/change-pin/route.ts b/src/app/api/auth/change-pin/route.ts new file mode 100644 index 0000000..a68c047 --- /dev/null +++ b/src/app/api/auth/change-pin/route.ts @@ -0,0 +1,43 @@ +import { z } from "zod"; + +import { prisma } from "@/lib/db"; +import { fail, ok } from "@/lib/http"; +import { loginWithPin } from "@/server/services/authService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const schema = z.object({ + employeeId: z.string().min(1), + currentPin: z.string().regex(/^\d{4}$/), + newPin: z.string().regex(/^\d{4}$/) +}); + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + const payload = schema.parse(await request.json()); + const requester = await loginWithPin(payload.currentPin); + + if (requester.id !== payload.employeeId && !requester.isAdmin) { + return fail("No autorizado para cambiar este PIN", 403); + } + + if (payload.currentPin === payload.newPin && requester.id === payload.employeeId) { + return fail("El nuevo PIN debe ser diferente al actual", 400); + } + + const employee = await prisma.employee.update({ + where: { id: payload.employeeId }, + data: { pin: payload.newPin } + }); + + return ok({ + employee: { + id: employee.id, + name: employee.name, + isAdmin: employee.isAdmin + } + }); + } catch (error) { + return fail("No fue posible cambiar PIN", 400, String(error)); + } +} diff --git a/src/app/api/auth/pin/route.ts b/src/app/api/auth/pin/route.ts new file mode 100644 index 0000000..36a7290 --- /dev/null +++ b/src/app/api/auth/pin/route.ts @@ -0,0 +1,24 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { loginWithPin } from "@/server/services/authService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const schema = z.object({ + pin: z.string().length(4) +}); + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + const payload = schema.parse(await request.json()); + const employee = await loginWithPin(payload.pin); + return ok({ + id: employee.id, + name: employee.name, + isAdmin: employee.isAdmin + }); + } catch (error) { + return fail("No fue posible autenticar empleado", 401, String(error)); + } +} diff --git a/src/app/api/customers/route.ts b/src/app/api/customers/route.ts new file mode 100644 index 0000000..b237fcc --- /dev/null +++ b/src/app/api/customers/route.ts @@ -0,0 +1,52 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { createCustomer, listCustomers } from "@/server/services/customerService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const createSchema = z.object({ + firstName: z.string().trim().min(2).max(80), + lastName: z.string().trim().min(2).max(80), + phone: z.string().trim().min(8).max(30), + email: z + .string() + .trim() + .email() + .max(120) + .optional() +}); + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + const url = new URL(request.url); + const query = url.searchParams.get("query") ?? undefined; + const limitRaw = url.searchParams.get("limit"); + const limit = limitRaw ? Number(limitRaw) : undefined; + const payload = await listCustomers({ query, limit }); + return ok(payload); + } catch (error) { + return fail("No fue posible cargar clientes", 400, String(error)); + } +} + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + const payload = createSchema.parse(await request.json()); + const customer = await createCustomer(payload); + const lookup = await listCustomers({ + query: customer.phone, + limit: 1 + }); + return ok( + { + customer: lookup.customers[0] ?? null, + loyalty: lookup.loyalty + }, + 201 + ); + } catch (error) { + return fail("No fue posible registrar cliente", 400, String(error)); + } +} diff --git a/src/app/api/machines/[id]/route.ts b/src/app/api/machines/[id]/route.ts new file mode 100644 index 0000000..24890a1 --- /dev/null +++ b/src/app/api/machines/[id]/route.ts @@ -0,0 +1,32 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { updateMachineConfig } from "@/server/services/machineService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const patchSchema = z.object({ + name: z.string().min(2).optional(), + relayChannel: z.number().int().min(0).max(63).optional(), + defaultPriceCents: z.number().int().positive().optional(), + defaultDurationMinutes: z.number().int().positive().optional(), + outOfService: z.boolean().optional(), + isActive: z.boolean().optional() +}); + +type Context = { + params: Promise<{ id: string }>; +}; + +export async function PATCH(request: Request, context: Context) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const { id } = await context.params; + const payload = patchSchema.parse(await request.json()); + const machine = await updateMachineConfig(id, payload); + return ok({ machine }); + } catch (error) { + return fail("No fue posible actualizar maquina", 403, String(error)); + } +} diff --git a/src/app/api/machines/bulk/route.ts b/src/app/api/machines/bulk/route.ts new file mode 100644 index 0000000..868662d --- /dev/null +++ b/src/app/api/machines/bulk/route.ts @@ -0,0 +1,27 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { updateAllMachineDefaults } from "@/server/services/machineService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const bulkPatchSchema = z + .object({ + defaultPriceCents: z.number().int().positive().optional(), + defaultDurationMinutes: z.number().int().positive().optional() + }) + .refine((value) => value.defaultPriceCents !== undefined || value.defaultDurationMinutes !== undefined, { + message: "Debe enviar al menos un campo para actualizar" + }); + +export async function PATCH(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const payload = bulkPatchSchema.parse(await request.json()); + const result = await updateAllMachineDefaults(payload); + return ok({ updated: result.count }); + } catch (error) { + return fail("No fue posible actualizar maquinas", 403, String(error)); + } +} diff --git a/src/app/api/machines/route.ts b/src/app/api/machines/route.ts new file mode 100644 index 0000000..0d6b639 --- /dev/null +++ b/src/app/api/machines/route.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { prisma } from "@/lib/db"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { getDashboardMachines } from "@/server/services/machineService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const createSchema = z.object({ + name: z.string().min(2), + type: z.enum(["washer", "dryer"]), + relayChannel: z.number().int().min(0).max(63), + defaultPriceCents: z.number().int().positive(), + defaultDurationMinutes: z.number().int().positive() +}); + +export async function GET() { + await ensureSystemBootstrapped(); + const data = await getDashboardMachines(); + return ok({ machines: data }); +} + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const payload = createSchema.parse(await request.json()); + const machine = await prisma.machine.create({ + data: payload + }); + return ok({ machine }, 201); + } catch (error) { + return fail("No fue posible crear maquina", 403, String(error)); + } +} diff --git a/src/app/api/reports/export/route.ts b/src/app/api/reports/export/route.ts new file mode 100644 index 0000000..c3ca28d --- /dev/null +++ b/src/app/api/reports/export/route.ts @@ -0,0 +1,24 @@ +import { parseDateRange } from "@/server/api/dateRange"; +import { fail } from "@/lib/http"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { getReportCsv } from "@/server/services/reportService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const url = new URL(request.url); + const range = parseDateRange(url.searchParams); + const csv = await getReportCsv(range); + return new Response(csv, { + status: 200, + headers: { + "Content-Type": "text/csv; charset=utf-8", + "Content-Disposition": "attachment; filename=\"reporte.csv\"" + } + }); + } catch (error) { + return fail("No fue posible exportar reporte", 403, String(error)); + } +} diff --git a/src/app/api/reports/summary/route.ts b/src/app/api/reports/summary/route.ts new file mode 100644 index 0000000..7d312af --- /dev/null +++ b/src/app/api/reports/summary/route.ts @@ -0,0 +1,18 @@ +import { fail, ok } from "@/lib/http"; +import { parseDateRange } from "@/server/api/dateRange"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { getReportSummary } from "@/server/services/reportService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const url = new URL(request.url); + const range = parseDateRange(url.searchParams); + const summary = await getReportSummary(range); + return ok(summary); + } catch (error) { + return fail("No fue posible generar reporte", 403, String(error)); + } +} diff --git a/src/app/api/reports/utilization/route.ts b/src/app/api/reports/utilization/route.ts new file mode 100644 index 0000000..cdea4b7 --- /dev/null +++ b/src/app/api/reports/utilization/route.ts @@ -0,0 +1,18 @@ +import { fail, ok } from "@/lib/http"; +import { parseDateRange } from "@/server/api/dateRange"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { getUtilizationReport } from "@/server/services/reportService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const url = new URL(request.url); + const range = parseDateRange(url.searchParams); + const utilization = await getUtilizationReport(range); + return ok({ utilization, range }); + } catch (error) { + return fail("No fue posible generar utilizacion", 403, String(error)); + } +} diff --git a/src/app/api/settings/business/route.ts b/src/app/api/settings/business/route.ts new file mode 100644 index 0000000..073091b --- /dev/null +++ b/src/app/api/settings/business/route.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; + +import { prisma } from "@/lib/db"; +import { fail, ok } from "@/lib/http"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const patchSchema = z.object({ + businessName: z.string().min(2).max(80), + timezone: z.string().min(3).max(50), + currency: z.string().min(3).max(3) +}); + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const config = await prisma.appConfig.findUnique({ where: { id: 1 } }); + return ok({ config }); + } catch (error) { + return fail("No autorizado", 403, String(error)); + } +} + +export async function PATCH(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const payload = patchSchema.parse(await request.json()); + const config = await prisma.appConfig.update({ + where: { id: 1 }, + data: payload + }); + return ok({ config }); + } catch (error) { + return fail("No fue posible actualizar negocio", 403, String(error)); + } +} diff --git a/src/app/api/settings/employees/[id]/route.ts b/src/app/api/settings/employees/[id]/route.ts new file mode 100644 index 0000000..214c082 --- /dev/null +++ b/src/app/api/settings/employees/[id]/route.ts @@ -0,0 +1,33 @@ +import { z } from "zod"; + +import { prisma } from "@/lib/db"; +import { fail, ok } from "@/lib/http"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const patchSchema = z.object({ + name: z.string().min(2).optional(), + pin: z.string().length(4).optional(), + isAdmin: z.boolean().optional(), + isActive: z.boolean().optional() +}); + +type Context = { + params: Promise<{ id: string }>; +}; + +export async function PATCH(request: Request, context: Context) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const { id } = await context.params; + const payload = patchSchema.parse(await request.json()); + const employee = await prisma.employee.update({ + where: { id }, + data: payload + }); + return ok({ employee }); + } catch (error) { + return fail("No fue posible actualizar empleado", 403, String(error)); + } +} diff --git a/src/app/api/settings/employees/route.ts b/src/app/api/settings/employees/route.ts new file mode 100644 index 0000000..58c7be8 --- /dev/null +++ b/src/app/api/settings/employees/route.ts @@ -0,0 +1,40 @@ +import { z } from "zod"; + +import { prisma } from "@/lib/db"; +import { fail, ok } from "@/lib/http"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const createSchema = z.object({ + name: z.string().min(2), + pin: z.string().length(4), + isAdmin: z.boolean().default(false) +}); + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const employees = await prisma.employee.findMany({ + where: { isActive: true }, + orderBy: { name: "asc" } + }); + return ok({ employees }); + } catch (error) { + return fail("No autorizado", 403, String(error)); + } +} + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const payload = createSchema.parse(await request.json()); + const employee = await prisma.employee.create({ + data: payload + }); + return ok({ employee }, 201); + } catch (error) { + return fail("No fue posible crear empleado", 403, String(error)); + } +} diff --git a/src/app/api/settings/pricing/route.ts b/src/app/api/settings/pricing/route.ts new file mode 100644 index 0000000..1b44a88 --- /dev/null +++ b/src/app/api/settings/pricing/route.ts @@ -0,0 +1,78 @@ +import { z } from "zod"; + +import { prisma } from "@/lib/db"; +import { fail, ok } from "@/lib/http"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const pricingSchema = z.object({ + selfServiceWashPriceCents: z.number().int().positive(), + selfServiceDryPriceCents: z.number().int().positive(), + selfServiceCycleMinutes: z.number().int().positive(), + encargoPricePerKgCents: z.number().int().positive(), + encargoMinimumChargeCents: z.number().int().positive(), + xlEdredonIndividualCents: z.number().int().positive(), + xlEdredonMatrimonialCents: z.number().int().positive(), + xlEdredonKingCents: z.number().int().positive(), + xlCobijaGruesaCents: z.number().int().positive(), + xlAlmohadaParCents: z.number().int().positive(), + dryCleaningMinimumCents: z.number().int().positive(), + dryCleaningUrgentSurchargePct: z.number().int().min(0).max(300), + detergentAddonCents: z.number().int().min(0).max(10_000), + softenerAddonCents: z.number().int().min(0).max(10_000), + bleachAddonCents: z.number().int().min(0).max(10_000), + loyaltyEveryNTransactions: z.number().int().min(1).max(200), + loyaltyDiscountPct: z.number().int().min(0).max(100) +}); + +export async function GET() { + await ensureSystemBootstrapped(); + try { + const config = await prisma.appConfig.findUnique({ where: { id: 1 } }); + if (!config) { + return fail("Configuracion no disponible", 404); + } + + return ok({ + pricing: { + selfServiceWashPriceCents: config.selfServiceWashPriceCents, + selfServiceDryPriceCents: config.selfServiceDryPriceCents, + selfServiceCycleMinutes: config.selfServiceCycleMinutes, + encargoPricePerKgCents: config.encargoPricePerKgCents, + encargoMinimumChargeCents: config.encargoMinimumChargeCents, + xlEdredonIndividualCents: config.xlEdredonIndividualCents, + xlEdredonMatrimonialCents: config.xlEdredonMatrimonialCents, + xlEdredonKingCents: config.xlEdredonKingCents, + xlCobijaGruesaCents: config.xlCobijaGruesaCents, + xlAlmohadaParCents: config.xlAlmohadaParCents, + dryCleaningMinimumCents: config.dryCleaningMinimumCents, + dryCleaningUrgentSurchargePct: config.dryCleaningUrgentSurchargePct, + detergentAddonCents: config.detergentAddonCents, + softenerAddonCents: config.softenerAddonCents, + bleachAddonCents: config.bleachAddonCents, + loyaltyEveryNTransactions: config.loyaltyEveryNTransactions, + loyaltyDiscountPct: config.loyaltyDiscountPct + } + }); + } catch (error) { + return fail("No fue posible cargar precios", 400, String(error)); + } +} + +export async function PATCH(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const payload = pricingSchema.parse(await request.json()); + const config = await prisma.appConfig.update({ + where: { id: 1 }, + data: payload + }); + return ok({ + pricing: payload, + updatedAt: config.updatedAt + }); + } catch (error) { + return fail("No fue posible actualizar precios", 403, String(error)); + } +} diff --git a/src/app/api/settings/serial/route.ts b/src/app/api/settings/serial/route.ts new file mode 100644 index 0000000..12f5041 --- /dev/null +++ b/src/app/api/settings/serial/route.ts @@ -0,0 +1,44 @@ +import { z } from "zod"; + +import { prisma } from "@/lib/db"; +import { fail, ok } from "@/lib/http"; +import { relayManager } from "@/server/relay/relayManager"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const patchSchema = z.object({ + relayMockMode: z.boolean(), + serialPortPath: z.string().min(1), + serialBaudRate: z.number().int().positive() +}); + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const config = await prisma.appConfig.findUnique({ where: { id: 1 } }); + const health = await relayManager.getHealth(); + const ports = await relayManager.listSerialPorts(); + return ok({ config, health, ports }); + } catch (error) { + return fail("No autorizado", 403, String(error)); + } +} + +export async function PATCH(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const payload = patchSchema.parse(await request.json()); + await prisma.appConfig.update({ + where: { id: 1 }, + data: payload + }); + await relayManager.connectWithSettings(payload.relayMockMode, payload.serialPortPath, payload.serialBaudRate); + const config = await prisma.appConfig.findUnique({ where: { id: 1 } }); + const health = await relayManager.getHealth(); + return ok({ config, health }); + } catch (error) { + return fail("No fue posible actualizar serial", 403, String(error)); + } +} diff --git a/src/app/api/shifts/active/route.ts b/src/app/api/shifts/active/route.ts new file mode 100644 index 0000000..73ce436 --- /dev/null +++ b/src/app/api/shifts/active/route.ts @@ -0,0 +1,17 @@ +import { fail, ok } from "@/lib/http"; +import { getActiveShift, getShiftSummary } from "@/server/services/shiftService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +export async function GET() { + await ensureSystemBootstrapped(); + try { + const shift = await getActiveShift(); + if (!shift) { + return ok({ shift: null, summary: null }); + } + const summary = await getShiftSummary(shift.id); + return ok({ shift, summary }); + } catch (error) { + return fail("No fue posible cargar turno activo", 400, String(error)); + } +} diff --git a/src/app/api/shifts/close/route.ts b/src/app/api/shifts/close/route.ts new file mode 100644 index 0000000..6549e83 --- /dev/null +++ b/src/app/api/shifts/close/route.ts @@ -0,0 +1,22 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { closeShift } from "@/server/services/shiftService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const schema = z.object({ + shiftId: z.string(), + actualCashCents: z.number().int().min(0), + notes: z.string().max(300).optional() +}); + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + const payload = schema.parse(await request.json()); + const shift = await closeShift(payload); + return ok({ shift }); + } catch (error) { + return fail("No fue posible cerrar turno", 400, String(error)); + } +} diff --git a/src/app/api/shifts/history/route.ts b/src/app/api/shifts/history/route.ts new file mode 100644 index 0000000..e6f6670 --- /dev/null +++ b/src/app/api/shifts/history/route.ts @@ -0,0 +1,18 @@ +import { fail, ok } from "@/lib/http"; +import { parseDateRange } from "@/server/api/dateRange"; +import { requireAdminFromRequest } from "@/server/services/authService"; +import { getShiftHistory } from "@/server/services/shiftService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + await requireAdminFromRequest(request); + const url = new URL(request.url); + const range = parseDateRange(url.searchParams); + const shifts = await getShiftHistory(range); + return ok({ shifts }); + } catch (error) { + return fail("No fue posible obtener historial de turnos", 403, String(error)); + } +} diff --git a/src/app/api/shifts/movements/route.ts b/src/app/api/shifts/movements/route.ts new file mode 100644 index 0000000..79da3a1 --- /dev/null +++ b/src/app/api/shifts/movements/route.ts @@ -0,0 +1,24 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { addCashMovement } from "@/server/services/shiftService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const schema = z.object({ + shiftId: z.string(), + employeeId: z.string(), + type: z.enum(["deposit", "withdrawal"]), + amountCents: z.number().int().positive(), + reason: z.string().min(3).max(120) +}); + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + const payload = schema.parse(await request.json()); + const movement = await addCashMovement(payload); + return ok({ movement }, 201); + } catch (error) { + return fail("No fue posible registrar movimiento", 400, String(error)); + } +} diff --git a/src/app/api/shifts/open/route.ts b/src/app/api/shifts/open/route.ts new file mode 100644 index 0000000..1f7df72 --- /dev/null +++ b/src/app/api/shifts/open/route.ts @@ -0,0 +1,21 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { openShift } from "@/server/services/shiftService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const schema = z.object({ + employeeId: z.string(), + startingCashCents: z.number().int().min(0) +}); + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + const payload = schema.parse(await request.json()); + const shift = await openShift(payload); + return ok({ shift }, 201); + } catch (error) { + return fail("No fue posible abrir turno", 400, String(error)); + } +} diff --git a/src/app/api/system/relay/route.ts b/src/app/api/system/relay/route.ts new file mode 100644 index 0000000..b02cac9 --- /dev/null +++ b/src/app/api/system/relay/route.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { relayManager } from "@/server/relay/relayManager"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const reconnectSchema = z.object({ + relayMockMode: z.boolean().optional(), + serialPortPath: z.string().optional(), + serialBaudRate: z.number().int().positive().optional() +}); + +export async function GET() { + try { + await ensureSystemBootstrapped(); + const health = await relayManager.getHealth(); + const ports = await relayManager.listSerialPorts(); + return ok({ health, ports }); + } catch (error) { + return fail("No fue posible consultar relay", 500, String(error)); + } +} + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + const payload = reconnectSchema.parse(await request.json()); + if (payload.relayMockMode !== undefined && payload.serialPortPath && payload.serialBaudRate) { + await relayManager.connectWithSettings(payload.relayMockMode, payload.serialPortPath, payload.serialBaudRate); + } else { + await relayManager.reconnect(); + } + const health = await relayManager.getHealth(); + return ok({ health }); + } catch (error) { + return fail("No fue posible reconectar relay", 400, String(error)); + } +} diff --git a/src/app/api/transactions/[id]/extend/route.ts b/src/app/api/transactions/[id]/extend/route.ts new file mode 100644 index 0000000..17cada8 --- /dev/null +++ b/src/app/api/transactions/[id]/extend/route.ts @@ -0,0 +1,31 @@ +import { z } from "zod"; + +import { addTimeToTransaction } from "@/server/services/activationService"; +import { fail, ok } from "@/lib/http"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const schema = z.object({ + employeeId: z.string(), + extraMinutes: z.number().int().positive(), + extraAmountCents: z.number().int().min(0), + reason: z.string().max(120).optional() +}); + +type Context = { + params: Promise<{ id: string }>; +}; + +export async function POST(request: Request, context: Context) { + await ensureSystemBootstrapped(); + try { + const { id } = await context.params; + const payload = schema.parse(await request.json()); + const transaction = await addTimeToTransaction({ + transactionId: id, + ...payload + }); + return ok({ transaction }); + } catch (error) { + return fail("No fue posible agregar tiempo", 400, String(error)); + } +} diff --git a/src/app/api/transactions/[id]/retry-relay/route.ts b/src/app/api/transactions/[id]/retry-relay/route.ts new file mode 100644 index 0000000..6a881e0 --- /dev/null +++ b/src/app/api/transactions/[id]/retry-relay/route.ts @@ -0,0 +1,18 @@ +import { fail, ok } from "@/lib/http"; +import { retryRelayOn } from "@/server/services/activationService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +type Context = { + params: Promise<{ id: string }>; +}; + +export async function POST(_request: Request, context: Context) { + await ensureSystemBootstrapped(); + try { + const { id } = await context.params; + const transaction = await retryRelayOn(id); + return ok({ transaction }); + } catch (error) { + return fail("No fue posible reintentar relay", 400, String(error)); + } +} diff --git a/src/app/api/transactions/[id]/void/route.ts b/src/app/api/transactions/[id]/void/route.ts new file mode 100644 index 0000000..e7c92e6 --- /dev/null +++ b/src/app/api/transactions/[id]/void/route.ts @@ -0,0 +1,28 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { voidTransaction } from "@/server/services/activationService"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const schema = z.object({ + reason: z.string().min(4).max(200) +}); + +type Context = { + params: Promise<{ id: string }>; +}; + +export async function POST(request: Request, context: Context) { + await ensureSystemBootstrapped(); + try { + const { id } = await context.params; + const payload = schema.parse(await request.json()); + const transaction = await voidTransaction({ + transactionId: id, + reason: payload.reason + }); + return ok({ transaction }); + } catch (error) { + return fail("No fue posible anular transaccion", 400, String(error)); + } +} diff --git a/src/app/api/transactions/route.ts b/src/app/api/transactions/route.ts new file mode 100644 index 0000000..8c2393c --- /dev/null +++ b/src/app/api/transactions/route.ts @@ -0,0 +1,70 @@ +import { z } from "zod"; + +import { fail, ok } from "@/lib/http"; +import { prisma } from "@/lib/db"; +import { SERVICE_TYPES } from "@/server/domain/constants"; +import { activateMachine } from "@/server/services/activationService"; +import { parseDateRange } from "@/server/api/dateRange"; +import { ensureSystemBootstrapped } from "@/server/system/bootstrap"; + +const activationSchema = z.object({ + machineId: z.string(), + employeeId: z.string(), + customerId: z.string(), + baseAmountCents: z.number().int().positive(), + durationMinutes: z.number().int().positive(), + serviceType: z.enum([SERVICE_TYPES.autoservicio, SERVICE_TYPES.encargo, SERVICE_TYPES.xl]), + paymentMethod: z.enum(["cash", "card", "transfer"]), + addons: z.object({ + detergentQty: z.number().int().min(0).max(50), + softenerQty: z.number().int().min(0).max(50), + bleachQty: z.number().int().min(0).max(50) + }) +}); + +export async function GET(request: Request) { + await ensureSystemBootstrapped(); + try { + const url = new URL(request.url); + const range = parseDateRange(url.searchParams); + const status = url.searchParams.get("status"); + const customerId = url.searchParams.get("customerId"); + const transactions = await prisma.transaction.findMany({ + where: { + createdAt: { + gte: range.from, + lte: range.to + }, + status: status ?? undefined, + customerId: customerId ?? undefined + }, + include: { + machine: { + select: { name: true } + }, + employee: { + select: { name: true } + }, + customer: { + select: { firstName: true, lastName: true, phone: true, email: true } + }, + extensions: true + }, + orderBy: { createdAt: "desc" } + }); + return ok({ transactions }); + } catch (error) { + return fail("No fue posible obtener transacciones", 400, String(error)); + } +} + +export async function POST(request: Request) { + await ensureSystemBootstrapped(); + try { + const payload = activationSchema.parse(await request.json()); + const result = await activateMachine(payload); + return ok(result, 201); + } catch (error) { + return fail("No fue posible activar maquina", 400, String(error)); + } +} diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 0000000..7494061 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,21 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + color-scheme: light; +} + +html, +body { + margin: 0; + padding: 0; + min-height: 100%; + background: radial-gradient(circle at top, #eef8f4 0%, #f8f6ee 45%, #efe8d4 100%); + color: #111827; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; +} + +* { + box-sizing: border-box; +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..fa346eb --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,16 @@ +import type { Metadata } from "next"; + +import "@/app/globals.css"; + +export const metadata: Metadata = { + title: "La Burbuja POS", + description: "Sistema local de lavanderia con control de relevadores" +}; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 0000000..68a8c45 --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,5 @@ +import { POSDashboard } from "@/components/POSDashboard"; + +export default function HomePage() { + return ; +} diff --git a/src/components/POSDashboard.tsx b/src/components/POSDashboard.tsx new file mode 100644 index 0000000..b2be310 --- /dev/null +++ b/src/components/POSDashboard.tsx @@ -0,0 +1,401 @@ +"use client"; + +import { useCallback, useEffect, useMemo, useState } from "react"; + +import { apiFetch } from "@/components/pos/api"; +import { LoginScreen } from "@/components/pos/LoginScreen"; +import { PanelTab } from "@/components/pos/PanelTab"; +import { ReportsTab } from "@/components/pos/ReportsTab"; +import { SettingsTab } from "@/components/pos/SettingsTab"; +import { ShiftTab } from "@/components/pos/ShiftTab"; +import type { ActiveShiftPayload, Employee, Machine, RelayHealth, ReportSummary, TicketPreviewData, UtilizationRow } from "@/components/pos/types"; +import { ActivateModal } from "@/components/pos/modals/ActivateModal"; +import { ChangePinModal } from "@/components/pos/modals/ChangePinModal"; +import { RunningModal } from "@/components/pos/modals/RunningModal"; +import { TicketPreviewModal } from "@/components/pos/modals/TicketPreviewModal"; + +type TabId = "panel" | "corte" | "reportes" | "config"; + +const tabLabels: Record = { + panel: "Panel", + corte: "Corte", + reportes: "Reportes", + config: "Configuracion" +}; + +type ActivationApiResponse = { + transaction: { + ticketNumber: number; + addonDetergentQty: number; + addonSoftenerQty: number; + addonBleachQty: number; + discountCents: number; + loyaltyDiscountApplied: boolean; + amountCents: number; + serviceType: "autoservicio" | "encargo" | "xl"; + paymentMethod: "cash" | "card" | "transfer"; + createdAt: string; + customer?: { + firstName: string; + lastName: string; + }; + employee?: { + name: string; + }; + machine?: { + name: string; + }; + }; + relayOk: boolean; + relayError?: string; +}; + +export function POSDashboard() { + const [tab, setTab] = useState("panel"); + const [pin, setPin] = useState(""); + const [sessionPin, setSessionPin] = useState(null); + const [employee, setEmployee] = useState(null); + const [employees, setEmployees] = useState([]); + const [machines, setMachines] = useState([]); + const [relayHealth, setRelayHealth] = useState(null); + const [activeShift, setActiveShift] = useState({ shift: null, summary: null }); + const [activateMachineId, setActivateMachineId] = useState(null); + const [runningMachineId, setRunningMachineId] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [ticker, setTicker] = useState(Date.now()); + const [reportFrom, setReportFrom] = useState(() => { + const d = new Date(); + d.setHours(0, 0, 0, 0); + return d.toISOString().slice(0, 16); + }); + const [reportTo, setReportTo] = useState(() => new Date().toISOString().slice(0, 16)); + const [reportSummary, setReportSummary] = useState(null); + const [utilization, setUtilization] = useState([]); + const [showChangePin, setShowChangePin] = useState(false); + const [ticketPreview, setTicketPreview] = useState(null); + const isAdmin = employee?.isAdmin ?? false; + const adminHeaders = useMemo>( + () => (sessionPin ? { "x-admin-pin": sessionPin } : ({} as Record)), + [sessionPin] + ); + const availableTabs = useMemo(() => (isAdmin ? (["panel", "corte", "reportes", "config"] as TabId[]) : (["panel", "corte"] as TabId[])), [isAdmin]); + + const selectedAvailable = useMemo(() => machines.find((machine) => machine.id === activateMachineId) ?? null, [activateMachineId, machines]); + const selectedRunning = useMemo(() => machines.find((machine) => machine.id === runningMachineId) ?? null, [runningMachineId, machines]); + + const loadDashboard = useCallback(async () => { + const [machinesPayload, relayPayload, shiftPayload] = await Promise.all([ + apiFetch<{ machines: Machine[] }>("/api/machines"), + apiFetch<{ health: RelayHealth }>("/api/system/relay"), + apiFetch("/api/shifts/active") + ]); + setMachines(machinesPayload.machines); + setRelayHealth(relayPayload.health); + setActiveShift(shiftPayload); + }, []); + + const loadEmployees = useCallback(async () => { + if (!isAdmin) { + setEmployees([]); + return; + } + const payload = await apiFetch<{ employees: Employee[] }>("/api/settings/employees", { + headers: adminHeaders + }); + setEmployees(payload.employees); + }, [adminHeaders, isAdmin]); + + const loadReports = useCallback(async () => { + if (!isAdmin) { + setReportSummary(null); + setUtilization([]); + return; + } + const query = `from=${encodeURIComponent(new Date(reportFrom).toISOString())}&to=${encodeURIComponent(new Date(reportTo).toISOString())}`; + const [summaryPayload, utilizationPayload] = await Promise.all([ + apiFetch(`/api/reports/summary?${query}`, { + headers: adminHeaders + }), + apiFetch<{ utilization: UtilizationRow[] }>(`/api/reports/utilization?${query}`, { + headers: adminHeaders + }) + ]); + setReportSummary(summaryPayload); + setUtilization(utilizationPayload.utilization); + }, [adminHeaders, isAdmin, reportFrom, reportTo]); + + const exportReports = useCallback(async () => { + if (!isAdmin || !sessionPin) { + throw new Error("Solo administrador puede exportar"); + } + + const query = `from=${encodeURIComponent(new Date(reportFrom).toISOString())}&to=${encodeURIComponent(new Date(reportTo).toISOString())}`; + const response = await fetch(`/api/reports/export?${query}`, { + headers: { + "x-admin-pin": sessionPin + } + }); + + if (!response.ok) { + const message = await response.text(); + throw new Error(message || "No fue posible exportar reporte"); + } + + const blob = await response.blob(); + const objectUrl = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.href = objectUrl; + link.download = "reporte.csv"; + document.body.appendChild(link); + link.click(); + link.remove(); + URL.revokeObjectURL(objectUrl); + }, [isAdmin, reportFrom, reportTo, sessionPin]); + + useEffect(() => { + setLoading(true); + Promise.all(isAdmin ? [loadDashboard(), loadEmployees()] : [loadDashboard()]) + .catch((err) => setError(err instanceof Error ? err.message : "No fue posible cargar datos")) + .finally(() => setLoading(false)); + }, [isAdmin, loadDashboard, loadEmployees]); + + useEffect(() => { + const id = setInterval(() => { + setTicker(Date.now()); + loadDashboard().catch(() => undefined); + }, 5000); + return () => clearInterval(id); + }, [loadDashboard]); + + useEffect(() => { + const id = setInterval(() => setTicker(Date.now()), 1000); + return () => clearInterval(id); + }, []); + + const login = async () => { + try { + const payload = await apiFetch("/api/auth/pin", { + method: "POST", + body: JSON.stringify({ pin }) + }); + setEmployee(payload); + setSessionPin(pin); + setTab("panel"); + setError(null); + } catch (err) { + setError(err instanceof Error ? err.message : "PIN invalido"); + } + }; + + const logout = () => { + setEmployee(null); + setSessionPin(null); + setPin(""); + setTab("panel"); + setShowChangePin(false); + setError(null); + setMachines([]); + setEmployees([]); + setRelayHealth(null); + setActiveShift({ shift: null, summary: null }); + setTicketPreview(null); + }; + + const activate = async ( + machine: Machine, + form: { + customerId: string; + customerName: string; + baseAmountCents: number; + durationMinutes: number; + serviceType: "autoservicio" | "encargo" | "xl"; + paymentMethod: "cash" | "card" | "transfer"; + addons: { + detergentQty: number; + softenerQty: number; + bleachQty: number; + }; + } + ) => { + if (!employee) { + return; + } + const result = await apiFetch("/api/transactions", { + method: "POST", + body: JSON.stringify({ + machineId: machine.id, + employeeId: employee.id, + customerId: form.customerId, + baseAmountCents: form.baseAmountCents, + durationMinutes: form.durationMinutes, + serviceType: form.serviceType, + paymentMethod: form.paymentMethod, + addons: form.addons + }) + }); + + const totalCents = result.transaction.amountCents; + const subtotalCents = Math.round(totalCents / 1.16); + const ivaCents = totalCents - subtotalCents; + const resolvedCustomerName = result.transaction.customer + ? `${result.transaction.customer.firstName} ${result.transaction.customer.lastName}`.trim() + : form.customerName; + + setTicketPreview({ + ticketNumber: result.transaction.ticketNumber, + customerName: resolvedCustomerName, + serviceType: result.transaction.serviceType ?? form.serviceType, + addons: { + detergentQty: result.transaction.addonDetergentQty, + softenerQty: result.transaction.addonSoftenerQty, + bleachQty: result.transaction.addonBleachQty + }, + loyaltyApplied: result.transaction.loyaltyDiscountApplied, + discountCents: result.transaction.discountCents, + subtotalCents, + ivaCents, + totalCents, + dateTimeIso: result.transaction.createdAt, + cashierName: result.transaction.employee?.name ?? employee.name, + machineName: result.transaction.machine?.name ?? machine.name, + paymentMethod: result.transaction.paymentMethod, + relayOk: result.relayOk + }); + + if (!result.relayOk && result.relayError) { + setError(`Ticket creado, pero no se encendio relay: ${result.relayError}`); + } else { + setError(null); + } + + setActivateMachineId(null); + await loadDashboard(); + }; + + const addTime = async (transactionId: string, extraMinutes: number, extraAmountCents: number) => { + if (!employee) { + return; + } + await apiFetch(`/api/transactions/${transactionId}/extend`, { + method: "POST", + body: JSON.stringify({ + employeeId: employee.id, + extraMinutes, + extraAmountCents + }) + }); + setRunningMachineId(null); + await loadDashboard(); + }; + + if (!employee) { + return ; + } + + return ( +
+
+
+

La Burbuja POS

+

Cajero: {employee.name}

+
+
+ + + +
+
+ + {relayHealth && ( +
+ Relay {relayHealth.mode === "mock" ? "SIMULADOR" : "SERIAL"}: {relayHealth.connected ? "Conectado" : "Desconectado"} + {relayHealth.error ? ` (${relayHealth.error})` : ""} +
+ )} + {error &&

{error}

} + {loading &&

Cargando datos...

} + + {tab === "panel" && ( + + )} + + {tab === "corte" && ( + + )} + + {tab === "reportes" && isAdmin && ( + + )} + + {tab === "config" && isAdmin && sessionPin && ( + { + await Promise.all([loadDashboard(), loadEmployees()]); + }} + onError={setError} + /> + )} + + {selectedAvailable && setActivateMachineId(null)} onConfirm={activate} />} + + {selectedRunning && selectedRunning.transaction && ( + setRunningMachineId(null)} onAddTime={addTime} /> + )} + + {showChangePin && ( + setShowChangePin(false)} + onSuccess={(newPin) => { + setSessionPin(newPin); + setShowChangePin(false); + setError(null); + }} + onError={setError} + /> + )} + + {ticketPreview && setTicketPreview(null)} />} +
+ ); +} diff --git a/src/components/pos/LoginScreen.tsx b/src/components/pos/LoginScreen.tsx new file mode 100644 index 0000000..3839d09 --- /dev/null +++ b/src/components/pos/LoginScreen.tsx @@ -0,0 +1,31 @@ +"use client"; + +type LoginScreenProps = { + pin: string; + error: string | null; + onPinChange: (value: string) => void; + onLogin: () => Promise; +}; + +export function LoginScreen({ pin, error, onPinChange, onLogin }: LoginScreenProps) { + return ( +
+

La Burbuja POS

+

Ingrese PIN para iniciar turno.

+ onPinChange(event.target.value.replace(/\D/g, "").slice(0, 4))} + className="rounded-xl border border-slate-300 bg-white px-4 py-4 text-2xl tracking-[0.4em]" + /> + + {error &&

{error}

} +
+ ); +} diff --git a/src/components/pos/PanelTab.tsx b/src/components/pos/PanelTab.tsx new file mode 100644 index 0000000..d46eb9c --- /dev/null +++ b/src/components/pos/PanelTab.tsx @@ -0,0 +1,103 @@ +"use client"; + +import type { Machine } from "@/components/pos/types"; +import { formatCurrency } from "@/lib/format"; + +type PanelTabProps = { + machines: Machine[]; + ticker: number; + onSelectAvailable: (machineId: string) => void; + onSelectRunning: (machineId: string) => void; +}; + +export function PanelTab({ machines, ticker, onSelectAvailable, onSelectRunning }: PanelTabProps) { + const washers = machines.filter((machine) => machine.type === "washer"); + const dryers = machines.filter((machine) => machine.type === "dryer"); + + const getSpecialLabel = (machine: Machine) => { + const upper = machine.name.toUpperCase(); + if (upper.includes("(ENCARGO)")) { + return "ENCARGO"; + } + if (upper.includes("(XL)")) { + return "XL"; + } + return null; + }; + + const renderMachineButton = (machine: Machine) => { + const remainingMinutes = machine.transaction + ? Math.max(0, Math.ceil((new Date(machine.transaction.expectedEndAt).getTime() - ticker) / 60_000)) + : 0; + const specialLabel = getSpecialLabel(machine); + + const statusClass = + machine.status === "out_of_service" + ? "border-2 border-slate-500 bg-slate-700 text-white" + : machine.status === "running" + ? machine.type === "washer" + ? "border-2 border-indigo-300 bg-indigo-800 text-white shadow-lg" + : "border-2 border-rose-300 bg-rose-800 text-white shadow-lg" + : machine.type === "washer" + ? "border-2 border-cyan-300 bg-cyan-100 text-cyan-950" + : "border-2 border-amber-300 bg-amber-100 text-amber-950"; + + return ( + + ); + }; + + return ( +
+
+

Lavadoras

+
{washers.map(renderMachineButton)}
+
+
+

Secadoras

+
{dryers.map(renderMachineButton)}
+
+
+ ); +} diff --git a/src/components/pos/ReportsTab.tsx b/src/components/pos/ReportsTab.tsx new file mode 100644 index 0000000..d30f86a --- /dev/null +++ b/src/components/pos/ReportsTab.tsx @@ -0,0 +1,100 @@ +"use client"; + +import type { ReportSummary, UtilizationRow } from "@/components/pos/types"; +import { formatCurrency } from "@/lib/format"; + +type ReportsTabProps = { + reportFrom: string; + reportTo: string; + setReportFrom: (value: string) => void; + setReportTo: (value: string) => void; + summary: ReportSummary | null; + utilization: UtilizationRow[]; + onLoad: () => Promise; + onExport: () => Promise; +}; + +export function ReportsTab({ + reportFrom, + reportTo, + setReportFrom, + setReportTo, + summary, + utilization, + onLoad, + onExport +}: ReportsTabProps) { + return ( +
+
+

Rango

+
+ setReportFrom(event.target.value)} + className="rounded-xl border border-slate-300 px-3 py-2" + /> + setReportTo(event.target.value)} + className="rounded-xl border border-slate-300 px-3 py-2" + /> + + +
+
+ + {summary && ( +
+

Resumen

+
+

Total: {formatCurrency(summary.totals.totalRevenueCents)}

+

Transacciones: {summary.totals.transactionCount}

+

Ticket promedio: {formatCurrency(summary.totals.avgTicketCents)}

+
+
+
+

Por metodo de pago

+
    + {summary.byPaymentMethod.map((row) => ( +
  • + {row.paymentMethod}: {formatCurrency(row.amountCents)} ({row.count}) +
  • + ))} +
+
+
+

Por maquina

+
    + {summary.byMachine.slice(0, 8).map((row) => ( +
  • + {row.machineName}: {formatCurrency(row.amountCents)} ({row.count}) +
  • + ))} +
+
+
+
+ )} + + {utilization.length > 0 && ( +
+

Utilizacion de maquinas

+
    + {utilization.map((row) => ( +
  • + {row.machineName}: {row.utilizationPct}% ({Math.round(row.usedMinutes)} min) +
  • + ))} +
+
+ )} +
+ ); +} diff --git a/src/components/pos/SettingsTab.tsx b/src/components/pos/SettingsTab.tsx new file mode 100644 index 0000000..d5d5af1 --- /dev/null +++ b/src/components/pos/SettingsTab.tsx @@ -0,0 +1,672 @@ +"use client"; + +import { useEffect, useState } from "react"; + +import { apiFetch } from "@/components/pos/api"; +import type { CustomerRecord, Employee, Machine, PricingVariables } from "@/components/pos/types"; +import { formatCurrency } from "@/lib/format"; + +type SettingsTabProps = { + employee: Employee; + adminPin: string; + machines: Machine[]; + employees: Employee[]; + onRefresh: () => Promise; + onError: (value: string) => void; +}; + +export function SettingsTab({ employee, adminPin, machines, employees, onRefresh, onError }: SettingsTabProps) { + const [newEmployeeName, setNewEmployeeName] = useState(""); + const [newEmployeePin, setNewEmployeePin] = useState(""); + const [serialPath, setSerialPath] = useState("COM3"); + const [serialBaudRate, setSerialBaudRate] = useState(9600); + const [mockMode, setMockMode] = useState(true); + const [bulkPrice, setBulkPrice] = useState(""); + const [bulkDuration, setBulkDuration] = useState(""); + const [machineDrafts, setMachineDrafts] = useState>({}); + const [pricing, setPricing] = useState(null); + const [customerQuery, setCustomerQuery] = useState(""); + const [customers, setCustomers] = useState([]); + const [customersLoading, setCustomersLoading] = useState(false); + const [showMachineList, setShowMachineList] = useState(false); + + useEffect(() => { + if (machines.length === 0) { + return; + } + if (!bulkPrice) { + setBulkPrice((machines[0].defaultPriceCents / 100).toString()); + } + if (!bulkDuration) { + setBulkDuration(machines[0].defaultDurationMinutes.toString()); + } + }, [bulkDuration, bulkPrice, machines]); + + useEffect(() => { + apiFetch<{ pricing: PricingVariables }>("/api/settings/pricing", { + headers: { + "x-admin-pin": adminPin + } + }) + .then((payload) => setPricing(payload.pricing)) + .catch(() => undefined); + }, [adminPin]); + + useEffect(() => { + const id = window.setTimeout(() => { + setCustomersLoading(true); + apiFetch<{ customers: CustomerRecord[] }>(`/api/customers?limit=200&query=${encodeURIComponent(customerQuery.trim())}`) + .then((payload) => setCustomers(payload.customers)) + .catch(() => undefined) + .finally(() => setCustomersLoading(false)); + }, 250); + + return () => window.clearTimeout(id); + }, [customerQuery]); + + const getMachineDraft = (machine: Machine) => + machineDrafts[machine.id] ?? { + price: machine.defaultPriceCents / 100, + duration: machine.defaultDurationMinutes + }; + + const washers = machines.filter((machine) => machine.type === "washer"); + const dryers = machines.filter((machine) => machine.type === "dryer"); + + const renderMachineItem = (machine: Machine) => ( +
  • +
    + {machine.name} + +
    +
    + + setMachineDrafts((current) => ({ + ...current, + [machine.id]: { + ...(current[machine.id] ?? { + price: machine.defaultPriceCents / 100, + duration: machine.defaultDurationMinutes + }), + price: Number(event.target.value || 0) + } + })) + } + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Precio" + /> + + setMachineDrafts((current) => ({ + ...current, + [machine.id]: { + ...(current[machine.id] ?? { + price: machine.defaultPriceCents / 100, + duration: machine.defaultDurationMinutes + }), + duration: Number(event.target.value || 0) + } + })) + } + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Minutos" + /> + +
    +
  • + ); + + return ( +
    +
    +

    Maquinas

    +
    +

    Aplicar valor global a todas

    +

    Despues puedes sobrescribir una maquina individualmente.

    +
    + setBulkPrice(event.target.value)} + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Precio global" + /> + setBulkDuration(event.target.value)} + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Minutos globales" + /> + +
    +
    +
    +

    Lista individual de maquinas

    + +
    + {showMachineList && ( +
    +
    + Lavadoras ({washers.length}) +
      {washers.map(renderMachineItem)}
    +
    +
    + Secadoras ({dryers.length}) +
      {dryers.map(renderMachineItem)}
    +
    +
    + )} +
    + +
    +

    Empleados

    +
      + {employees.map((item) => ( +
    • + {item.name} {item.isAdmin ? "(admin)" : ""} +
    • + ))} +
    + {employee.isAdmin && ( +
    + setNewEmployeeName(event.target.value)} + className="rounded-xl border border-slate-300 px-3 py-2" + placeholder="Nombre" + /> + setNewEmployeePin(event.target.value)} + className="rounded-xl border border-slate-300 px-3 py-2" + placeholder="PIN 4 digitos" + /> + +
    + )} +
    + +
    +

    Serial / Relay

    +
    + + setSerialPath(event.target.value)} + className="rounded-xl border border-slate-300 px-3 py-2" + placeholder="Puerto" + /> + setSerialBaudRate(Number(event.target.value || 9600))} + className="rounded-xl border border-slate-300 px-3 py-2" + placeholder="BaudRate" + /> + +
    +
    + + {pricing && ( +
    +

    Variables de precio

    +

    Configuracion por categoria de servicio

    +
    +
    +

    Servicio 1: Autoservicio

    +
    + + + +
    +
    + +
    +

    Servicio 2: Encargo

    +
    + + +
    +
    + +
    +

    Servicio 3: XL

    +
    + + + + + +
    +
    + +
    +

    Tintoreria

    +
    + + +
    +
    + +
    +

    Add-ons

    +
    + + + +
    +
    + + +
    +
    +
    +
    + +
    +
    + )} + +
    +

    Base de clientes

    +
    + setCustomerQuery(event.target.value)} + className="w-full max-w-md rounded-xl border border-slate-300 px-3 py-2" + placeholder="Buscar por nombre, telefono o email" + /> + {customersLoading && Buscando...} +
    +
    + + + + + + + + + + + + + {customers.length === 0 && ( + + + + )} + {customers.map((customer) => ( + + + + + + + + + ))} + +
    ClienteTelefonoEmailTx validasSiguiente promoTotal gastado
    + Sin clientes para mostrar +
    + {customer.firstName} {customer.lastName} + {customer.phone}{customer.email || "-"}{customer.eligibleTransactionCount}Tx #{customer.nextDiscountTransactionNumber}{formatCurrency(customer.totalSpentCents)}
    +
    +
    +
    + ); +} diff --git a/src/components/pos/ShiftTab.tsx b/src/components/pos/ShiftTab.tsx new file mode 100644 index 0000000..475f90f --- /dev/null +++ b/src/components/pos/ShiftTab.tsx @@ -0,0 +1,161 @@ +"use client"; + +import { useState } from "react"; + +import { apiFetch } from "@/components/pos/api"; +import type { ActiveShiftPayload, Employee } from "@/components/pos/types"; +import { formatCurrency, formatDateTime } from "@/lib/format"; + +type ShiftTabProps = { + employee: Employee; + activeShift: ActiveShiftPayload; + onRefresh: () => Promise; + onError: (value: string) => void; +}; + +export function ShiftTab({ employee, activeShift, onRefresh, onError }: ShiftTabProps) { + const [startingCash, setStartingCash] = useState(0); + const [movementAmount, setMovementAmount] = useState(0); + const [movementReason, setMovementReason] = useState(""); + const [movementType, setMovementType] = useState<"deposit" | "withdrawal">("deposit"); + const [actualCash, setActualCash] = useState(0); + const [closing, setClosing] = useState(false); + + if (!activeShift.shift || !activeShift.summary) { + return ( +
    +

    Corte de Caja

    +

    No hay turno abierto.

    +
    + setStartingCash(Number(event.target.value || 0))} + className="rounded-xl border border-slate-300 px-4 py-3 text-xl" + /> + +
    +
    + ); + } + + return ( +
    +
    +

    Turno Activo

    +

    Inicio: {formatDateTime(activeShift.shift.startTime)}

    +
    +

    Ventas: {formatCurrency(activeShift.summary.totals.totalSalesCents)}

    +

    Transacciones: {activeShift.summary.totals.transactionCount}

    +

    Efectivo esperado: {formatCurrency(activeShift.summary.totals.expectedCashCents)}

    +
    +
    + +
    +

    Movimientos de Caja

    +
    + + setMovementAmount(Number(event.target.value || 0))} + className="rounded-xl border border-slate-300 px-4 py-3" + placeholder="Monto" + /> + setMovementReason(event.target.value)} + className="rounded-xl border border-slate-300 px-4 py-3" + placeholder="Motivo" + /> + +
    +
    + +
    +

    Cerrar Turno

    +
    + setActualCash(Number(event.target.value || 0))} + className="rounded-xl border border-slate-300 px-4 py-3 text-xl" + placeholder="Efectivo contado" + /> + +
    +
    +
    + ); +} diff --git a/src/components/pos/api.ts b/src/components/pos/api.ts new file mode 100644 index 0000000..bdfe791 --- /dev/null +++ b/src/components/pos/api.ts @@ -0,0 +1,34 @@ +export async function apiFetch(url: string, init?: RequestInit): Promise { + const response = await fetch(url, { + ...init, + headers: { + "Content-Type": "application/json", + ...(init?.headers ?? {}) + } + }); + + let data: unknown = null; + const contentType = response.headers.get("content-type") ?? ""; + + if (contentType.includes("application/json")) { + try { + data = await response.json(); + } catch { + data = null; + } + } else { + const text = await response.text(); + data = text.length > 0 ? text : null; + } + + if (!response.ok) { + if (data && typeof data === "object" && "error" in data) { + throw new Error(String((data as { error: unknown }).error)); + } + if (typeof data === "string" && data.length > 0) { + throw new Error(data); + } + throw new Error(`Error de API (${response.status})`); + } + return data as T; +} diff --git a/src/components/pos/modals/ActivateModal.tsx b/src/components/pos/modals/ActivateModal.tsx new file mode 100644 index 0000000..48e5032 --- /dev/null +++ b/src/components/pos/modals/ActivateModal.tsx @@ -0,0 +1,461 @@ +"use client"; + +import { useEffect, useMemo, useState } from "react"; + +import { apiFetch } from "@/components/pos/api"; +import type { CustomerRecord, LoyaltyRule, Machine, PricingVariables, ServiceType } from "@/components/pos/types"; + +type ActivateModalProps = { + machine: Machine; + onCancel: () => void; + onConfirm: ( + machine: Machine, + form: { + customerId: string; + customerName: string; + baseAmountCents: number; + durationMinutes: number; + serviceType: ServiceType; + paymentMethod: "cash" | "card" | "transfer"; + addons: { + detergentQty: number; + softenerQty: number; + bleachQty: number; + }; + } + ) => Promise; +}; + +type CustomersPayload = { + customers: CustomerRecord[]; + loyalty: LoyaltyRule; +}; + +const serviceLabels: Record = { + autoservicio: "Autoservicio", + encargo: "Encargo", + xl: "XL" +}; + +function money(cents: number) { + return `$${(cents / 100).toFixed(2)}`; +} + +export function ActivateModal({ machine, onCancel, onConfirm }: ActivateModalProps) { + const [baseAmountCents, setBaseAmountCents] = useState(machine.defaultPriceCents); + const [durationMinutes] = useState(machine.defaultDurationMinutes); + const [serviceType, setServiceType] = useState("autoservicio"); + const [paymentMethod, setPaymentMethod] = useState<"cash" | "card" | "transfer">("cash"); + const [submitting, setSubmitting] = useState(false); + const [pricing, setPricing] = useState(null); + + const [customerQuery, setCustomerQuery] = useState(""); + const [customers, setCustomers] = useState([]); + const [selectedCustomer, setSelectedCustomer] = useState(null); + const [customerLoading, setCustomerLoading] = useState(false); + const [customerError, setCustomerError] = useState(null); + const [creatingCustomer, setCreatingCustomer] = useState(false); + const [newCustomerFirstName, setNewCustomerFirstName] = useState(""); + const [newCustomerLastName, setNewCustomerLastName] = useState(""); + const [newCustomerPhone, setNewCustomerPhone] = useState(""); + const [newCustomerEmail, setNewCustomerEmail] = useState(""); + const [loyaltyRule, setLoyaltyRule] = useState({ + everyNTransactions: 10, + discountPct: 50 + }); + + const [encargoWeightKg, setEncargoWeightKg] = useState(0); + const [xlItems, setXlItems] = useState({ + individual: 0, + matrimonial: 0, + king: 0, + cobija: 0, + almohadaPar: 0 + }); + const [addons, setAddons] = useState({ + detergentQty: 0, + softenerQty: 0, + bleachQty: 0 + }); + + useEffect(() => { + apiFetch<{ pricing: PricingVariables }>("/api/settings/pricing") + .then((payload) => { + setPricing(payload.pricing); + setLoyaltyRule({ + everyNTransactions: payload.pricing.loyaltyEveryNTransactions, + discountPct: payload.pricing.loyaltyDiscountPct + }); + }) + .catch(() => undefined); + }, []); + + useEffect(() => { + const id = window.setTimeout(() => { + setCustomerLoading(true); + setCustomerError(null); + apiFetch(`/api/customers?limit=20&query=${encodeURIComponent(customerQuery.trim())}`) + .then((payload) => { + setCustomers(payload.customers); + setLoyaltyRule(payload.loyalty); + }) + .catch((error) => { + setCustomerError(error instanceof Error ? error.message : "No fue posible buscar clientes"); + }) + .finally(() => setCustomerLoading(false)); + }, 220); + + return () => window.clearTimeout(id); + }, [customerQuery]); + + const xlTotal = useMemo(() => { + if (!pricing) { + return 0; + } + return ( + xlItems.individual * pricing.xlEdredonIndividualCents + + xlItems.matrimonial * pricing.xlEdredonMatrimonialCents + + xlItems.king * pricing.xlEdredonKingCents + + xlItems.cobija * pricing.xlCobijaGruesaCents + + xlItems.almohadaPar * pricing.xlAlmohadaParCents + ); + }, [pricing, xlItems]); + + const addonTotalCents = useMemo(() => { + if (!pricing) { + return 0; + } + + return ( + addons.detergentQty * pricing.detergentAddonCents + + addons.softenerQty * pricing.softenerAddonCents + + addons.bleachQty * pricing.bleachAddonCents + ); + }, [addons, pricing]); + + const nextTransactionNumber = selectedCustomer ? selectedCustomer.eligibleTransactionCount + 1 : null; + const loyaltyEvery = Math.max(1, loyaltyRule.everyNTransactions); + const loyaltyDiscountPct = Math.max(0, Math.min(100, loyaltyRule.discountPct)); + const loyaltyApplies = nextTransactionNumber !== null && nextTransactionNumber % loyaltyEvery === 0; + const loyaltyDiscountPreviewCents = loyaltyApplies ? Math.round((baseAmountCents * loyaltyDiscountPct) / 100) : 0; + const finalTotalPreviewCents = Math.max(0, baseAmountCents - loyaltyDiscountPreviewCents + addonTotalCents); + + const registerCustomer = async () => { + setCreatingCustomer(true); + setCustomerError(null); + try { + const payload = await apiFetch<{ customer: CustomerRecord | null; loyalty: LoyaltyRule }>("/api/customers", { + method: "POST", + body: JSON.stringify({ + firstName: newCustomerFirstName, + lastName: newCustomerLastName, + phone: newCustomerPhone, + email: newCustomerEmail.trim().length > 0 ? newCustomerEmail : undefined + }) + }); + + if (!payload.customer) { + throw new Error("No fue posible recuperar cliente nuevo"); + } + + setLoyaltyRule(payload.loyalty); + setSelectedCustomer(payload.customer); + setCustomerQuery(`${payload.customer.firstName} ${payload.customer.lastName}`.trim()); + setNewCustomerFirstName(""); + setNewCustomerLastName(""); + setNewCustomerPhone(""); + setNewCustomerEmail(""); + } catch (error) { + setCustomerError(error instanceof Error ? error.message : "No fue posible registrar cliente"); + } finally { + setCreatingCustomer(false); + } + }; + + const incrementAddon = (key: "detergentQty" | "softenerQty" | "bleachQty") => { + setAddons((current) => ({ + ...current, + [key]: current[key] + 1 + })); + }; + + const decrementAddon = (key: "detergentQty" | "softenerQty" | "bleachQty") => { + setAddons((current) => ({ + ...current, + [key]: Math.max(0, current[key] - 1) + })); + }; + + const resetAddons = () => { + setAddons({ + detergentQty: 0, + softenerQty: 0, + bleachQty: 0 + }); + }; + + return ( +
    +
    +

    {machine.name}

    +

    Activacion con ticket y cliente

    + +
    +
    +
    +

    Cliente obligatorio

    + setCustomerQuery(event.target.value)} + className="mt-2 w-full rounded-lg border border-slate-300 px-3 py-2" + placeholder="Buscar por nombre, telefono o email" + /> + {customerLoading &&

    Buscando...

    } +
    + {customers.length === 0 &&

    Sin resultados

    } + {customers.map((customer) => ( + + ))} +
    + {selectedCustomer && ( +
    + Cliente seleccionado: {selectedCustomer.firstName} {selectedCustomer.lastName} ({selectedCustomer.phone}) +
    + )} +
    + +
    + Registrar cliente nuevo +
    + setNewCustomerFirstName(event.target.value)} + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Nombre" + /> + setNewCustomerLastName(event.target.value)} + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Apellido" + /> + setNewCustomerPhone(event.target.value)} + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Telefono" + /> + setNewCustomerEmail(event.target.value)} + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Email (opcional)" + /> +
    + +
    + + {customerError &&

    {customerError}

    } +
    + +
    +
    +

    Tipo de servicio

    +
    + {(["autoservicio", "encargo", "xl"] as ServiceType[]).map((option) => ( + + ))} +
    +
    + + {pricing && serviceType === "encargo" && ( +
    +

    Calculadora encargo

    +
    + setEncargoWeightKg(Number(event.target.value || 0))} + className="rounded-lg border border-slate-300 px-3 py-2" + placeholder="Peso (kg)" + /> + +
    +
    + )} + + {pricing && serviceType === "xl" && ( +
    +

    Items XL

    +
    + + + + + + +
    + +
    + )} + +
    +
    +

    Add-ons

    + +
    +
    +
    + +
    + + x{addons.detergentQty} + {money(addons.detergentQty * (pricing?.detergentAddonCents ?? 0))} +
    +
    +
    + +
    + + x{addons.softenerQty} + {money(addons.softenerQty * (pricing?.softenerAddonCents ?? 0))} +
    +
    +
    + +
    + + x{addons.bleachQty} + {money(addons.bleachQty * (pricing?.bleachAddonCents ?? 0))} +
    +
    +
    +
    + +
    +

    Configuracion del ticket

    +
    +
    +

    Servicio

    +

    {serviceLabels[serviceType]}

    +
    +
    +

    Precio base configurado

    +

    {money(baseAmountCents)}

    +
    +
    +

    Duracion configurada

    +

    {durationMinutes} min

    +
    +
    + +
    +
    +
    + +
    +
    +

    Servicio: {serviceLabels[serviceType]}

    +

    Base: {money(baseAmountCents)}

    +

    Lealtad: -{money(loyaltyDiscountPreviewCents)}

    +

    Add-ons: +{money(addonTotalCents)}

    +

    Total: {money(finalTotalPreviewCents)}

    +
    + {selectedCustomer && loyaltyApplies && ( +

    Descuento de lealtad aplicado (Tx #{nextTransactionNumber}, {loyaltyDiscountPct}% off).

    + )} +
    + + +
    +
    +
    +
    + ); +} diff --git a/src/components/pos/modals/ChangePinModal.tsx b/src/components/pos/modals/ChangePinModal.tsx new file mode 100644 index 0000000..4016fcd --- /dev/null +++ b/src/components/pos/modals/ChangePinModal.tsx @@ -0,0 +1,103 @@ +"use client"; + +import { useState } from "react"; + +import { apiFetch } from "@/components/pos/api"; +import type { Employee } from "@/components/pos/types"; + +type ChangePinModalProps = { + employee: Employee; + onClose: () => void; + onSuccess: (newPin: string) => void; + onError: (message: string) => void; +}; + +function sanitizePin(value: string) { + return value.replace(/\D/g, "").slice(0, 4); +} + +export function ChangePinModal({ employee, onClose, onSuccess, onError }: ChangePinModalProps) { + const [currentPin, setCurrentPin] = useState(""); + const [newPin, setNewPin] = useState(""); + const [confirmPin, setConfirmPin] = useState(""); + const [saving, setSaving] = useState(false); + + return ( +
    +
    +

    Cambiar PIN

    +

    {employee.name}

    +
    + setCurrentPin(sanitizePin(event.target.value))} + className="rounded-xl border border-slate-300 px-4 py-3" + placeholder="PIN actual" + /> + setNewPin(sanitizePin(event.target.value))} + className="rounded-xl border border-slate-300 px-4 py-3" + placeholder="PIN nuevo" + /> + setConfirmPin(sanitizePin(event.target.value))} + className="rounded-xl border border-slate-300 px-4 py-3" + placeholder="Confirmar PIN nuevo" + /> +
    +
    + + +
    +
    +
    + ); +} diff --git a/src/components/pos/modals/RunningModal.tsx b/src/components/pos/modals/RunningModal.tsx new file mode 100644 index 0000000..70417ee --- /dev/null +++ b/src/components/pos/modals/RunningModal.tsx @@ -0,0 +1,78 @@ +"use client"; + +import { useState } from "react"; + +import { formatCurrency, formatDateTime } from "@/lib/format"; +import type { Machine } from "@/components/pos/types"; + +type RunningModalProps = { + machine: Machine; + onCancel: () => void; + onAddTime: (transactionId: string, extraMinutes: number, extraAmountCents: number) => Promise; +}; + +export function RunningModal({ machine, onCancel, onAddTime }: RunningModalProps) { + const [extraMinutes, setExtraMinutes] = useState(10); + const [extraAmount, setExtraAmount] = useState(20); + const [submitting, setSubmitting] = useState(false); + if (!machine.transaction) { + return null; + } + + return ( +
    +
    +

    {machine.name}

    +

    Ticket #{machine.transaction.ticketNumber}

    +

    Cliente: {machine.transaction.customerName}

    +

    Inicio: {formatDateTime(machine.transaction.startedAt)}

    +

    Fin esperado: {formatDateTime(machine.transaction.expectedEndAt)}

    +

    Importe: {formatCurrency(machine.transaction.amountCents)}

    + {machine.transaction.loyaltyDiscountApplied && ( +

    Incluye descuento de lealtad

    + )} +
    + + +
    +
    + + +
    +
    +
    + ); +} diff --git a/src/components/pos/modals/TicketPreviewModal.tsx b/src/components/pos/modals/TicketPreviewModal.tsx new file mode 100644 index 0000000..1de21a8 --- /dev/null +++ b/src/components/pos/modals/TicketPreviewModal.tsx @@ -0,0 +1,228 @@ +"use client"; + +import { useMemo, useState } from "react"; + +import type { TicketPreviewData } from "@/components/pos/types"; +import { APP_DEFAULTS } from "@/lib/config"; +import { formatCurrency } from "@/lib/format"; + +type TicketPreviewModalProps = { + ticket: TicketPreviewData; + onClose: () => void; +}; + +const serviceLabels: Record = { + autoservicio: "Autoservicio", + encargo: "Encargo", + xl: "XL" +}; + +const paymentLabels: Record = { + cash: "Efectivo", + card: "Tarjeta", + transfer: "Transferencia" +}; + +function escapeHtml(value: string) { + return value + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +} + +export function TicketPreviewModal({ ticket, onClose }: TicketPreviewModalProps) { + const [shareStatus, setShareStatus] = useState(null); + const ticketDate = useMemo(() => new Date(ticket.dateTimeIso), [ticket.dateTimeIso]); + + const dateLabel = useMemo( + () => + new Intl.DateTimeFormat(APP_DEFAULTS.locale, { + dateStyle: "medium", + timeZone: APP_DEFAULTS.timezone + }).format(ticketDate), + [ticketDate] + ); + + const timeLabel = useMemo( + () => + new Intl.DateTimeFormat(APP_DEFAULTS.locale, { + timeStyle: "short", + timeZone: APP_DEFAULTS.timezone + }).format(ticketDate), + [ticketDate] + ); + + const addonLines = useMemo( + () => [ + { label: "Detergente", qty: ticket.addons.detergentQty }, + { label: "Suavizante", qty: ticket.addons.softenerQty }, + { label: "Cloro", qty: ticket.addons.bleachQty } + ].filter((line) => line.qty > 0), + [ticket.addons] + ); + + const ticketText = useMemo(() => { + const lines: string[] = []; + lines.push("LA BURBUJA POS"); + lines.push("------------------------------"); + lines.push(`TICKET #${ticket.ticketNumber}`); + lines.push("------------------------------"); + lines.push(`Cliente: ${ticket.customerName}`); + lines.push(`Servicio: ${serviceLabels[ticket.serviceType]}`); + lines.push(`Pago: ${paymentLabels[ticket.paymentMethod]}`); + lines.push(`Cajero: ${ticket.cashierName}`); + lines.push(`Fecha: ${dateLabel}`); + lines.push(`Hora: ${timeLabel}`); + lines.push("------------------------------"); + lines.push("ADD-ONS"); + if (addonLines.length === 0) { + lines.push("Sin add-ons"); + } else { + for (const line of addonLines) { + lines.push(`${line.label}: x${line.qty}`); + } + } + lines.push("------------------------------"); + lines.push(`Lealtad: ${ticket.loyaltyApplied ? `Si (-${formatCurrency(ticket.discountCents)})` : "No"}`); + lines.push(`Subtotal: ${formatCurrency(ticket.subtotalCents)}`); + lines.push(`IVA 16%: ${formatCurrency(ticket.ivaCents)}`); + lines.push(`TOTAL: ${formatCurrency(ticket.totalCents)}`); + return lines.join("\n"); + }, [addonLines, dateLabel, timeLabel, ticket]); + + const handlePrint = () => { + const popup = window.open("", "_blank", "width=420,height=680"); + if (!popup) { + setShareStatus("No se pudo abrir ventana de impresion."); + return; + } + + const safeText = escapeHtml(ticketText).replaceAll("\n", "
    "); + popup.document.write(` + + + Ticket #${ticket.ticketNumber} + + + +
    +
    #${ticket.ticketNumber}
    +
    ${safeText}
    +
    + + + `); + popup.document.close(); + popup.focus(); + popup.print(); + popup.close(); + }; + + const handleShare = async () => { + setShareStatus(null); + + try { + const nav = window.navigator; + if (typeof nav.share === "function") { + await nav.share({ + title: `Ticket #${ticket.ticketNumber}`, + text: ticketText + }); + return; + } + + if (nav.clipboard?.writeText) { + await nav.clipboard.writeText(ticketText); + } else { + throw new Error("Clipboard no disponible"); + } + setShareStatus("Ticket copiado al portapapeles."); + } catch { + setShareStatus("No se pudo compartir el ticket."); + } + }; + + return ( +
    +
    +

    Vista previa ticket

    +

    #{ticket.ticketNumber}

    + +
    +
    + Cliente: + {ticket.customerName} +
    +
    + Servicio: + {serviceLabels[ticket.serviceType]} +
    +
    + Cajero: + {ticket.cashierName} +
    +
    +

    Fecha: {dateLabel}

    +

    Hora: {timeLabel}

    +
    + +
    +

    Add-ons

    + {addonLines.length === 0 ? ( +

    Sin add-ons

    + ) : ( +
    + {addonLines.map((line) => ( +
    + {line.label} + x{line.qty} +
    + ))} +
    + )} +
    + +
    +
    + Lealtad aplicada + {ticket.loyaltyApplied ? `Si (-${formatCurrency(ticket.discountCents)})` : "No"} +
    +
    + Subtotal + {formatCurrency(ticket.subtotalCents)} +
    +
    + IVA (16%) + {formatCurrency(ticket.ivaCents)} +
    +
    + Total + {formatCurrency(ticket.totalCents)} +
    +
    +
    + + {!ticket.relayOk && ( +

    + Activacion registrada pero relay no confirmado. Revisa estado de la maquina. +

    + )} + + {shareStatus &&

    {shareStatus}

    } + +
    + + + +
    +
    +
    + ); +} diff --git a/src/components/pos/types.ts b/src/components/pos/types.ts new file mode 100644 index 0000000..41dba48 --- /dev/null +++ b/src/components/pos/types.ts @@ -0,0 +1,136 @@ +export type ServiceType = "autoservicio" | "encargo" | "xl"; + +export type Machine = { + id: string; + name: string; + type: "washer" | "dryer"; + relayChannel: number; + defaultPriceCents: number; + defaultDurationMinutes: number; + status: "available" | "running" | "out_of_service"; + transaction: { + id: string; + ticketNumber: number; + customerId: string; + customerName: string; + baseAmountCents: number; + discountCents: number; + loyaltyDiscountApplied: boolean; + addonDetergentQty: number; + addonSoftenerQty: number; + addonBleachQty: number; + addonAmountCents: number; + serviceType: ServiceType; + amountCents: number; + paymentMethod: "cash" | "card" | "transfer"; + startedAt: string; + expectedEndAt: string; + employeeId: string; + } | null; +}; + +export type CustomerRecord = { + id: string; + firstName: string; + lastName: string; + phone: string; + email: string | null; + createdAt: string; + updatedAt: string; + eligibleTransactionCount: number; + totalSpentCents: number; + nextDiscountTransactionNumber: number; + isNextTransactionDiscount: boolean; +}; + +export type LoyaltyRule = { + everyNTransactions: number; + discountPct: number; +}; + +export type RelayHealth = { + connected: boolean; + mode: "mock" | "serial"; + error?: string; +}; + +export type Employee = { + id: string; + name: string; + isAdmin: boolean; +}; + +export type ActiveShiftPayload = { + shift: { + id: string; + startTime: string; + startingCashCents: number; + } | null; + summary: { + totals: { + totalSalesCents: number; + expectedCashCents: number; + transactionCount: number; + byPaymentMethod: Array<{ paymentMethod: string; amountCents: number; count: number }>; + }; + } | null; +}; + +export type ReportSummary = { + totals: { + totalRevenueCents: number; + transactionCount: number; + avgTicketCents: number; + }; + byPaymentMethod: Array<{ paymentMethod: string; amountCents: number; count: number }>; + byMachine: Array<{ machineName: string; amountCents: number; count: number }>; +}; + +export type UtilizationRow = { + machineId: string; + machineName: string; + usedMinutes: number; + totalWindowMinutes: number; + utilizationPct: number; +}; + +export type PricingVariables = { + selfServiceWashPriceCents: number; + selfServiceDryPriceCents: number; + selfServiceCycleMinutes: number; + encargoPricePerKgCents: number; + encargoMinimumChargeCents: number; + xlEdredonIndividualCents: number; + xlEdredonMatrimonialCents: number; + xlEdredonKingCents: number; + xlCobijaGruesaCents: number; + xlAlmohadaParCents: number; + dryCleaningMinimumCents: number; + dryCleaningUrgentSurchargePct: number; + detergentAddonCents: number; + softenerAddonCents: number; + bleachAddonCents: number; + loyaltyEveryNTransactions: number; + loyaltyDiscountPct: number; +}; + +export type TicketPreviewData = { + ticketNumber: number; + customerName: string; + serviceType: ServiceType; + addons: { + detergentQty: number; + softenerQty: number; + bleachQty: number; + }; + loyaltyApplied: boolean; + discountCents: number; + subtotalCents: number; + ivaCents: number; + totalCents: number; + dateTimeIso: string; + cashierName: string; + machineName: string; + paymentMethod: "cash" | "card" | "transfer"; + relayOk: boolean; +}; diff --git a/src/lib/config.ts b/src/lib/config.ts new file mode 100644 index 0000000..9674e63 --- /dev/null +++ b/src/lib/config.ts @@ -0,0 +1,21 @@ +export const APP_DEFAULTS = { + timezone: "America/Monterrey", + currency: "MXN", + locale: "es-MX", + serialBaudRate: 9600, + serialPortPath: "COM3" +} as const; + +export function getNodeEnv(): "development" | "test" | "production" { + if (process.env.NODE_ENV === "production") { + return "production"; + } + if (process.env.NODE_ENV === "test") { + return "test"; + } + return "development"; +} + +export function nowDate() { + return new Date(); +} diff --git a/src/lib/db.ts b/src/lib/db.ts new file mode 100644 index 0000000..9d07cfc --- /dev/null +++ b/src/lib/db.ts @@ -0,0 +1,16 @@ +import { PrismaClient } from "@prisma/client"; + +declare global { + // eslint-disable-next-line no-var + var prismaGlobal: PrismaClient | undefined; +} + +export const prisma = + global.prismaGlobal ?? + new PrismaClient({ + log: process.env.NODE_ENV === "development" ? ["warn", "error"] : ["error"] + }); + +if (process.env.NODE_ENV !== "production") { + global.prismaGlobal = prisma; +} diff --git a/src/lib/format.ts b/src/lib/format.ts new file mode 100644 index 0000000..5ccafb4 --- /dev/null +++ b/src/lib/format.ts @@ -0,0 +1,36 @@ +import { APP_DEFAULTS } from "@/lib/config"; + +export function formatCurrency(cents: number, currency = APP_DEFAULTS.currency) { + return new Intl.NumberFormat(APP_DEFAULTS.locale, { + style: "currency", + currency, + minimumFractionDigits: 2 + }).format(cents / 100); +} + +export function formatDateTime(value: Date | string) { + const date = typeof value === "string" ? new Date(value) : value; + return new Intl.DateTimeFormat(APP_DEFAULTS.locale, { + dateStyle: "medium", + timeStyle: "short", + timeZone: APP_DEFAULTS.timezone + }).format(date); +} + +export function formatMinutes(minutes: number) { + const safe = Math.max(0, Math.floor(minutes)); + const hrs = Math.floor(safe / 60); + const mins = safe % 60; + if (hrs === 0) { + return `${mins} min`; + } + return `${hrs} h ${mins} min`; +} + +export function parseMoneyToCents(input: string | number) { + const value = typeof input === "number" ? input : Number.parseFloat(input); + if (!Number.isFinite(value)) { + return 0; + } + return Math.round(value * 100); +} diff --git a/src/lib/http.ts b/src/lib/http.ts new file mode 100644 index 0000000..4a21add --- /dev/null +++ b/src/lib/http.ts @@ -0,0 +1,15 @@ +import { NextResponse } from "next/server"; + +export function ok(data: T, status = 200) { + return NextResponse.json(data, { status }); +} + +export function fail(message: string, status = 400, detail?: unknown) { + return NextResponse.json( + { + error: message, + detail + }, + { status } + ); +} diff --git a/src/lib/logger.ts b/src/lib/logger.ts new file mode 100644 index 0000000..3cd0902 --- /dev/null +++ b/src/lib/logger.ts @@ -0,0 +1,21 @@ +type LogPayload = Record; + +function out(level: "info" | "warn" | "error", message: string, payload?: LogPayload) { + const stamp = new Date().toISOString(); + const line = payload ? `${stamp} [${level}] ${message} ${JSON.stringify(payload)}` : `${stamp} [${level}] ${message}`; + if (level === "error") { + console.error(line); + return; + } + if (level === "warn") { + console.warn(line); + return; + } + console.log(line); +} + +export const logger = { + info: (message: string, payload?: LogPayload) => out("info", message, payload), + warn: (message: string, payload?: LogPayload) => out("warn", message, payload), + error: (message: string, payload?: LogPayload) => out("error", message, payload) +}; diff --git a/src/lib/relay/mockRelayController.ts b/src/lib/relay/mockRelayController.ts new file mode 100644 index 0000000..1abe301 --- /dev/null +++ b/src/lib/relay/mockRelayController.ts @@ -0,0 +1,37 @@ +import "server-only"; + +import type { RelayController } from "@/lib/relay/types"; + +export class MockRelayController implements RelayController { + private connected = false; + private states = new Map(); + + async connect(): Promise { + this.connected = true; + } + + async turnOn(channel: number): Promise { + this.assertConnected(); + this.states.set(channel, true); + } + + async turnOff(channel: number): Promise { + this.assertConnected(); + this.states.set(channel, false); + } + + async getStatus(channel: number): Promise { + this.assertConnected(); + return this.states.get(channel) ?? false; + } + + async disconnect(): Promise { + this.connected = false; + } + + private assertConnected() { + if (!this.connected) { + throw new Error("Mock relay no conectado"); + } + } +} diff --git a/src/lib/relay/protocol.ts b/src/lib/relay/protocol.ts new file mode 100644 index 0000000..f48b61c --- /dev/null +++ b/src/lib/relay/protocol.ts @@ -0,0 +1,13 @@ +export type RelayProtocol = { + onCommand: (channel: number) => Buffer; + offCommand: (channel: number) => Buffer; +}; + +export const asciiRelayProtocol: RelayProtocol = { + onCommand(channel) { + return Buffer.from(`relay on ${channel + 1}\n`, "utf8"); + }, + offCommand(channel) { + return Buffer.from(`relay off ${channel + 1}\n`, "utf8"); + } +}; diff --git a/src/lib/relay/serialRelayController.ts b/src/lib/relay/serialRelayController.ts new file mode 100644 index 0000000..185ca79 --- /dev/null +++ b/src/lib/relay/serialRelayController.ts @@ -0,0 +1,91 @@ +import "server-only"; + +import { asciiRelayProtocol, type RelayProtocol } from "@/lib/relay/protocol"; +import type { RelayController } from "@/lib/relay/types"; + +export class SerialRelayController implements RelayController { + private serialPort: import("serialport").SerialPort | null = null; + + constructor(private readonly protocol: RelayProtocol = asciiRelayProtocol) {} + + async connect(port: string, baudRate: number): Promise { + const SerialPort = await this.getSerialPortCtor(); + if (this.serialPort?.isOpen) { + return; + } + this.serialPort = new SerialPort({ + path: port, + baudRate, + autoOpen: false + }); + await new Promise((resolve, reject) => { + this.serialPort?.open((error) => { + if (error) { + reject(error); + return; + } + resolve(); + }); + }); + } + + async turnOn(channel: number): Promise { + await this.write(this.protocol.onCommand(channel)); + } + + async turnOff(channel: number): Promise { + await this.write(this.protocol.offCommand(channel)); + } + + async getStatus(): Promise { + return this.serialPort?.isOpen ?? false; + } + + async disconnect(): Promise { + if (!this.serialPort?.isOpen) { + return; + } + await new Promise((resolve, reject) => { + this.serialPort?.close((error) => { + if (error) { + reject(error); + return; + } + resolve(); + }); + }); + this.serialPort = null; + } + + private async write(command: Buffer) { + const port = this.serialPort; + if (!port || !port.isOpen) { + throw new Error("Puerto serial no conectado"); + } + await new Promise((resolve, reject) => { + port.write(command, (error) => { + if (error) { + reject(error); + return; + } + port.drain((drainError) => { + if (drainError) { + reject(drainError); + return; + } + resolve(); + }); + }); + }); + } + + static async listPorts() { + const { SerialPort } = await import("serialport"); + return SerialPort.list(); + } + + private async getSerialPortCtor() { + const { SerialPort } = await import("serialport"); + return SerialPort; + } +} diff --git a/src/lib/relay/types.ts b/src/lib/relay/types.ts new file mode 100644 index 0000000..860bb6c --- /dev/null +++ b/src/lib/relay/types.ts @@ -0,0 +1,14 @@ +export interface RelayController { + connect(port: string, baudRate: number): Promise; + turnOn(channel: number): Promise; + turnOff(channel: number): Promise; + getStatus(channel: number): Promise; + disconnect(): Promise; +} + +export interface RelayHealth { + connected: boolean; + mode: "mock" | "serial"; + port?: string; + error?: string; +} diff --git a/src/lib/time.ts b/src/lib/time.ts new file mode 100644 index 0000000..4cb9a9f --- /dev/null +++ b/src/lib/time.ts @@ -0,0 +1,16 @@ +export function minutesBetween(start: Date, end: Date) { + return Math.max(0, (end.getTime() - start.getTime()) / 60_000); +} + +export function addMinutes(date: Date, minutes: number) { + return new Date(date.getTime() + minutes * 60_000); +} + +export function clampRange(start: Date, end: Date, rangeStart: Date, rangeEnd: Date) { + const clampedStart = new Date(Math.max(start.getTime(), rangeStart.getTime())); + const clampedEnd = new Date(Math.min(end.getTime(), rangeEnd.getTime())); + if (clampedEnd <= clampedStart) { + return null; + } + return { start: clampedStart, end: clampedEnd }; +} diff --git a/src/server/api/dateRange.ts b/src/server/api/dateRange.ts new file mode 100644 index 0000000..a9e4505 --- /dev/null +++ b/src/server/api/dateRange.ts @@ -0,0 +1,21 @@ +export function parseDateRange(params: URLSearchParams) { + const fromRaw = params.get("from"); + const toRaw = params.get("to"); + const now = new Date(); + + if (!fromRaw || !toRaw) { + const start = new Date(now); + start.setHours(0, 0, 0, 0); + return { from: start, to: now }; + } + + const from = new Date(fromRaw); + const to = new Date(toRaw); + if (Number.isNaN(from.getTime()) || Number.isNaN(to.getTime())) { + throw new Error("Rango de fechas invalido"); + } + if (to < from) { + throw new Error("Rango de fechas invalido"); + } + return { from, to }; +} diff --git a/src/server/domain/constants.ts b/src/server/domain/constants.ts new file mode 100644 index 0000000..9351ae9 --- /dev/null +++ b/src/server/domain/constants.ts @@ -0,0 +1,34 @@ +export const MACHINE_TYPES = { + washer: "washer", + dryer: "dryer" +} as const; + +export const PAYMENT_METHODS = { + cash: "cash", + card: "card", + transfer: "transfer" +} as const; + +export const SERVICE_TYPES = { + autoservicio: "autoservicio", + encargo: "encargo", + xl: "xl" +} as const; + +export const TRANSACTION_STATUS = { + pendingRelay: "pending_relay", + running: "running", + completed: "completed", + relayFailed: "relay_failed", + voided: "voided" +} as const; + +export const CASH_MOVEMENT_TYPE = { + deposit: "deposit", + withdrawal: "withdrawal" +} as const; + +export type PaymentMethodValue = (typeof PAYMENT_METHODS)[keyof typeof PAYMENT_METHODS]; +export type ServiceTypeValue = (typeof SERVICE_TYPES)[keyof typeof SERVICE_TYPES]; +export type TransactionStatusValue = (typeof TRANSACTION_STATUS)[keyof typeof TRANSACTION_STATUS]; +export type CashMovementTypeValue = (typeof CASH_MOVEMENT_TYPE)[keyof typeof CASH_MOVEMENT_TYPE]; diff --git a/src/server/relay/relayManager.ts b/src/server/relay/relayManager.ts new file mode 100644 index 0000000..48ce708 --- /dev/null +++ b/src/server/relay/relayManager.ts @@ -0,0 +1,152 @@ +import "server-only"; + +import { APP_DEFAULTS } from "@/lib/config"; +import { prisma } from "@/lib/db"; +import { logger } from "@/lib/logger"; +import { MockRelayController } from "@/lib/relay/mockRelayController"; +import { SerialRelayController } from "@/lib/relay/serialRelayController"; +import type { RelayController, RelayHealth } from "@/lib/relay/types"; + +class RelayManager { + private controller: RelayController | null = null; + private health: RelayHealth = { + connected: false, + mode: "mock" + }; + private initialized = false; + + async init() { + if (this.initialized) { + return; + } + await this.reloadFromConfig(); + this.initialized = true; + } + + async reloadFromConfig() { + const config = await prisma.appConfig.upsert({ + where: { id: 1 }, + update: {}, + create: { + id: 1, + businessName: "La Burbuja" + } + }); + await this.connectWithSettings(config.relayMockMode, config.serialPortPath, config.serialBaudRate); + } + + async connectWithSettings(mockMode: boolean, port: string, baudRate: number) { + if (this.controller) { + try { + await this.controller.disconnect(); + } catch (error) { + logger.warn("Error al cerrar relay previo", { error: String(error) }); + } + } + + this.controller = mockMode ? new MockRelayController() : new SerialRelayController(); + this.health = { + connected: false, + mode: mockMode ? "mock" : "serial", + port + }; + + try { + await this.controller.connect(port, baudRate || APP_DEFAULTS.serialBaudRate); + this.health.connected = true; + this.health.error = undefined; + await prisma.appConfig.update({ + where: { id: 1 }, + data: { + relayConnected: true, + relayMockMode: mockMode, + serialPortPath: port, + serialBaudRate: baudRate || APP_DEFAULTS.serialBaudRate + } + }); + logger.info("Relay conectado", { mode: this.health.mode, port }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + this.health.connected = false; + this.health.error = message; + await prisma.appConfig.update({ + where: { id: 1 }, + data: { + relayConnected: false, + relayMockMode: mockMode, + serialPortPath: port, + serialBaudRate: baudRate || APP_DEFAULTS.serialBaudRate + } + }); + logger.error("Fallo conexion relay", { message, mode: this.health.mode, port }); + } + } + + async turnOn(channel: number) { + await this.init(); + if (!this.controller) { + throw new Error("Relay no inicializado"); + } + try { + await this.controller.turnOn(channel); + } catch (error) { + this.health.connected = false; + this.health.error = error instanceof Error ? error.message : String(error); + throw error; + } + } + + async turnOff(channel: number) { + await this.init(); + if (!this.controller) { + throw new Error("Relay no inicializado"); + } + try { + await this.controller.turnOff(channel); + } catch (error) { + this.health.connected = false; + this.health.error = error instanceof Error ? error.message : String(error); + throw error; + } + } + + async getChannelStatus(channel: number) { + await this.init(); + if (!this.controller) { + return false; + } + return this.controller.getStatus(channel); + } + + async reconnect() { + this.initialized = false; + await this.init(); + } + + async getHealth() { + await this.init(); + return this.health; + } + + async listSerialPorts() { + try { + return await SerialRelayController.listPorts(); + } catch (error) { + logger.warn("No se pudieron listar puertos seriales", { + error: String(error) + }); + return []; + } + } +} + +declare global { + // eslint-disable-next-line no-var + var relayManagerGlobal: RelayManager | undefined; +} + +export const relayManager = global.relayManagerGlobal ?? new RelayManager(); + +if (process.env.NODE_ENV !== "production") { + global.relayManagerGlobal = relayManager; +} diff --git a/src/server/services/activationService.ts b/src/server/services/activationService.ts new file mode 100644 index 0000000..44547bb --- /dev/null +++ b/src/server/services/activationService.ts @@ -0,0 +1,307 @@ +import "server-only"; + +import { addMinutes } from "@/lib/time"; +import { prisma } from "@/lib/db"; +import { TRANSACTION_STATUS, type PaymentMethodValue, type ServiceTypeValue } from "@/server/domain/constants"; +import { relayManager } from "@/server/relay/relayManager"; +import { calculateAddonTotalCents, calculateLoyaltyDiscountCents } from "@/server/services/calculations"; +import { timerService } from "@/server/services/timerService"; + +type ActivateMachineAddonsInput = { + detergentQty: number; + softenerQty: number; + bleachQty: number; +}; + +export type ActivateMachineInput = { + machineId: string; + employeeId: string; + customerId: string; + baseAmountCents: number; + durationMinutes: number; + serviceType: ServiceTypeValue; + paymentMethod: PaymentMethodValue; + addons: ActivateMachineAddonsInput; +}; + +export async function activateMachine(input: ActivateMachineInput) { + const startedAt = new Date(); + const expectedEndAt = addMinutes(startedAt, input.durationMinutes); + + const { machineRelayChannel, transaction } = await prisma.$transaction(async (tx) => { + const machine = await tx.machine.findUnique({ + where: { id: input.machineId }, + include: { + transactions: { + where: { + status: { + in: [TRANSACTION_STATUS.running, TRANSACTION_STATUS.pendingRelay] + } + }, + take: 1 + } + } + }); + + if (!machine || !machine.isActive) { + throw new Error("Maquina no disponible"); + } + + if (machine.outOfService) { + throw new Error("Maquina fuera de servicio"); + } + + if (machine.transactions.length > 0) { + throw new Error("Maquina actualmente en uso"); + } + + const customer = await tx.customer.findUnique({ + where: { id: input.customerId }, + select: { id: true, isActive: true } + }); + + if (!customer || !customer.isActive) { + throw new Error("Cliente no disponible"); + } + + const config = await tx.appConfig.findUnique({ + where: { id: 1 }, + select: { + loyaltyEveryNTransactions: true, + loyaltyDiscountPct: true, + detergentAddonCents: true, + softenerAddonCents: true, + bleachAddonCents: true + } + }); + + if (!config) { + throw new Error("Configuracion no disponible"); + } + + const priorEligibleTransactions = await tx.transaction.count({ + where: { + customerId: input.customerId, + status: { + in: [TRANSACTION_STATUS.pendingRelay, TRANSACTION_STATUS.running, TRANSACTION_STATUS.completed] + } + } + }); + + const customerTransactionNumber = priorEligibleTransactions + 1; + const loyaltyEveryNTransactions = Math.max(1, config.loyaltyEveryNTransactions); + const loyaltyDiscountPct = Math.max(0, Math.min(100, config.loyaltyDiscountPct)); + const loyaltyDiscountApplied = + loyaltyDiscountPct > 0 && customerTransactionNumber % loyaltyEveryNTransactions === 0; + + const discountCents = loyaltyDiscountApplied + ? calculateLoyaltyDiscountCents(input.baseAmountCents, loyaltyDiscountPct) + : 0; + const addonAmountCents = calculateAddonTotalCents({ + detergentQty: input.addons.detergentQty, + softenerQty: input.addons.softenerQty, + bleachQty: input.addons.bleachQty, + detergentAddonCents: config.detergentAddonCents, + softenerAddonCents: config.softenerAddonCents, + bleachAddonCents: config.bleachAddonCents + }); + + const amountCents = Math.max(0, input.baseAmountCents - discountCents + addonAmountCents); + + const ticketAgg = await tx.transaction.aggregate({ + _max: { ticketNumber: true } + }); + const ticketNumber = (ticketAgg._max.ticketNumber ?? 0) + 1; + + const transaction = await tx.transaction.create({ + data: { + ticketNumber, + machineId: input.machineId, + employeeId: input.employeeId, + customerId: input.customerId, + baseAmountCents: input.baseAmountCents, + discountCents, + loyaltyDiscountApplied, + addonDetergentQty: input.addons.detergentQty, + addonSoftenerQty: input.addons.softenerQty, + addonBleachQty: input.addons.bleachQty, + addonAmountCents, + serviceType: input.serviceType, + amountCents, + paymentMethod: input.paymentMethod, + startedAt, + expectedEndAt, + status: TRANSACTION_STATUS.pendingRelay + } + }); + + return { + machineRelayChannel: machine.relayChannel, + transaction + }; + }); + + await prisma.transaction.update({ + where: { id: transaction.id }, + data: { relayOnAttemptedAt: new Date() } + }); + + try { + await relayManager.turnOn(machineRelayChannel); + const updated = await prisma.transaction.update({ + where: { id: transaction.id }, + data: { + status: TRANSACTION_STATUS.running, + relayTurnedOnAt: new Date(), + relayFailureReason: null + }, + include: { + customer: { + select: { firstName: true, lastName: true, phone: true } + }, + employee: { + select: { name: true } + }, + machine: { + select: { name: true } + } + } + }); + timerService.scheduleExpiry(updated.id, updated.expectedEndAt); + return { + transaction: updated, + relayOk: true + }; + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + const updated = await prisma.transaction.update({ + where: { id: transaction.id }, + data: { + status: TRANSACTION_STATUS.relayFailed, + relayFailureReason: message + }, + include: { + customer: { + select: { firstName: true, lastName: true, phone: true } + }, + employee: { + select: { name: true } + }, + machine: { + select: { name: true } + } + } + }); + return { + transaction: updated, + relayOk: false, + relayError: message + }; + } +} + +export async function retryRelayOn(transactionId: string) { + const transaction = await prisma.transaction.findUnique({ + where: { id: transactionId }, + include: { machine: true } + }); + + if (!transaction) { + throw new Error("Transaccion no encontrada"); + } + + const retryableStatuses = new Set([TRANSACTION_STATUS.relayFailed, TRANSACTION_STATUS.pendingRelay]); + if (!retryableStatuses.has(transaction.status)) { + throw new Error("Transaccion no elegible para reintento"); + } + + await prisma.transaction.update({ + where: { id: transaction.id }, + data: { relayOnAttemptedAt: new Date() } + }); + + await relayManager.turnOn(transaction.machine.relayChannel); + const updated = await prisma.transaction.update({ + where: { id: transaction.id }, + data: { + status: TRANSACTION_STATUS.running, + relayTurnedOnAt: new Date(), + relayFailureReason: null + } + }); + timerService.scheduleExpiry(updated.id, updated.expectedEndAt); + return updated; +} + +export async function addTimeToTransaction(input: { + transactionId: string; + employeeId: string; + extraMinutes: number; + extraAmountCents: number; + reason?: string; +}) { + const transaction = await prisma.transaction.findUnique({ + where: { id: input.transactionId } + }); + + if (!transaction) { + throw new Error("Transaccion no encontrada"); + } + + if (transaction.status !== TRANSACTION_STATUS.running) { + throw new Error("Solo se puede agregar tiempo a transacciones activas"); + } + + const nextEnd = addMinutes(transaction.expectedEndAt, input.extraMinutes); + const updated = await prisma.transaction.update({ + where: { id: transaction.id }, + data: { + expectedEndAt: nextEnd, + amountCents: transaction.amountCents + input.extraAmountCents, + baseAmountCents: transaction.baseAmountCents + input.extraAmountCents + } + }); + + await prisma.transactionExtension.create({ + data: { + transactionId: transaction.id, + employeeId: input.employeeId, + extraMinutes: input.extraMinutes, + extraAmountCents: input.extraAmountCents, + reason: input.reason + } + }); + + timerService.scheduleExpiry(updated.id, updated.expectedEndAt); + return updated; +} + +export async function voidTransaction(input: { transactionId: string; reason: string }) { + const transaction = await prisma.transaction.findUnique({ + where: { id: input.transactionId }, + include: { machine: true } + }); + + if (!transaction) { + throw new Error("Transaccion no encontrada"); + } + + if (transaction.status === TRANSACTION_STATUS.voided) { + return transaction; + } + + if (transaction.status === TRANSACTION_STATUS.running) { + await relayManager.turnOff(transaction.machine.relayChannel); + } + timerService.unschedule(transaction.id); + + return prisma.transaction.update({ + where: { id: transaction.id }, + data: { + status: TRANSACTION_STATUS.voided, + voidReason: input.reason, + endedAt: new Date(), + relayTurnedOffAt: new Date() + } + }); +} diff --git a/src/server/services/authService.ts b/src/server/services/authService.ts new file mode 100644 index 0000000..e4078ec --- /dev/null +++ b/src/server/services/authService.ts @@ -0,0 +1,34 @@ +import "server-only"; + +import { prisma } from "@/lib/db"; + +export async function loginWithPin(pin: string) { + const employee = await prisma.employee.findFirst({ + where: { + pin, + isActive: true + } + }); + + if (!employee) { + throw new Error("PIN invalido"); + } + + return employee; +} + +export function getAdminPinFromRequest(request: Request) { + return request.headers.get("x-admin-pin")?.trim() ?? ""; +} + +export async function requireAdminFromRequest(request: Request) { + const pin = getAdminPinFromRequest(request); + if (!pin || pin.length !== 4) { + throw new Error("PIN de administrador requerido"); + } + const employee = await loginWithPin(pin); + if (!employee.isAdmin) { + throw new Error("Permiso denegado: solo administrador"); + } + return employee; +} diff --git a/src/server/services/calculations.ts b/src/server/services/calculations.ts new file mode 100644 index 0000000..b65ace5 --- /dev/null +++ b/src/server/services/calculations.ts @@ -0,0 +1,38 @@ +export function calculateExpectedCash(input: { + startingCashCents: number; + cashSalesCents: number; + depositsCents: number; + withdrawalsCents: number; +}) { + return input.startingCashCents + input.cashSalesCents + input.depositsCents - input.withdrawalsCents; +} + +export function calculateUtilizationPct(usedMinutes: number, totalWindowMinutes: number) { + if (totalWindowMinutes <= 0) { + return 0; + } + return Number(((usedMinutes / totalWindowMinutes) * 100).toFixed(2)); +} + +export function calculateLoyaltyDiscountCents(baseAmountCents: number, discountPct: number) { + if (baseAmountCents <= 0 || discountPct <= 0) { + return 0; + } + const boundedPct = Math.min(100, Math.max(0, discountPct)); + return Math.round((baseAmountCents * boundedPct) / 100); +} + +export function calculateAddonTotalCents(input: { + detergentQty: number; + softenerQty: number; + bleachQty: number; + detergentAddonCents: number; + softenerAddonCents: number; + bleachAddonCents: number; +}) { + return ( + Math.max(0, input.detergentQty) * input.detergentAddonCents + + Math.max(0, input.softenerQty) * input.softenerAddonCents + + Math.max(0, input.bleachQty) * input.bleachAddonCents + ); +} diff --git a/src/server/services/customerService.ts b/src/server/services/customerService.ts new file mode 100644 index 0000000..a8f4298 --- /dev/null +++ b/src/server/services/customerService.ts @@ -0,0 +1,153 @@ +import "server-only"; + +import { Prisma } from "@prisma/client"; + +import { prisma } from "@/lib/db"; +import { TRANSACTION_STATUS } from "@/server/domain/constants"; + +const DEFAULT_LIMIT = 20; +const MAX_LIMIT = 200; + +const LOYALTY_ELIGIBLE_STATUSES = [TRANSACTION_STATUS.pendingRelay, TRANSACTION_STATUS.running, TRANSACTION_STATUS.completed] as const; + +export type CustomerListItem = { + id: string; + firstName: string; + lastName: string; + phone: string; + email: string | null; + createdAt: string; + updatedAt: string; + eligibleTransactionCount: number; + totalSpentCents: number; + nextDiscountTransactionNumber: number; + isNextTransactionDiscount: boolean; +}; + +export function normalizePhone(raw: string) { + return raw.replace(/[^\d+]/g, ""); +} + +function sanitizeLimit(limit: number | undefined) { + if (!Number.isFinite(limit) || !limit) { + return DEFAULT_LIMIT; + } + return Math.max(1, Math.min(MAX_LIMIT, Math.floor(limit))); +} + +function nextDiscountTransactionNumber(transactionCount: number, everyN: number) { + const normalizedEveryN = Math.max(1, everyN); + return Math.ceil((transactionCount + 1) / normalizedEveryN) * normalizedEveryN; +} + +export async function listCustomers(input: { query?: string; limit?: number }) { + const limit = sanitizeLimit(input.limit); + const query = input.query?.trim(); + + const where: Prisma.CustomerWhereInput = query + ? { + isActive: true, + OR: [ + { firstName: { contains: query } }, + { lastName: { contains: query } }, + { phone: { contains: query } }, + { email: { contains: query } } + ] + } + : { isActive: true }; + + const [customers, config] = await Promise.all([ + prisma.customer.findMany({ + where, + orderBy: [{ updatedAt: "desc" }, { createdAt: "desc" }], + take: limit + }), + prisma.appConfig.findUnique({ + where: { id: 1 }, + select: { + loyaltyEveryNTransactions: true, + loyaltyDiscountPct: true + } + }) + ]); + + const customerIds = customers.map((customer) => customer.id); + const stats = + customerIds.length > 0 + ? await prisma.transaction.groupBy({ + by: ["customerId"], + where: { + customerId: { in: customerIds }, + status: { in: [...LOYALTY_ELIGIBLE_STATUSES] } + }, + _count: { _all: true }, + _sum: { amountCents: true } + }) + : []; + + const statsMap = new Map(); + for (const row of stats) { + statsMap.set(row.customerId, { + count: row._count._all, + total: row._sum.amountCents ?? 0 + }); + } + + const loyaltyEveryNTransactions = Math.max(1, config?.loyaltyEveryNTransactions ?? 10); + const loyaltyDiscountPct = Math.max(0, Math.min(100, config?.loyaltyDiscountPct ?? 50)); + + const rows: CustomerListItem[] = customers.map((customer) => { + const txStats = statsMap.get(customer.id) ?? { count: 0, total: 0 }; + const nextDiscount = nextDiscountTransactionNumber(txStats.count, loyaltyEveryNTransactions); + + return { + id: customer.id, + firstName: customer.firstName, + lastName: customer.lastName, + phone: customer.phone, + email: customer.email, + createdAt: customer.createdAt.toISOString(), + updatedAt: customer.updatedAt.toISOString(), + eligibleTransactionCount: txStats.count, + totalSpentCents: txStats.total, + nextDiscountTransactionNumber: nextDiscount, + isNextTransactionDiscount: txStats.count + 1 === nextDiscount + }; + }); + + return { + customers: rows, + loyalty: { + everyNTransactions: loyaltyEveryNTransactions, + discountPct: loyaltyDiscountPct + } + }; +} + +export async function createCustomer(input: { + firstName: string; + lastName: string; + phone: string; + email?: string | null; +}) { + const normalizedPhone = normalizePhone(input.phone); + if (normalizedPhone.length < 8) { + throw new Error("Telefono invalido"); + } + + try { + return await prisma.customer.create({ + data: { + firstName: input.firstName.trim(), + lastName: input.lastName.trim(), + phone: normalizedPhone, + email: input.email?.trim() || null + } + }); + } catch (error) { + if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") { + throw new Error("Ya existe un cliente con ese telefono"); + } + throw error; + } +} diff --git a/src/server/services/machineService.ts b/src/server/services/machineService.ts new file mode 100644 index 0000000..40f9eae --- /dev/null +++ b/src/server/services/machineService.ts @@ -0,0 +1,248 @@ +import "server-only"; + +import { prisma } from "@/lib/db"; +import { TRANSACTION_STATUS } from "@/server/domain/constants"; + +export type DashboardMachine = { + id: string; + name: string; + type: "washer" | "dryer"; + relayChannel: number; + defaultPriceCents: number; + defaultDurationMinutes: number; + status: "available" | "running" | "out_of_service"; + transaction: { + id: string; + ticketNumber: number; + customerId: string; + customerName: string; + baseAmountCents: number; + discountCents: number; + loyaltyDiscountApplied: boolean; + addonDetergentQty: number; + addonSoftenerQty: number; + addonBleachQty: number; + addonAmountCents: number; + serviceType: "autoservicio" | "encargo" | "xl"; + amountCents: number; + paymentMethod: "cash" | "card" | "transfer"; + startedAt: string; + expectedEndAt: string; + employeeId: string; + } | null; +}; + +type ComboLabel = "ENCARGO" | "XL"; + +type ComboDescriptor = { + number: number; + label?: ComboLabel; +}; + +const DEFAULT_COMBOS: ComboDescriptor[] = [ + ...Array.from({ length: 12 }, (_, index) => ({ + number: index + 1 + })), + { number: 13, label: "ENCARGO" }, + { number: 14, label: "ENCARGO" }, + { number: 15, label: "ENCARGO" }, + { number: 16, label: "XL" } +]; + +function toComboLabelText(label?: ComboLabel) { + if (label === "ENCARGO") { + return "Encargo"; + } + if (label === "XL") { + return "XL"; + } + return ""; +} + +function buildDefaultMachineName(type: "washer" | "dryer", combo: ComboDescriptor) { + const base = type === "washer" ? `Lavadora ${combo.number}` : `Secadora ${combo.number}`; + const label = toComboLabelText(combo.label); + return label ? `${base} (${label})` : base; +} + +export async function ensureDefaultMachineCombos() { + const existingMachines = await prisma.machine.findMany({ + select: { + name: true, + relayChannel: true + }, + orderBy: { relayChannel: "asc" } + }); + const usedNames = new Set(existingMachines.map((machine) => machine.name)); + + const requiredNames = new Set(); + for (const combo of DEFAULT_COMBOS) { + requiredNames.add(buildDefaultMachineName("washer", combo)); + requiredNames.add(buildDefaultMachineName("dryer", combo)); + } + const hasAllDefaultCombos = Array.from(requiredNames).every((name) => usedNames.has(name)); + if (hasAllDefaultCombos) { + return; + } + + const usedRelayChannels = new Set(existingMachines.map((machine) => machine.relayChannel)); + let nextRelayChannel = 0; + + function reserveRelayChannel() { + while (usedRelayChannels.has(nextRelayChannel)) { + nextRelayChannel += 1; + } + const value = nextRelayChannel; + usedRelayChannels.add(value); + nextRelayChannel += 1; + return value; + } + + const toCreate: Array<{ + name: string; + type: "washer" | "dryer"; + relayChannel: number; + defaultPriceCents: number; + defaultDurationMinutes: number; + }> = []; + + for (const combo of DEFAULT_COMBOS) { + const washerName = buildDefaultMachineName("washer", combo); + if (!usedNames.has(washerName)) { + usedNames.add(washerName); + toCreate.push({ + name: washerName, + type: "washer", + relayChannel: reserveRelayChannel(), + defaultPriceCents: 8000, + defaultDurationMinutes: 35 + }); + } + + const dryerName = buildDefaultMachineName("dryer", combo); + if (!usedNames.has(dryerName)) { + usedNames.add(dryerName); + toCreate.push({ + name: dryerName, + type: "dryer", + relayChannel: reserveRelayChannel(), + defaultPriceCents: 6000, + defaultDurationMinutes: 45 + }); + } + } + + if (toCreate.length > 0) { + await prisma.machine.createMany({ data: toCreate }); + } +} + +export async function getDashboardMachines(): Promise { + await ensureDefaultMachineCombos(); + + const machines = await prisma.machine.findMany({ + where: { isActive: true }, + orderBy: { relayChannel: "asc" }, + include: { + transactions: { + where: { + status: { + in: [TRANSACTION_STATUS.running, TRANSACTION_STATUS.pendingRelay] + } + }, + orderBy: { createdAt: "desc" }, + take: 1, + include: { + customer: { + select: { + id: true, + firstName: true, + lastName: true + } + } + } + } + } + }); + + return machines.map((machine) => { + const runningTransaction = machine.transactions.at(0); + const machineType = machine.type === "dryer" ? "dryer" : "washer"; + const status = machine.outOfService + ? "out_of_service" + : runningTransaction + ? "running" + : "available"; + + return { + id: machine.id, + name: machine.name, + type: machineType, + relayChannel: machine.relayChannel, + defaultPriceCents: machine.defaultPriceCents, + defaultDurationMinutes: machine.defaultDurationMinutes, + status, + transaction: runningTransaction + ? { + id: runningTransaction.id, + ticketNumber: runningTransaction.ticketNumber, + customerId: runningTransaction.customerId, + customerName: `${runningTransaction.customer.firstName} ${runningTransaction.customer.lastName}`.trim(), + baseAmountCents: runningTransaction.baseAmountCents, + discountCents: runningTransaction.discountCents, + loyaltyDiscountApplied: runningTransaction.loyaltyDiscountApplied, + addonDetergentQty: runningTransaction.addonDetergentQty, + addonSoftenerQty: runningTransaction.addonSoftenerQty, + addonBleachQty: runningTransaction.addonBleachQty, + addonAmountCents: runningTransaction.addonAmountCents, + serviceType: + runningTransaction.serviceType === "encargo" + ? "encargo" + : runningTransaction.serviceType === "xl" + ? "xl" + : "autoservicio", + amountCents: runningTransaction.amountCents, + paymentMethod: + runningTransaction.paymentMethod === "card" + ? "card" + : runningTransaction.paymentMethod === "transfer" + ? "transfer" + : "cash", + startedAt: runningTransaction.startedAt.toISOString(), + expectedEndAt: runningTransaction.expectedEndAt.toISOString(), + employeeId: runningTransaction.employeeId + } + : null + }; + }); +} + +export async function updateMachineConfig( + machineId: string, + input: Partial<{ + name: string; + relayChannel: number; + defaultPriceCents: number; + defaultDurationMinutes: number; + outOfService: boolean; + isActive: boolean; + }> +) { + return prisma.machine.update({ + where: { id: machineId }, + data: input + }); +} + +export async function updateAllMachineDefaults(input: { + defaultPriceCents?: number; + defaultDurationMinutes?: number; +}) { + if (input.defaultPriceCents === undefined && input.defaultDurationMinutes === undefined) { + return { count: 0 }; + } + return prisma.machine.updateMany({ + where: { isActive: true }, + data: input + }); +} diff --git a/src/server/services/recoveryService.ts b/src/server/services/recoveryService.ts new file mode 100644 index 0000000..77b2f96 --- /dev/null +++ b/src/server/services/recoveryService.ts @@ -0,0 +1,58 @@ +import "server-only"; + +import { prisma } from "@/lib/db"; +import { logger } from "@/lib/logger"; +import { TRANSACTION_STATUS } from "@/server/domain/constants"; +import { relayManager } from "@/server/relay/relayManager"; +import { ensureDefaultMachineCombos } from "@/server/services/machineService"; +import { timerService } from "@/server/services/timerService"; + +class RecoveryService { + private restored = false; + + async restoreOnBoot() { + if (this.restored) { + return; + } + this.restored = true; + + await relayManager.init(); + await ensureDefaultMachineCombos(); + await timerService.bootstrap(); + + const now = new Date(); + const running = await prisma.transaction.findMany({ + where: { + status: TRANSACTION_STATUS.running + }, + include: { machine: true } + }); + + for (const transaction of running) { + if (transaction.expectedEndAt <= now) { + await timerService.expireTransaction(transaction.id, "recovery"); + continue; + } + try { + await relayManager.turnOn(transaction.machine.relayChannel); + } catch (error) { + logger.warn("No se pudo reactivar relay en recuperacion", { + transactionId: transaction.id, + error: String(error) + }); + } + timerService.scheduleExpiry(transaction.id, transaction.expectedEndAt); + } + } +} + +declare global { + // eslint-disable-next-line no-var + var recoveryServiceGlobal: RecoveryService | undefined; +} + +export const recoveryService = global.recoveryServiceGlobal ?? new RecoveryService(); + +if (process.env.NODE_ENV !== "production") { + global.recoveryServiceGlobal = recoveryService; +} diff --git a/src/server/services/reportService.ts b/src/server/services/reportService.ts new file mode 100644 index 0000000..1525c54 --- /dev/null +++ b/src/server/services/reportService.ts @@ -0,0 +1,142 @@ +import "server-only"; + +import { prisma } from "@/lib/db"; +import { clampRange, minutesBetween } from "@/lib/time"; +import { TRANSACTION_STATUS } from "@/server/domain/constants"; +import { calculateUtilizationPct } from "@/server/services/calculations"; + +export type ReportRange = { + from: Date; + to: Date; +}; + +export async function getReportSummary(range: ReportRange) { + const transactions = await prisma.transaction.findMany({ + where: { + createdAt: { + gte: range.from, + lte: range.to + }, + status: { + not: TRANSACTION_STATUS.voided + } + }, + include: { + machine: { + select: { id: true, name: true } + } + } + }); + + const totalRevenueCents = transactions.reduce((sum, tx) => sum + tx.amountCents, 0); + const transactionCount = transactions.length; + const avgTicketCents = transactionCount > 0 ? Math.round(totalRevenueCents / transactionCount) : 0; + + const paymentMap = new Map(); + const machineMap = new Map(); + + for (const tx of transactions) { + const paymentEntry = paymentMap.get(tx.paymentMethod) ?? { amountCents: 0, count: 0 }; + paymentEntry.amountCents += tx.amountCents; + paymentEntry.count += 1; + paymentMap.set(tx.paymentMethod, paymentEntry); + + const machineEntry = machineMap.get(tx.machineId) ?? { + machineId: tx.machineId, + machineName: tx.machine.name, + amountCents: 0, + count: 0 + }; + machineEntry.amountCents += tx.amountCents; + machineEntry.count += 1; + machineMap.set(tx.machineId, machineEntry); + } + + return { + range, + totals: { + totalRevenueCents, + transactionCount, + avgTicketCents + }, + byPaymentMethod: Array.from(paymentMap.entries()).map(([paymentMethod, value]) => ({ + paymentMethod, + ...value + })), + byMachine: Array.from(machineMap.values()).sort((a, b) => b.amountCents - a.amountCents) + }; +} + +export async function getUtilizationReport(range: ReportRange) { + const machines = await prisma.machine.findMany({ + where: { isActive: true }, + orderBy: { relayChannel: "asc" } + }); + const transactions = await prisma.transaction.findMany({ + where: { + status: { + in: [TRANSACTION_STATUS.running, TRANSACTION_STATUS.completed] + }, + startedAt: { + lte: range.to + }, + OR: [ + { + endedAt: { + gte: range.from + } + }, + { + endedAt: null, + expectedEndAt: { + gte: range.from + } + } + ] + } + }); + + const totalWindowMinutes = minutesBetween(range.from, range.to); + const usageByMachine = new Map(); + + for (const tx of transactions) { + const txEnd = tx.endedAt ?? tx.expectedEndAt; + const overlap = clampRange(tx.startedAt, txEnd, range.from, range.to); + if (!overlap) { + continue; + } + const minutes = minutesBetween(overlap.start, overlap.end); + usageByMachine.set(tx.machineId, (usageByMachine.get(tx.machineId) ?? 0) + minutes); + } + + return machines.map((machine) => { + const usedMinutes = usageByMachine.get(machine.id) ?? 0; + const utilizationPct = calculateUtilizationPct(usedMinutes, totalWindowMinutes); + return { + machineId: machine.id, + machineName: machine.name, + usedMinutes: Number(usedMinutes.toFixed(2)), + totalWindowMinutes: Number(totalWindowMinutes.toFixed(2)), + utilizationPct + }; + }); +} + +export async function getReportCsv(range: ReportRange) { + const summary = await getReportSummary(range); + const lines = [ + "Tipo,Clave,Valor1,Valor2", + `totales,totalRevenueCents,${summary.totals.totalRevenueCents},`, + `totales,transactionCount,${summary.totals.transactionCount},`, + `totales,avgTicketCents,${summary.totals.avgTicketCents},` + ]; + + for (const row of summary.byPaymentMethod) { + lines.push(`payment,${row.paymentMethod},${row.amountCents},${row.count}`); + } + for (const row of summary.byMachine) { + lines.push(`machine,${row.machineName},${row.amountCents},${row.count}`); + } + + return lines.join("\n"); +} diff --git a/src/server/services/shiftService.ts b/src/server/services/shiftService.ts new file mode 100644 index 0000000..3690c4e --- /dev/null +++ b/src/server/services/shiftService.ts @@ -0,0 +1,171 @@ +import "server-only"; + +import { prisma } from "@/lib/db"; +import { CASH_MOVEMENT_TYPE, PAYMENT_METHODS, TRANSACTION_STATUS, type CashMovementTypeValue } from "@/server/domain/constants"; +import { calculateExpectedCash } from "@/server/services/calculations"; + +export async function getActiveShift() { + return prisma.shift.findFirst({ + where: { endTime: null }, + include: { + employee: true, + cashMovements: { + orderBy: { createdAt: "desc" } + } + }, + orderBy: { startTime: "desc" } + }); +} + +export async function openShift(input: { employeeId: string; startingCashCents: number }) { + const existing = await getActiveShift(); + if (existing) { + throw new Error("Ya hay un turno abierto"); + } + return prisma.shift.create({ + data: { + employeeId: input.employeeId, + startingCashCents: input.startingCashCents + } + }); +} + +export async function addCashMovement(input: { + employeeId: string; + shiftId: string; + type: CashMovementTypeValue; + amountCents: number; + reason: string; +}) { + return prisma.cashMovement.create({ + data: input + }); +} + +export async function calculateExpectedCashCents(shiftId: string) { + const shift = await prisma.shift.findUnique({ + where: { id: shiftId } + }); + if (!shift) { + throw new Error("Turno no encontrado"); + } + + const rangeEnd = shift.endTime ?? new Date(); + const rangeStart = shift.startTime; + + const cashSales = await prisma.transaction.aggregate({ + _sum: { amountCents: true }, + where: { + createdAt: { + gte: rangeStart, + lte: rangeEnd + }, + paymentMethod: PAYMENT_METHODS.cash, + status: { + not: TRANSACTION_STATUS.voided + } + } + }); + + const movements = await prisma.cashMovement.groupBy({ + by: ["type"], + _sum: { amountCents: true }, + where: { + shiftId + } + }); + + const deposits = movements.find((item) => item.type === CASH_MOVEMENT_TYPE.deposit)?._sum.amountCents ?? 0; + const withdrawals = movements.find((item) => item.type === CASH_MOVEMENT_TYPE.withdrawal)?._sum.amountCents ?? 0; + const sales = cashSales._sum.amountCents ?? 0; + + return calculateExpectedCash({ + startingCashCents: shift.startingCashCents, + cashSalesCents: sales, + depositsCents: deposits, + withdrawalsCents: withdrawals + }); +} + +export async function closeShift(input: { shiftId: string; actualCashCents: number; notes?: string }) { + const shift = await prisma.shift.findUnique({ + where: { id: input.shiftId } + }); + if (!shift || shift.endTime) { + throw new Error("Turno no valido para cierre"); + } + const expected = await calculateExpectedCashCents(input.shiftId); + const difference = input.actualCashCents - expected; + + return prisma.shift.update({ + where: { id: input.shiftId }, + data: { + endTime: new Date(), + expectedCashCents: expected, + actualCashCents: input.actualCashCents, + differenceCashCents: difference, + notes: input.notes + } + }); +} + +export async function getShiftSummary(shiftId: string) { + const shift = await prisma.shift.findUnique({ + where: { id: shiftId }, + include: { + cashMovements: true, + employee: true + } + }); + if (!shift) { + throw new Error("Turno no encontrado"); + } + + const end = shift.endTime ?? new Date(); + const txStats = await prisma.transaction.groupBy({ + by: ["paymentMethod"], + where: { + createdAt: { + gte: shift.startTime, + lte: end + }, + status: { + not: TRANSACTION_STATUS.voided + } + }, + _sum: { amountCents: true }, + _count: { _all: true } + }); + + const totalSalesCents = txStats.reduce((sum, row) => sum + (row._sum.amountCents ?? 0), 0); + const expectedCashCents = await calculateExpectedCashCents(shift.id); + + return { + shift, + totals: { + totalSalesCents, + expectedCashCents, + transactionCount: txStats.reduce((sum, row) => sum + row._count._all, 0), + byPaymentMethod: txStats.map((row) => ({ + paymentMethod: row.paymentMethod, + amountCents: row._sum.amountCents ?? 0, + count: row._count._all + })) + } + }; +} + +export async function getShiftHistory(range: { from: Date; to: Date }) { + return prisma.shift.findMany({ + where: { + startTime: { + gte: range.from, + lte: range.to + } + }, + include: { + employee: true + }, + orderBy: { startTime: "desc" } + }); +} diff --git a/src/server/services/timerService.ts b/src/server/services/timerService.ts new file mode 100644 index 0000000..d168165 --- /dev/null +++ b/src/server/services/timerService.ts @@ -0,0 +1,150 @@ +import "server-only"; + +import { prisma } from "@/lib/db"; +import { logger } from "@/lib/logger"; +import { TRANSACTION_STATUS } from "@/server/domain/constants"; +import { relayManager } from "@/server/relay/relayManager"; + +type JobMap = Map; + +class TimerService { + private jobs: JobMap = new Map(); + private lock = new Set(); + private bootstrapped = false; + private sweepInterval: NodeJS.Timeout | null = null; + + async bootstrap() { + if (this.bootstrapped) { + return; + } + this.bootstrapped = true; + + const running = await prisma.transaction.findMany({ + where: { + status: TRANSACTION_STATUS.running + } + }); + + for (const transaction of running) { + this.scheduleExpiry(transaction.id, transaction.expectedEndAt); + } + + this.sweepInterval = setInterval(() => { + this.sweepDueTransactions().catch((error) => { + logger.error("Error en barrido de timers", { error: String(error) }); + }); + }, 30_000); + } + + scheduleExpiry(transactionId: string, expectedEndAt: Date) { + const existing = this.jobs.get(transactionId); + if (existing) { + clearTimeout(existing); + } + const delayMs = Math.max(0, expectedEndAt.getTime() - Date.now()); + const timeout = setTimeout(() => { + this.expireTransaction(transactionId, "scheduled").catch((error) => + logger.error("Error en expiracion programada", { error: String(error), transactionId }) + ); + }, delayMs); + this.jobs.set(transactionId, timeout); + } + + unschedule(transactionId: string) { + const existing = this.jobs.get(transactionId); + if (existing) { + clearTimeout(existing); + this.jobs.delete(transactionId); + } + } + + async sweepDueTransactions() { + const now = new Date(); + const due = await prisma.transaction.findMany({ + where: { + status: TRANSACTION_STATUS.running, + expectedEndAt: { + lte: now + } + }, + select: { id: true } + }); + + for (const row of due) { + await this.expireTransaction(row.id, "sweep"); + } + } + + async expireTransaction(transactionId: string, source: "scheduled" | "sweep" | "recovery") { + if (this.lock.has(transactionId)) { + return; + } + this.lock.add(transactionId); + + try { + const tx = await prisma.transaction.findUnique({ + where: { id: transactionId }, + include: { machine: true } + }); + + if (!tx) { + this.unschedule(transactionId); + return; + } + + if (tx.status !== TRANSACTION_STATUS.running) { + this.unschedule(transactionId); + return; + } + + if (tx.expectedEndAt > new Date() && source !== "recovery") { + this.scheduleExpiry(tx.id, tx.expectedEndAt); + return; + } + + await prisma.transaction.update({ + where: { id: tx.id }, + data: { + relayOffAttemptedAt: new Date() + } + }); + + await relayManager.turnOff(tx.machine.relayChannel); + + await prisma.transaction.update({ + where: { id: tx.id }, + data: { + status: TRANSACTION_STATUS.completed, + endedAt: new Date(), + relayTurnedOffAt: new Date(), + relayFailureReason: null + } + }); + this.unschedule(tx.id); + logger.info("Transaccion completada por expiracion", { transactionId: tx.id }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + await prisma.transaction.update({ + where: { id: transactionId }, + data: { + relayFailureReason: `OFF_FAIL: ${message}` + } + }); + this.scheduleExpiry(transactionId, new Date(Date.now() + 30_000)); + logger.error("Fallo apagado de relay en expiracion", { transactionId, message }); + } finally { + this.lock.delete(transactionId); + } + } +} + +declare global { + // eslint-disable-next-line no-var + var timerServiceGlobal: TimerService | undefined; +} + +export const timerService = global.timerServiceGlobal ?? new TimerService(); + +if (process.env.NODE_ENV !== "production") { + global.timerServiceGlobal = timerService; +} diff --git a/src/server/system/bootstrap.ts b/src/server/system/bootstrap.ts new file mode 100644 index 0000000..d09c72e --- /dev/null +++ b/src/server/system/bootstrap.ts @@ -0,0 +1,15 @@ +import "server-only"; + +import { recoveryService } from "@/server/services/recoveryService"; + +let bootPromise: Promise | null = null; + +export function ensureSystemBootstrapped() { + if (!bootPromise) { + bootPromise = recoveryService.restoreOnBoot().catch((error) => { + bootPromise = null; + throw error; + }); + } + return bootPromise; +} diff --git a/tailwind.config.ts b/tailwind.config.ts new file mode 100644 index 0000000..36d4420 --- /dev/null +++ b/tailwind.config.ts @@ -0,0 +1,25 @@ +import type { Config } from "tailwindcss"; + +const config: Config = { + content: [ + "./src/app/**/*.{ts,tsx}", + "./src/components/**/*.{ts,tsx}", + "./src/lib/**/*.{ts,tsx}" + ], + theme: { + extend: { + colors: { + surface: "#f8f6ee", + panel: "#ffffff", + accent: "#0f766e", + available: "#166534", + running: "#1d4ed8", + danger: "#b91c1c", + warning: "#a16207" + } + } + }, + plugins: [] +}; + +export default config; diff --git a/tests/e2e/smoke.spec.ts b/tests/e2e/smoke.spec.ts new file mode 100644 index 0000000..7980e1f --- /dev/null +++ b/tests/e2e/smoke.spec.ts @@ -0,0 +1,7 @@ +import { expect, test } from "@playwright/test"; + +test("login screen is visible", async ({ page }) => { + await page.goto("/"); + await expect(page.getByText("La Burbuja POS")).toBeVisible(); + await expect(page.getByRole("button", { name: "Entrar" })).toBeVisible(); +}); diff --git a/tests/unit/calculations.test.ts b/tests/unit/calculations.test.ts new file mode 100644 index 0000000..44c7aa9 --- /dev/null +++ b/tests/unit/calculations.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, it } from "vitest"; + +import { calculateAddonTotalCents, calculateExpectedCash, calculateLoyaltyDiscountCents, calculateUtilizationPct } from "@/server/services/calculations"; + +describe("calculateExpectedCash", () => { + it("computes shift expected cash with deposits and withdrawals", () => { + const value = calculateExpectedCash({ + startingCashCents: 10_000, + cashSalesCents: 24_500, + depositsCents: 2_000, + withdrawalsCents: 1_500 + }); + expect(value).toBe(35_000); + }); +}); + +describe("calculateUtilizationPct", () => { + it("returns rounded percentage", () => { + expect(calculateUtilizationPct(43, 120)).toBe(35.83); + }); + + it("guards zero window", () => { + expect(calculateUtilizationPct(10, 0)).toBe(0); + }); +}); + +describe("calculateLoyaltyDiscountCents", () => { + it("computes rounded discount by percentage", () => { + expect(calculateLoyaltyDiscountCents(4_500, 50)).toBe(2_250); + }); + + it("caps percentage and guards invalid values", () => { + expect(calculateLoyaltyDiscountCents(3_000, 150)).toBe(3_000); + expect(calculateLoyaltyDiscountCents(3_000, -20)).toBe(0); + }); +}); + +describe("calculateAddonTotalCents", () => { + it("sums addon quantities by configured prices", () => { + expect( + calculateAddonTotalCents({ + detergentQty: 2, + softenerQty: 1, + bleachQty: 3, + detergentAddonCents: 500, + softenerAddonCents: 500, + bleachAddonCents: 500 + }) + ).toBe(3_000); + }); +}); diff --git a/tests/unit/dateRange.test.ts b/tests/unit/dateRange.test.ts new file mode 100644 index 0000000..f569522 --- /dev/null +++ b/tests/unit/dateRange.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest"; + +import { parseDateRange } from "@/server/api/dateRange"; + +describe("parseDateRange", () => { + it("parses explicit from/to", () => { + const params = new URLSearchParams({ + from: "2026-04-05T10:00:00.000Z", + to: "2026-04-05T18:00:00.000Z" + }); + const range = parseDateRange(params); + expect(range.from.toISOString()).toBe("2026-04-05T10:00:00.000Z"); + expect(range.to.toISOString()).toBe("2026-04-05T18:00:00.000Z"); + }); + + it("throws on inverted range", () => { + const params = new URLSearchParams({ + from: "2026-04-05T18:00:00.000Z", + to: "2026-04-05T10:00:00.000Z" + }); + expect(() => parseDateRange(params)).toThrow("Rango de fechas invalido"); + }); +}); diff --git a/tests/unit/time.test.ts b/tests/unit/time.test.ts new file mode 100644 index 0000000..47bde5c --- /dev/null +++ b/tests/unit/time.test.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest"; + +import { addMinutes, clampRange, minutesBetween } from "@/lib/time"; + +describe("time helpers", () => { + it("adds minutes correctly", () => { + const base = new Date("2026-04-06T10:00:00.000Z"); + const result = addMinutes(base, 35); + expect(result.toISOString()).toBe("2026-04-06T10:35:00.000Z"); + }); + + it("returns overlap range", () => { + const overlap = clampRange( + new Date("2026-04-06T10:00:00.000Z"), + new Date("2026-04-06T11:00:00.000Z"), + new Date("2026-04-06T10:30:00.000Z"), + new Date("2026-04-06T12:00:00.000Z") + ); + expect(overlap?.start.toISOString()).toBe("2026-04-06T10:30:00.000Z"); + expect(overlap?.end.toISOString()).toBe("2026-04-06T11:00:00.000Z"); + expect(minutesBetween(overlap!.start, overlap!.end)).toBe(30); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5f882b1 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,44 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": [ + "dom", + "dom.iterable", + "es2022" + ], + "allowJs": false, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./src/*" + ] + }, + "types": [ + "node", + "vitest/globals" + ] + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo new file mode 100644 index 0000000..b4911b1 --- /dev/null +++ b/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.es2021.d.ts","./node_modules/typescript/lib/lib.es2022.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.es2021.promise.d.ts","./node_modules/typescript/lib/lib.es2021.string.d.ts","./node_modules/typescript/lib/lib.es2021.weakref.d.ts","./node_modules/typescript/lib/lib.es2021.intl.d.ts","./node_modules/typescript/lib/lib.es2022.array.d.ts","./node_modules/typescript/lib/lib.es2022.error.d.ts","./node_modules/typescript/lib/lib.es2022.intl.d.ts","./node_modules/typescript/lib/lib.es2022.object.d.ts","./node_modules/typescript/lib/lib.es2022.string.d.ts","./node_modules/typescript/lib/lib.es2022.regexp.d.ts","./node_modules/typescript/lib/lib.decorators.d.ts","./node_modules/typescript/lib/lib.decorators.legacy.d.ts","./.next/types/routes.d.ts","./node_modules/@types/react/global.d.ts","./node_modules/csstype/index.d.ts","./node_modules/@types/react/index.d.ts","./node_modules/next/dist/styled-jsx/types/css.d.ts","./node_modules/next/dist/styled-jsx/types/macro.d.ts","./node_modules/next/dist/styled-jsx/types/style.d.ts","./node_modules/next/dist/styled-jsx/types/global.d.ts","./node_modules/next/dist/styled-jsx/types/index.d.ts","./node_modules/next/dist/shared/lib/amp.d.ts","./node_modules/next/amp.d.ts","./node_modules/next/dist/server/get-page-files.d.ts","./node_modules/@types/node/compatibility/disposable.d.ts","./node_modules/@types/node/compatibility/indexable.d.ts","./node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/@types/node/compatibility/index.d.ts","./node_modules/@types/node/globals.typedarray.d.ts","./node_modules/@types/node/buffer.buffer.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/web-globals/abortcontroller.d.ts","./node_modules/@types/node/web-globals/domexception.d.ts","./node_modules/@types/node/web-globals/events.d.ts","./node_modules/undici-types/header.d.ts","./node_modules/undici-types/readable.d.ts","./node_modules/undici-types/file.d.ts","./node_modules/undici-types/fetch.d.ts","./node_modules/undici-types/formdata.d.ts","./node_modules/undici-types/connector.d.ts","./node_modules/undici-types/client.d.ts","./node_modules/undici-types/errors.d.ts","./node_modules/undici-types/dispatcher.d.ts","./node_modules/undici-types/global-dispatcher.d.ts","./node_modules/undici-types/global-origin.d.ts","./node_modules/undici-types/pool-stats.d.ts","./node_modules/undici-types/pool.d.ts","./node_modules/undici-types/handlers.d.ts","./node_modules/undici-types/balanced-pool.d.ts","./node_modules/undici-types/agent.d.ts","./node_modules/undici-types/mock-interceptor.d.ts","./node_modules/undici-types/mock-agent.d.ts","./node_modules/undici-types/mock-client.d.ts","./node_modules/undici-types/mock-pool.d.ts","./node_modules/undici-types/mock-errors.d.ts","./node_modules/undici-types/proxy-agent.d.ts","./node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/undici-types/retry-handler.d.ts","./node_modules/undici-types/retry-agent.d.ts","./node_modules/undici-types/api.d.ts","./node_modules/undici-types/interceptors.d.ts","./node_modules/undici-types/util.d.ts","./node_modules/undici-types/cookies.d.ts","./node_modules/undici-types/patch.d.ts","./node_modules/undici-types/websocket.d.ts","./node_modules/undici-types/eventsource.d.ts","./node_modules/undici-types/filereader.d.ts","./node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/undici-types/content-type.d.ts","./node_modules/undici-types/cache.d.ts","./node_modules/undici-types/index.d.ts","./node_modules/@types/node/web-globals/fetch.d.ts","./node_modules/@types/node/web-globals/navigator.d.ts","./node_modules/@types/node/web-globals/storage.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/inspector.generated.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/sea.d.ts","./node_modules/@types/node/sqlite.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/index.d.ts","./node_modules/@types/react/canary.d.ts","./node_modules/@types/react/experimental.d.ts","./node_modules/@types/react-dom/index.d.ts","./node_modules/@types/react-dom/canary.d.ts","./node_modules/@types/react-dom/experimental.d.ts","./node_modules/next/dist/lib/fallback.d.ts","./node_modules/next/dist/compiled/webpack/webpack.d.ts","./node_modules/next/dist/server/config.d.ts","./node_modules/next/dist/lib/load-custom-routes.d.ts","./node_modules/next/dist/shared/lib/image-config.d.ts","./node_modules/next/dist/build/webpack/plugins/subresource-integrity-plugin.d.ts","./node_modules/next/dist/server/body-streams.d.ts","./node_modules/next/dist/server/lib/cache-control.d.ts","./node_modules/next/dist/lib/setup-exception-listeners.d.ts","./node_modules/next/dist/lib/worker.d.ts","./node_modules/next/dist/lib/constants.d.ts","./node_modules/next/dist/client/components/app-router-headers.d.ts","./node_modules/next/dist/build/rendering-mode.d.ts","./node_modules/next/dist/server/lib/router-utils/build-prefetch-segment-data-route.d.ts","./node_modules/next/dist/server/require-hook.d.ts","./node_modules/next/dist/server/lib/experimental/ppr.d.ts","./node_modules/next/dist/build/webpack/plugins/app-build-manifest-plugin.d.ts","./node_modules/next/dist/lib/page-types.d.ts","./node_modules/next/dist/build/segment-config/app/app-segment-config.d.ts","./node_modules/next/dist/build/segment-config/pages/pages-segment-config.d.ts","./node_modules/next/dist/build/analysis/get-page-static-info.d.ts","./node_modules/next/dist/build/webpack/loaders/get-module-build-info.d.ts","./node_modules/next/dist/build/webpack/plugins/middleware-plugin.d.ts","./node_modules/next/dist/server/node-polyfill-crypto.d.ts","./node_modules/next/dist/server/node-environment-baseline.d.ts","./node_modules/next/dist/server/node-environment-extensions/error-inspect.d.ts","./node_modules/next/dist/server/node-environment-extensions/random.d.ts","./node_modules/next/dist/server/node-environment-extensions/date.d.ts","./node_modules/next/dist/server/node-environment-extensions/web-crypto.d.ts","./node_modules/next/dist/server/node-environment-extensions/node-crypto.d.ts","./node_modules/next/dist/server/node-environment.d.ts","./node_modules/next/dist/build/page-extensions-type.d.ts","./node_modules/next/dist/build/webpack/plugins/flight-manifest-plugin.d.ts","./node_modules/next/dist/server/instrumentation/types.d.ts","./node_modules/next/dist/lib/coalesced-function.d.ts","./node_modules/next/dist/shared/lib/router/utils/middleware-route-matcher.d.ts","./node_modules/next/dist/server/lib/router-utils/types.d.ts","./node_modules/next/dist/shared/lib/modern-browserslist-target.d.ts","./node_modules/next/dist/shared/lib/constants.d.ts","./node_modules/next/dist/trace/types.d.ts","./node_modules/next/dist/trace/trace.d.ts","./node_modules/next/dist/trace/shared.d.ts","./node_modules/next/dist/trace/index.d.ts","./node_modules/next/dist/build/load-jsconfig.d.ts","./node_modules/@next/env/dist/index.d.ts","./node_modules/next/dist/build/webpack/plugins/telemetry-plugin/use-cache-tracker-utils.d.ts","./node_modules/next/dist/build/webpack/plugins/telemetry-plugin/telemetry-plugin.d.ts","./node_modules/next/dist/telemetry/storage.d.ts","./node_modules/next/dist/build/build-context.d.ts","./node_modules/next/dist/shared/lib/bloom-filter.d.ts","./node_modules/next/dist/build/webpack-config.d.ts","./node_modules/next/dist/server/route-kind.d.ts","./node_modules/next/dist/server/route-definitions/route-definition.d.ts","./node_modules/next/dist/build/swc/generated-native.d.ts","./node_modules/next/dist/build/swc/types.d.ts","./node_modules/next/dist/server/dev/parse-version-info.d.ts","./node_modules/next/dist/next-devtools/shared/types.d.ts","./node_modules/next/dist/server/dev/dev-indicator-server-state.d.ts","./node_modules/next/dist/server/lib/parse-stack.d.ts","./node_modules/next/dist/next-devtools/server/shared.d.ts","./node_modules/next/dist/next-devtools/shared/stack-frame.d.ts","./node_modules/next/dist/next-devtools/dev-overlay/utils/get-error-by-type.d.ts","./node_modules/@types/react/jsx-runtime.d.ts","./node_modules/next/dist/next-devtools/dev-overlay/container/runtime-error/render-error.d.ts","./node_modules/next/dist/next-devtools/dev-overlay/shared.d.ts","./node_modules/next/dist/server/dev/hot-reloader-types.d.ts","./node_modules/next/dist/server/lib/cache-handlers/types.d.ts","./node_modules/next/dist/server/response-cache/types.d.ts","./node_modules/next/dist/server/resume-data-cache/cache-store.d.ts","./node_modules/next/dist/server/resume-data-cache/resume-data-cache.d.ts","./node_modules/next/dist/server/render-result.d.ts","./node_modules/next/dist/server/lib/i18n-provider.d.ts","./node_modules/next/dist/server/web/next-url.d.ts","./node_modules/next/dist/compiled/@edge-runtime/cookies/index.d.ts","./node_modules/next/dist/server/web/spec-extension/cookies.d.ts","./node_modules/next/dist/server/web/spec-extension/request.d.ts","./node_modules/next/dist/server/after/builtin-request-context.d.ts","./node_modules/next/dist/server/web/spec-extension/fetch-event.d.ts","./node_modules/next/dist/server/web/spec-extension/response.d.ts","./node_modules/next/dist/build/segment-config/middleware/middleware-config.d.ts","./node_modules/next/dist/server/web/types.d.ts","./node_modules/next/dist/build/webpack/plugins/pages-manifest-plugin.d.ts","./node_modules/next/dist/shared/lib/router/utils/parse-url.d.ts","./node_modules/next/dist/server/base-http/node.d.ts","./node_modules/next/dist/build/webpack/plugins/next-font-manifest-plugin.d.ts","./node_modules/next/dist/server/route-definitions/locale-route-definition.d.ts","./node_modules/next/dist/server/route-definitions/pages-route-definition.d.ts","./node_modules/next/dist/shared/lib/mitt.d.ts","./node_modules/next/dist/client/with-router.d.ts","./node_modules/next/dist/client/router.d.ts","./node_modules/next/dist/client/route-loader.d.ts","./node_modules/next/dist/client/page-loader.d.ts","./node_modules/next/dist/shared/lib/router/router.d.ts","./node_modules/next/dist/shared/lib/router-context.shared-runtime.d.ts","./node_modules/next/dist/shared/lib/loadable-context.shared-runtime.d.ts","./node_modules/next/dist/shared/lib/loadable.shared-runtime.d.ts","./node_modules/next/dist/shared/lib/image-config-context.shared-runtime.d.ts","./node_modules/next/dist/shared/lib/hooks-client-context.shared-runtime.d.ts","./node_modules/next/dist/shared/lib/head-manager-context.shared-runtime.d.ts","./node_modules/next/dist/server/route-definitions/app-page-route-definition.d.ts","./node_modules/next/dist/build/webpack/loaders/metadata/types.d.ts","./node_modules/next/dist/build/webpack/loaders/next-app-loader/index.d.ts","./node_modules/next/dist/server/lib/app-dir-module.d.ts","./node_modules/next/dist/server/web/spec-extension/adapters/request-cookies.d.ts","./node_modules/next/dist/server/async-storage/draft-mode-provider.d.ts","./node_modules/next/dist/server/web/spec-extension/adapters/headers.d.ts","./node_modules/next/dist/server/app-render/cache-signal.d.ts","./node_modules/next/dist/server/app-render/dynamic-rendering.d.ts","./node_modules/next/dist/server/request/fallback-params.d.ts","./node_modules/next/dist/server/app-render/work-unit-async-storage-instance.d.ts","./node_modules/next/dist/server/response-cache/index.d.ts","./node_modules/next/dist/server/lib/lazy-result.d.ts","./node_modules/next/dist/server/lib/implicit-tags.d.ts","./node_modules/next/dist/server/app-render/work-unit-async-storage.external.d.ts","./node_modules/next/dist/shared/lib/deep-readonly.d.ts","./node_modules/next/dist/shared/lib/router/utils/parse-relative-url.d.ts","./node_modules/next/dist/server/app-render/app-render.d.ts","./node_modules/next/dist/shared/lib/server-inserted-html.shared-runtime.d.ts","./node_modules/next/dist/shared/lib/amp-context.shared-runtime.d.ts","./node_modules/next/dist/server/route-modules/app-page/vendored/contexts/entrypoints.d.ts","./node_modules/next/dist/server/route-modules/app-page/module.compiled.d.ts","./node_modules/next/dist/client/components/error-boundary.d.ts","./node_modules/next/dist/client/components/layout-router.d.ts","./node_modules/next/dist/client/components/render-from-template-context.d.ts","./node_modules/next/dist/server/app-render/action-async-storage-instance.d.ts","./node_modules/next/dist/server/app-render/action-async-storage.external.d.ts","./node_modules/next/dist/client/components/client-page.d.ts","./node_modules/next/dist/client/components/client-segment.d.ts","./node_modules/next/dist/server/request/search-params.d.ts","./node_modules/next/dist/client/components/hooks-server-context.d.ts","./node_modules/next/dist/client/components/http-access-fallback/error-boundary.d.ts","./node_modules/next/dist/lib/metadata/types/alternative-urls-types.d.ts","./node_modules/next/dist/lib/metadata/types/extra-types.d.ts","./node_modules/next/dist/lib/metadata/types/metadata-types.d.ts","./node_modules/next/dist/lib/metadata/types/manifest-types.d.ts","./node_modules/next/dist/lib/metadata/types/opengraph-types.d.ts","./node_modules/next/dist/lib/metadata/types/twitter-types.d.ts","./node_modules/next/dist/lib/metadata/types/metadata-interface.d.ts","./node_modules/next/dist/lib/metadata/types/resolvers.d.ts","./node_modules/next/dist/lib/metadata/types/icons.d.ts","./node_modules/next/dist/lib/metadata/resolve-metadata.d.ts","./node_modules/next/dist/lib/metadata/metadata.d.ts","./node_modules/next/dist/lib/framework/boundary-components.d.ts","./node_modules/next/dist/server/app-render/rsc/preloads.d.ts","./node_modules/next/dist/server/app-render/rsc/postpone.d.ts","./node_modules/next/dist/server/app-render/rsc/taint.d.ts","./node_modules/next/dist/shared/lib/segment-cache/segment-value-encoding.d.ts","./node_modules/next/dist/server/app-render/collect-segment-data.d.ts","./node_modules/next/dist/next-devtools/userspace/app/segment-explorer-node.d.ts","./node_modules/next/dist/server/app-render/entry-base.d.ts","./node_modules/next/dist/build/templates/app-page.d.ts","./node_modules/@types/react/jsx-dev-runtime.d.ts","./node_modules/@types/react/compiler-runtime.d.ts","./node_modules/next/dist/server/route-modules/app-page/vendored/rsc/entrypoints.d.ts","./node_modules/@types/react-dom/client.d.ts","./node_modules/@types/react-dom/static.d.ts","./node_modules/@types/react-dom/server.d.ts","./node_modules/next/dist/server/route-modules/app-page/vendored/ssr/entrypoints.d.ts","./node_modules/next/dist/server/route-modules/app-page/module.d.ts","./node_modules/next/dist/server/web/adapter.d.ts","./node_modules/next/dist/server/use-cache/cache-life.d.ts","./node_modules/next/dist/server/app-render/types.d.ts","./node_modules/next/dist/client/components/router-reducer/router-reducer-types.d.ts","./node_modules/next/dist/client/flight-data-helpers.d.ts","./node_modules/next/dist/client/components/router-reducer/fetch-server-response.d.ts","./node_modules/next/dist/shared/lib/app-router-context.shared-runtime.d.ts","./node_modules/next/dist/server/route-modules/pages/vendored/contexts/entrypoints.d.ts","./node_modules/next/dist/server/route-modules/pages/module.compiled.d.ts","./node_modules/next/dist/build/templates/pages.d.ts","./node_modules/next/dist/server/route-modules/pages/module.d.ts","./node_modules/next/dist/next-devtools/userspace/pages/pages-dev-overlay-setup.d.ts","./node_modules/next/dist/server/render.d.ts","./node_modules/next/dist/server/route-definitions/pages-api-route-definition.d.ts","./node_modules/next/dist/server/route-matches/pages-api-route-match.d.ts","./node_modules/next/dist/server/route-matchers/route-matcher.d.ts","./node_modules/next/dist/server/route-matcher-providers/route-matcher-provider.d.ts","./node_modules/next/dist/server/route-matcher-managers/route-matcher-manager.d.ts","./node_modules/next/dist/server/normalizers/normalizer.d.ts","./node_modules/next/dist/server/normalizers/locale-route-normalizer.d.ts","./node_modules/next/dist/server/normalizers/request/pathname-normalizer.d.ts","./node_modules/next/dist/server/normalizers/request/suffix.d.ts","./node_modules/next/dist/server/normalizers/request/rsc.d.ts","./node_modules/next/dist/server/normalizers/request/prefetch-rsc.d.ts","./node_modules/next/dist/server/normalizers/request/next-data.d.ts","./node_modules/next/dist/server/normalizers/request/segment-prefix-rsc.d.ts","./node_modules/next/dist/build/static-paths/types.d.ts","./node_modules/next/dist/server/base-server.d.ts","./node_modules/next/dist/server/lib/async-callback-set.d.ts","./node_modules/next/dist/shared/lib/router/utils/route-regex.d.ts","./node_modules/next/dist/shared/lib/router/utils/route-matcher.d.ts","./node_modules/sharp/lib/index.d.ts","./node_modules/next/dist/server/image-optimizer.d.ts","./node_modules/next/dist/server/next-server.d.ts","./node_modules/next/dist/server/lib/types.d.ts","./node_modules/next/dist/server/lib/lru-cache.d.ts","./node_modules/next/dist/server/lib/dev-bundler-service.d.ts","./node_modules/next/dist/server/dev/static-paths-worker.d.ts","./node_modules/next/dist/server/dev/next-dev-server.d.ts","./node_modules/next/dist/server/next.d.ts","./node_modules/next/dist/server/lib/render-server.d.ts","./node_modules/next/dist/server/lib/router-server.d.ts","./node_modules/next/dist/shared/lib/router/utils/path-match.d.ts","./node_modules/next/dist/server/lib/router-utils/filesystem.d.ts","./node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.d.ts","./node_modules/next/dist/server/lib/router-utils/router-server-context.d.ts","./node_modules/next/dist/server/route-modules/route-module.d.ts","./node_modules/next/dist/server/load-components.d.ts","./node_modules/next/dist/server/route-definitions/app-route-route-definition.d.ts","./node_modules/next/dist/server/async-storage/work-store.d.ts","./node_modules/next/dist/server/web/http.d.ts","./node_modules/next/dist/server/route-modules/app-route/shared-modules.d.ts","./node_modules/next/dist/client/components/redirect-status-code.d.ts","./node_modules/next/dist/client/components/redirect-error.d.ts","./node_modules/next/dist/build/templates/app-route.d.ts","./node_modules/next/dist/server/route-modules/app-route/module.d.ts","./node_modules/next/dist/server/route-modules/app-route/module.compiled.d.ts","./node_modules/next/dist/build/segment-config/app/app-segments.d.ts","./node_modules/next/dist/build/utils.d.ts","./node_modules/next/dist/build/turborepo-access-trace/types.d.ts","./node_modules/next/dist/build/turborepo-access-trace/result.d.ts","./node_modules/next/dist/build/turborepo-access-trace/helpers.d.ts","./node_modules/next/dist/build/turborepo-access-trace/index.d.ts","./node_modules/next/dist/export/routes/types.d.ts","./node_modules/next/dist/export/types.d.ts","./node_modules/next/dist/export/worker.d.ts","./node_modules/next/dist/build/worker.d.ts","./node_modules/next/dist/build/index.d.ts","./node_modules/next/dist/server/lib/incremental-cache/index.d.ts","./node_modules/next/dist/server/after/after.d.ts","./node_modules/next/dist/server/after/after-context.d.ts","./node_modules/next/dist/server/app-render/work-async-storage-instance.d.ts","./node_modules/next/dist/server/app-render/work-async-storage.external.d.ts","./node_modules/next/dist/server/request/params.d.ts","./node_modules/next/dist/server/route-matches/route-match.d.ts","./node_modules/next/dist/server/request-meta.d.ts","./node_modules/next/dist/cli/next-test.d.ts","./node_modules/next/dist/server/config-shared.d.ts","./node_modules/next/dist/server/base-http/index.d.ts","./node_modules/next/dist/server/api-utils/index.d.ts","./node_modules/next/dist/types.d.ts","./node_modules/next/dist/shared/lib/html-context.shared-runtime.d.ts","./node_modules/next/dist/shared/lib/utils.d.ts","./node_modules/next/dist/pages/_app.d.ts","./node_modules/next/app.d.ts","./node_modules/next/dist/server/web/spec-extension/unstable-cache.d.ts","./node_modules/next/dist/server/web/spec-extension/revalidate.d.ts","./node_modules/next/dist/server/web/spec-extension/unstable-no-store.d.ts","./node_modules/next/dist/server/use-cache/cache-tag.d.ts","./node_modules/next/cache.d.ts","./node_modules/next/dist/shared/lib/runtime-config.external.d.ts","./node_modules/next/config.d.ts","./node_modules/next/dist/pages/_document.d.ts","./node_modules/next/document.d.ts","./node_modules/next/dist/shared/lib/dynamic.d.ts","./node_modules/next/dynamic.d.ts","./node_modules/next/dist/pages/_error.d.ts","./node_modules/next/error.d.ts","./node_modules/next/dist/shared/lib/head.d.ts","./node_modules/next/head.d.ts","./node_modules/next/dist/server/request/cookies.d.ts","./node_modules/next/dist/server/request/headers.d.ts","./node_modules/next/dist/server/request/draft-mode.d.ts","./node_modules/next/headers.d.ts","./node_modules/next/dist/shared/lib/get-img-props.d.ts","./node_modules/next/dist/client/image-component.d.ts","./node_modules/next/dist/shared/lib/image-external.d.ts","./node_modules/next/image.d.ts","./node_modules/next/dist/client/link.d.ts","./node_modules/next/link.d.ts","./node_modules/next/dist/client/components/redirect.d.ts","./node_modules/next/dist/client/components/not-found.d.ts","./node_modules/next/dist/client/components/forbidden.d.ts","./node_modules/next/dist/client/components/unauthorized.d.ts","./node_modules/next/dist/client/components/unstable-rethrow.server.d.ts","./node_modules/next/dist/client/components/unstable-rethrow.d.ts","./node_modules/next/dist/client/components/navigation.react-server.d.ts","./node_modules/next/dist/client/components/unrecognized-action-error.d.ts","./node_modules/next/dist/client/components/navigation.d.ts","./node_modules/next/navigation.d.ts","./node_modules/next/router.d.ts","./node_modules/next/dist/client/script.d.ts","./node_modules/next/script.d.ts","./node_modules/next/dist/server/web/spec-extension/user-agent.d.ts","./node_modules/next/dist/compiled/@edge-runtime/primitives/url.d.ts","./node_modules/next/dist/server/web/spec-extension/image-response.d.ts","./node_modules/next/dist/compiled/@vercel/og/satori/index.d.ts","./node_modules/next/dist/compiled/@vercel/og/emoji/index.d.ts","./node_modules/next/dist/compiled/@vercel/og/types.d.ts","./node_modules/next/dist/server/after/index.d.ts","./node_modules/next/dist/server/request/root-params.d.ts","./node_modules/next/dist/server/request/connection.d.ts","./node_modules/next/server.d.ts","./node_modules/next/types/global.d.ts","./node_modules/next/types/compiled.d.ts","./node_modules/next/types.d.ts","./node_modules/next/index.d.ts","./node_modules/next/image-types/global.d.ts","./next-env.d.ts","./next.config.ts","./node_modules/playwright-core/types/protocol.d.ts","./node_modules/playwright-core/types/structs.d.ts","./node_modules/zod/v3/helpers/typealiases.d.cts","./node_modules/zod/v3/helpers/util.d.cts","./node_modules/zod/v3/index.d.cts","./node_modules/zod/v3/zoderror.d.cts","./node_modules/zod/v3/locales/en.d.cts","./node_modules/zod/v3/errors.d.cts","./node_modules/zod/v3/helpers/parseutil.d.cts","./node_modules/zod/v3/helpers/enumutil.d.cts","./node_modules/zod/v3/helpers/errorutil.d.cts","./node_modules/zod/v3/helpers/partialutil.d.cts","./node_modules/zod/v3/standard-schema.d.cts","./node_modules/zod/v3/types.d.cts","./node_modules/zod/v3/external.d.cts","./node_modules/zod/index.d.cts","./node_modules/playwright-core/types/types.d.ts","./node_modules/playwright-core/index.d.ts","./node_modules/playwright/types/test.d.ts","./node_modules/playwright/test.d.ts","./node_modules/@playwright/test/index.d.ts","./playwright.config.ts","./node_modules/source-map-js/source-map.d.ts","./node_modules/postcss/lib/previous-map.d.ts","./node_modules/postcss/lib/input.d.ts","./node_modules/postcss/lib/css-syntax-error.d.ts","./node_modules/postcss/lib/declaration.d.ts","./node_modules/postcss/lib/root.d.ts","./node_modules/postcss/lib/warning.d.ts","./node_modules/postcss/lib/lazy-result.d.ts","./node_modules/postcss/lib/no-work-result.d.ts","./node_modules/postcss/lib/processor.d.ts","./node_modules/postcss/lib/result.d.ts","./node_modules/postcss/lib/document.d.ts","./node_modules/postcss/lib/rule.d.ts","./node_modules/postcss/lib/node.d.ts","./node_modules/postcss/lib/comment.d.ts","./node_modules/postcss/lib/container.d.ts","./node_modules/postcss/lib/at-rule.d.ts","./node_modules/postcss/lib/list.d.ts","./node_modules/postcss/lib/postcss.d.ts","./node_modules/postcss/lib/postcss.d.mts","./node_modules/tailwindcss/types/generated/corepluginlist.d.ts","./node_modules/tailwindcss/types/generated/colors.d.ts","./node_modules/tailwindcss/types/config.d.ts","./node_modules/tailwindcss/types/index.d.ts","./tailwind.config.ts","./node_modules/@types/estree/index.d.ts","./node_modules/rollup/dist/rollup.d.ts","./node_modules/rollup/dist/parseast.d.ts","./node_modules/vite/types/hmrpayload.d.ts","./node_modules/vite/types/customevent.d.ts","./node_modules/vite/types/hot.d.ts","./node_modules/vite/dist/node/types.d-agj9qkwt.d.ts","./node_modules/vite/node_modules/esbuild/lib/main.d.ts","./node_modules/vite/dist/node/runtime.d.ts","./node_modules/vite/types/importglob.d.ts","./node_modules/vite/types/metadata.d.ts","./node_modules/vite/dist/node/index.d.ts","./node_modules/@vitest/pretty-format/dist/index.d.ts","./node_modules/@vitest/utils/dist/types.d.ts","./node_modules/@vitest/utils/dist/helpers.d.ts","./node_modules/tinyrainbow/dist/index-c1cfc5e9.d.ts","./node_modules/tinyrainbow/dist/node.d.ts","./node_modules/@vitest/utils/dist/index.d.ts","./node_modules/@vitest/runner/dist/tasks-3znpj1lr.d.ts","./node_modules/@vitest/utils/dist/types-bxe-2udy.d.ts","./node_modules/@vitest/utils/dist/diff.d.ts","./node_modules/@vitest/runner/dist/types.d.ts","./node_modules/@vitest/utils/dist/error.d.ts","./node_modules/@vitest/runner/dist/index.d.ts","./node_modules/vitest/dist/chunks/environment.looobwuu.d.ts","./node_modules/@vitest/snapshot/dist/environment-ddx0edty.d.ts","./node_modules/@vitest/snapshot/dist/rawsnapshot-cpnkto81.d.ts","./node_modules/@vitest/snapshot/dist/index.d.ts","./node_modules/@vitest/snapshot/dist/environment.d.ts","./node_modules/vitest/dist/chunks/config.cy0c388z.d.ts","./node_modules/vite-node/dist/trace-mapping.d-dlvdeqop.d.ts","./node_modules/vite-node/dist/index-z0r8hvru.d.ts","./node_modules/vite-node/dist/index.d.ts","./node_modules/@vitest/utils/dist/source-map.d.ts","./node_modules/vite-node/dist/client.d.ts","./node_modules/vite-node/dist/server.d.ts","./node_modules/@vitest/runner/dist/utils.d.ts","./node_modules/tinybench/dist/index.d.ts","./node_modules/vitest/dist/chunks/benchmark.geerunq4.d.ts","./node_modules/@vitest/snapshot/dist/manager.d.ts","./node_modules/vitest/dist/chunks/reporters.nr4dxcka.d.ts","./node_modules/vitest/dist/chunks/vite.czkp4x9w.d.ts","./node_modules/vitest/dist/config.d.ts","./node_modules/vitest/config.d.ts","./vitest.config.ts","./node_modules/@prisma/client/runtime/library.d.ts","./node_modules/@prisma/client/runtime/binary.d.ts","./node_modules/.prisma/client/index.d.ts","./node_modules/.prisma/client/default.d.ts","./node_modules/@prisma/client/default.d.ts","./prisma/seed.ts","./src/lib/db.ts","./src/lib/http.ts","./src/server/services/authservice.ts","./src/lib/logger.ts","./src/server/domain/constants.ts","./src/lib/config.ts","./src/lib/relay/types.ts","./src/lib/relay/mockrelaycontroller.ts","./src/lib/relay/protocol.ts","./node_modules/@serialport/parser-byte-length/dist/index.d.ts","./node_modules/@serialport/parser-cctalk/dist/index.d.ts","./node_modules/@serialport/parser-delimiter/dist/index.d.ts","./node_modules/@serialport/parser-inter-byte-timeout/dist/index.d.ts","./node_modules/@serialport/parser-packet-length/dist/index.d.ts","./node_modules/@serialport/parser-readline/dist/index.d.ts","./node_modules/@serialport/parser-ready/dist/index.d.ts","./node_modules/@serialport/parser-regex/dist/index.d.ts","./node_modules/@serialport/parser-slip-encoder/dist/decoder.d.ts","./node_modules/@serialport/parser-slip-encoder/dist/encoder.d.ts","./node_modules/@serialport/parser-slip-encoder/dist/index.d.ts","./node_modules/@serialport/parser-spacepacket/dist/utils.d.ts","./node_modules/@serialport/parser-spacepacket/dist/index.d.ts","./node_modules/@serialport/stream/dist/index.d.ts","./node_modules/serialport/dist/serialport-mock.d.ts","./node_modules/@serialport/bindings-cpp/dist/poller.d.ts","./node_modules/@serialport/bindings-cpp/dist/darwin.d.ts","./node_modules/@serialport/bindings-cpp/dist/linux.d.ts","./node_modules/@serialport/bindings-cpp/dist/win32.d.ts","./node_modules/@serialport/bindings-cpp/dist/errors.d.ts","./node_modules/@serialport/bindings-cpp/dist/index.d.ts","./node_modules/serialport/dist/serialport.d.ts","./node_modules/serialport/dist/index.d.ts","./src/lib/relay/serialrelaycontroller.ts","./src/server/relay/relaymanager.ts","./src/server/services/machineservice.ts","./src/server/services/timerservice.ts","./src/server/services/recoveryservice.ts","./src/server/system/bootstrap.ts","./src/app/api/auth/change-pin/route.ts","./src/app/api/auth/pin/route.ts","./src/server/services/customerservice.ts","./src/app/api/customers/route.ts","./src/app/api/machines/route.ts","./src/app/api/machines/[id]/route.ts","./src/app/api/machines/bulk/route.ts","./src/server/api/daterange.ts","./src/lib/time.ts","./src/server/services/calculations.ts","./src/server/services/reportservice.ts","./src/app/api/reports/export/route.ts","./src/app/api/reports/summary/route.ts","./src/app/api/reports/utilization/route.ts","./src/app/api/settings/business/route.ts","./src/app/api/settings/employees/route.ts","./src/app/api/settings/employees/[id]/route.ts","./src/app/api/settings/pricing/route.ts","./src/app/api/settings/serial/route.ts","./src/server/services/shiftservice.ts","./src/app/api/shifts/active/route.ts","./src/app/api/shifts/close/route.ts","./src/app/api/shifts/history/route.ts","./src/app/api/shifts/movements/route.ts","./src/app/api/shifts/open/route.ts","./src/app/api/system/relay/route.ts","./src/server/services/activationservice.ts","./src/app/api/transactions/route.ts","./src/app/api/transactions/[id]/extend/route.ts","./src/app/api/transactions/[id]/retry-relay/route.ts","./src/app/api/transactions/[id]/void/route.ts","./src/components/pos/api.ts","./src/components/pos/types.ts","./src/lib/format.ts","./tests/e2e/smoke.spec.ts","./node_modules/vitest/dist/chunks/worker.tn5kgiih.d.ts","./node_modules/vitest/dist/chunks/worker.b9fxpcac.d.ts","./node_modules/@vitest/expect/dist/chai.d.cts","./node_modules/@vitest/expect/dist/index.d.ts","./node_modules/@vitest/expect/index.d.ts","./node_modules/@vitest/spy/dist/index.d.ts","./node_modules/@vitest/mocker/dist/types-dzoqtgin.d.ts","./node_modules/@vitest/mocker/dist/index.d.ts","./node_modules/vitest/dist/chunks/mocker.crtm890j.d.ts","./node_modules/vitest/dist/chunks/suite.b2jumifp.d.ts","./node_modules/expect-type/dist/utils.d.ts","./node_modules/expect-type/dist/overloads.d.ts","./node_modules/expect-type/dist/branding.d.ts","./node_modules/expect-type/dist/messages.d.ts","./node_modules/expect-type/dist/index.d.ts","./node_modules/vitest/dist/index.d.ts","./tests/unit/calculations.test.ts","./tests/unit/daterange.test.ts","./tests/unit/time.test.ts","./src/app/layout.tsx","./src/components/pos/loginscreen.tsx","./src/components/pos/paneltab.tsx","./src/components/pos/reportstab.tsx","./src/components/pos/settingstab.tsx","./src/components/pos/shifttab.tsx","./src/components/pos/modals/activatemodal.tsx","./src/components/pos/modals/changepinmodal.tsx","./src/components/pos/modals/runningmodal.tsx","./src/components/pos/modals/ticketpreviewmodal.tsx","./src/components/posdashboard.tsx","./src/app/page.tsx","./.next/types/cache-life.d.ts","./.next/types/validator.ts","./.next/types/app/layout.ts","./.next/types/app/page.ts","./.next/types/app/api/auth/change-pin/route.ts","./.next/types/app/api/auth/pin/route.ts","./.next/types/app/api/customers/route.ts","./.next/types/app/api/machines/route.ts","./.next/types/app/api/machines/[id]/route.ts","./.next/types/app/api/machines/bulk/route.ts","./.next/types/app/api/reports/export/route.ts","./.next/types/app/api/reports/summary/route.ts","./.next/types/app/api/reports/utilization/route.ts","./.next/types/app/api/settings/business/route.ts","./.next/types/app/api/settings/employees/route.ts","./.next/types/app/api/settings/employees/[id]/route.ts","./.next/types/app/api/settings/pricing/route.ts","./.next/types/app/api/settings/serial/route.ts","./.next/types/app/api/shifts/active/route.ts","./.next/types/app/api/shifts/close/route.ts","./.next/types/app/api/shifts/history/route.ts","./.next/types/app/api/shifts/movements/route.ts","./.next/types/app/api/shifts/open/route.ts","./.next/types/app/api/system/relay/route.ts","./.next/types/app/api/transactions/route.ts","./.next/types/app/api/transactions/[id]/extend/route.ts","./.next/types/app/api/transactions/[id]/retry-relay/route.ts","./.next/types/app/api/transactions/[id]/void/route.ts","./node_modules/vitest/globals.d.ts"],"fileIdsList":[[77,125,142,143,472,616],[77,125,142,143,472,617],[77,125,142,143,472,619],[77,125,142,143,472,621],[77,125,142,143,472,622],[77,125,142,143,472,620],[77,125,142,143,472,627],[77,125,142,143,472,628],[77,125,142,143,472,629],[77,125,142,143,472,630],[77,125,142,143,472,632],[77,125,142,143,472,631],[77,125,142,143,472,633],[77,125,142,143,472,634],[77,125,142,143,472,636],[77,125,142,143,472,637],[77,125,142,143,472,638],[77,125,142,143,472,639],[77,125,142,143,472,640],[77,125,142,143,472,641],[77,125,142,143,472,644],[77,125,142,143,472,645],[77,125,142,143,472,646],[77,125,142,143,472,643],[77,125,142,143,318,670],[77,125,142,143,318,681],[77,125,142,143,425,426,427,428],[77,125,142,143],[60,77,125,142,143,472,475,616,617,619,620,621,622,627,628,629,630,631,632,633,634,636,637,638,639,640,641,643,644,645,646,670,681],[60,77,125,142,143,476,477],[77,125,142,143,476],[77,125,142,143,574],[77,125,142,143,573],[77,125,142,143,499],[77,125,142,143,575],[77,125,142,143,572],[77,125,142,143,602,607],[77,125,142,143,603,604,605,606],[77,125,136,142,143],[77,125,142,143,607],[77,125,142,143,157,175],[77,125,142,143,157,175,589],[77,125,142,143,595,596],[77,125,142,143,157,175,598],[77,122,123,125,142,143],[77,124,125,142,143],[125,142,143],[77,125,130,142,143,160],[77,125,126,131,136,142,143,145,157,168],[77,125,126,127,136,142,143,145],[72,73,74,77,125,142,143],[77,125,128,142,143,169],[77,125,129,130,137,142,143,146],[77,125,130,142,143,157,165],[77,125,131,133,136,142,143,145],[77,124,125,132,142,143],[77,125,133,134,142,143],[77,125,135,136,142,143],[77,124,125,136,142,143],[77,125,136,137,138,142,143,157,168],[77,125,136,137,138,142,143,152,157,160],[77,118,125,133,136,139,142,143,145,157,168],[77,125,136,137,139,140,142,143,145,157,165,168],[77,125,139,141,142,143,157,165,168],[75,76,77,78,79,80,81,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174],[77,125,142,143,144,168],[77,125,133,136,142,143,145,157],[77,125,142,143,146],[77,125,142,143,147],[77,124,125,142,143,148],[77,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174],[77,125,142,143,150],[77,125,142,143,151],[77,125,136,142,143,152,153],[77,125,142,143,152,154,169,171],[77,125,137,142,143],[77,125,136,142,143,157,158,160],[77,125,142,143,159,160],[77,125,142,143,157,158],[77,125,142,143,160],[77,125,142,143,161],[77,122,125,142,143,157,162,168],[77,125,136,142,143,163,164],[77,125,142,143,163,164],[77,125,130,142,143,145,157,165],[77,125,142,143,166],[77,125,142,143,145,167],[77,125,139,142,143,151,168],[77,125,130,142,143,169],[77,125,142,143,157,170],[77,125,142,143,144,171],[77,125,142,143,172],[77,118,125,142,143],[77,118,125,136,138,142,143,148,157,160,168,170,171,173],[77,125,142,143,157,174],[63,67,77,125,142,143,176,177,178,180,420,468],[63,77,125,142,143],[63,67,77,125,142,143,176,177,178,179,335,420,468],[63,67,77,125,142,143,176,177,179,180,420,468],[63,77,125,142,143,180,335,336],[63,77,125,142,143,180,335],[63,67,77,125,142,143,177,178,179,180,420,468],[63,67,77,125,142,143,176,178,179,180,420,468],[61,62,77,125,142,143],[77,125,142,143,543,544,547],[77,125,142,143,654],[77,125,142,143,657],[77,125,142,143,544,545,547,548,549],[77,125,142,143,544],[77,125,142,143,544,545,547],[77,125,142,143,544,545],[77,125,142,143,552],[77,125,142,143,539,552,553],[77,125,142,143,539,552],[77,125,142,143,539,546],[77,125,142,143,540],[77,125,142,143,539,540,541,543],[77,125,142,143,539],[77,125,142,143,661,662],[77,125,142,143,661,662,663,664],[77,125,142,143,661,663],[77,125,142,143,661],[69,77,125,142,143],[77,125,142,143,423],[77,125,142,143,430],[77,125,142,143,184,198,199,200,202,417],[77,125,142,143,184,223,225,227,228,231,417,419],[77,125,142,143,184,188,190,191,192,193,194,406,417,419],[77,125,142,143,417],[77,125,142,143,199,301,387,396,413],[77,125,142,143,184],[77,125,142,143,181,413],[77,125,142,143,235],[77,125,142,143,234,417,419],[77,125,139,142,143,283,301,330,474],[77,125,139,142,143,294,310,396,412],[77,125,139,142,143,348],[77,125,142,143,400],[77,125,142,143,399,400,401],[77,125,142,143,399],[71,77,125,139,142,143,181,184,188,191,195,196,197,199,203,211,212,341,366,397,417,420],[77,125,142,143,184,201,219,223,224,229,230,417,474],[77,125,142,143,201,474],[77,125,142,143,212,219,281,417,474],[77,125,142,143,474],[77,125,142,143,184,201,202,474],[77,125,142,143,226,474],[77,125,142,143,195,398,405],[77,125,142,143,151,243,413],[77,125,142,143,243,413],[63,77,125,142,143,243],[63,77,125,142,143,302],[77,125,142,143,298,346,413,456,457],[77,125,142,143,393,450,451,452,453,455],[77,125,142,143,392],[77,125,142,143,392,393],[77,125,142,143,192,342,343,344],[77,125,142,143,342,345,346],[77,125,142,143,454],[77,125,142,143,342,346],[63,77,125,142,143,185,444],[63,77,125,142,143,168],[63,77,125,142,143,201,271],[63,77,125,142,143,201],[77,125,142,143,269,273],[63,77,125,142,143,270,422],[63,67,77,125,139,142,143,175,176,177,178,179,180,420,466,467],[77,125,139,142,143],[77,125,139,142,143,188,250,342,352,367,387,402,403,417,418,474],[77,125,142,143,211,404],[77,125,142,143,420],[77,125,142,143,183],[63,77,125,142,143,283,297,309,319,321,412],[77,125,142,143,151,283,297,318,319,320,412,473],[77,125,142,143,312,313,314,315,316,317],[77,125,142,143,314],[77,125,142,143,318],[77,125,142,143,241,242,243,245],[63,77,125,142,143,236,237,238,244],[77,125,142,143,241,244],[77,125,142,143,239],[77,125,142,143,240],[63,77,125,142,143,243,270,422],[63,77,125,142,143,243,421,422],[63,77,125,142,143,243,422],[77,125,142,143,367,409],[77,125,142,143,409],[77,125,139,142,143,418,422],[77,125,142,143,306],[77,124,125,142,143,305],[77,125,142,143,213,251,289,291,293,294,295,296,339,342,412,415,418],[77,125,142,143,213,327,342,346],[77,125,142,143,294,412],[63,77,125,142,143,294,303,304,306,307,308,309,310,311,322,323,324,325,326,328,329,412,413,474],[77,125,142,143,288],[77,125,139,142,143,151,213,214,250,265,295,339,340,341,346,367,387,408,417,418,419,420,474],[77,125,142,143,412],[77,124,125,142,143,199,292,295,341,408,410,411,418],[77,125,142,143,294],[77,124,125,142,143,250,255,284,285,286,287,288,289,290,291,293,412,413],[77,125,139,142,143,255,256,284,418,419],[77,125,142,143,199,341,342,367,408,412,418],[77,125,139,142,143,417,419],[77,125,139,142,143,157,415,418,419],[77,125,139,142,143,151,168,181,188,201,213,214,216,251,252,257,262,265,291,295,342,352,354,357,359,362,363,364,365,366,387,407,408,413,415,417,418,419],[77,125,139,142,143,157],[77,125,142,143,184,185,186,188,193,196,201,219,407,415,416,420,422,474],[77,125,139,142,143,157,168,231,233,235,236,237,238,245,474],[77,125,142,143,151,168,181,223,233,261,262,263,264,291,342,357,366,367,373,376,377,387,408,413,415],[77,125,142,143,195,196,211,341,366,408,417],[77,125,139,142,143,168,185,188,291,371,415,417],[77,125,142,143,282],[77,125,139,142,143,374,375,384],[77,125,142,143,415,417],[77,125,142,143,289,292],[77,125,142,143,291,295,407,422],[77,125,139,142,143,151,217,223,264,357,367,373,376,379,415],[77,125,139,142,143,195,211,223,380],[77,125,142,143,184,216,382,407,417],[77,125,139,142,143,168,417],[77,125,139,142,143,201,215,216,217,228,246,381,383,407,417],[71,77,125,142,143,213,295,386,420,422],[77,125,139,142,143,151,168,188,195,203,211,214,251,257,261,262,263,264,265,291,342,354,367,368,370,372,387,407,408,413,414,415,422],[77,125,139,142,143,157,195,373,378,384,415],[77,125,142,143,206,207,208,209,210],[77,125,142,143,252,358],[77,125,142,143,360],[77,125,142,143,358],[77,125,142,143,360,361],[77,125,139,142,143,188,191,192,250,418],[77,125,139,142,143,151,183,185,213,251,265,295,350,351,387,415,419,420,422],[77,125,139,142,143,151,168,187,192,291,351,414,418],[77,125,142,143,284],[77,125,142,143,285],[77,125,142,143,286],[77,125,142,143,413],[77,125,142,143,232,248],[77,125,139,142,143,188,232,251],[77,125,142,143,247,248],[77,125,142,143,249],[77,125,142,143,232,233],[77,125,142,143,232,266],[77,125,142,143,232],[77,125,142,143,252,356,414],[77,125,142,143,355],[77,125,142,143,233,413,414],[77,125,142,143,353,414],[77,125,142,143,233,413],[77,125,142,143,339],[77,125,142,143,188,193,251,280,283,289,291,295,297,300,331,334,338,342,386,407,415,418],[77,125,142,143,274,277,278,279,298,299,346],[63,77,125,142,143,178,180,243,332,333],[63,77,125,142,143,178,180,243,332,333,337],[77,125,142,143,395],[77,125,142,143,199,256,294,295,306,310,342,386,388,389,390,391,393,394,397,407,412,417],[77,125,142,143,346],[77,125,142,143,350],[77,125,139,142,143,251,267,347,349,352,386,415,420,422],[77,125,142,143,274,275,276,277,278,279,298,299,346,421],[71,77,125,139,142,143,151,168,214,232,233,265,291,295,384,385,387,407,408,417,418,420],[77,125,142,143,256,258,261,408],[77,125,139,142,143,252,417],[77,125,142,143,255,294],[77,125,142,143,254],[77,125,142,143,256,257],[77,125,142,143,253,255,417],[77,125,139,142,143,187,256,258,259,260,417,418],[63,77,125,142,143,342,343,345],[77,125,142,143,218],[63,77,125,142,143,185],[63,77,125,142,143,413],[63,71,77,125,142,143,265,295,420,422],[77,125,142,143,185,444,445],[63,77,125,142,143,273],[63,77,125,142,143,151,168,183,230,268,270,272,422],[77,125,142,143,201,413,418],[77,125,142,143,369,413],[77,125,142,143,342],[63,77,125,137,139,142,143,151,183,219,225,273,420,421],[63,77,125,142,143,176,177,178,179,180,420,468],[63,64,65,66,67,77,125,142,143],[77,125,130,142,143],[77,125,142,143,220,221,222],[77,125,142,143,220],[63,67,77,125,139,141,142,143,151,175,176,177,178,179,180,181,183,214,318,379,417,419,422,468],[77,125,142,143,432],[77,125,142,143,434],[77,125,142,143,436],[77,125,142,143,438],[77,125,142,143,440,441,442],[77,125,142,143,446],[68,70,77,125,142,143,424,429,431,433,435,437,439,443,447,449,459,460,462,472,473,474,475],[77,125,142,143,448],[77,125,142,143,458],[77,125,142,143,270],[77,125,142,143,461],[77,124,125,142,143,256,258,259,261,309,413,463,464,465,468,469,470,471],[77,125,142,143,175],[77,125,142,143,496],[77,125,126,137,142,143,157,480,481,484,495],[77,125,142,143,498],[77,125,142,143,497],[77,125,142,143,517],[77,125,142,143,515,517],[77,125,142,143,506,514,515,516,518,520],[77,125,142,143,504],[77,125,142,143,507,512,517,520],[77,125,142,143,503,520],[77,125,142,143,507,508,511,512,513,520],[77,125,142,143,507,508,509,511,512,520],[77,125,142,143,504,505,506,507,508,512,513,514,516,517,518,520],[77,125,142,143,520],[77,125,142,143,502,504,505,506,507,508,509,511,512,513,514,515,516,517,518,519],[77,125,142,143,502,520],[77,125,142,143,507,509,510,512,513,520],[77,125,142,143,511,520],[77,125,142,143,512,513,517,520],[77,125,142,143,505,515],[77,125,142,143,528,537],[77,125,142,143,527,528],[77,125,142,143,587,588,589,590,591,592,593,594,597,599,601,608],[77,125,142,143,600],[77,125,142,143,600,607],[77,125,142,143,522,523],[77,125,142,143,521,524],[77,125,142,143,542],[77,90,94,125,142,143,168],[77,90,125,142,143,157,168],[77,85,125,142,143],[77,87,90,125,142,143,165,168],[77,125,142,143,145,165],[77,85,125,142,143,175],[77,87,90,125,142,143,145,168],[77,82,83,86,89,125,136,142,143,157,168],[77,90,97,125,142,143],[77,82,88,125,142,143],[77,90,111,112,125,142,143],[77,86,90,125,142,143,160,168,175],[77,111,125,142,143,175],[77,84,85,125,142,143,175],[77,90,125,142,143],[77,84,85,86,87,88,89,90,91,92,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,112,113,114,115,116,117,125,142,143],[77,90,105,125,142,143],[77,90,97,98,125,142,143],[77,88,90,98,99,125,142,143],[77,89,125,142,143],[77,82,85,90,125,142,143],[77,90,94,98,99,125,142,143],[77,94,125,142,143],[77,88,90,93,125,142,143,168],[77,82,87,90,97,125,142,143],[77,125,142,143,157],[77,85,90,111,125,142,143,173,175],[77,125,142,143,557,558],[77,125,142,143,557],[77,125,142,143,538,557,558,568],[77,125,136,137,139,140,141,142,143,145,157,165,168,174,175,521,528,529,530,531,532,533,534,535,536,537],[77,125,142,143,530,531,532,533],[77,125,142,143,530,531,532],[77,125,142,143,530],[77,125,142,143,531],[77,125,142,143,528],[77,125,142,143,569],[77,125,142,143,550,563,564,666],[77,125,142,143,539,550,554,555,666],[77,125,142,143,658],[77,125,137,142,143,157,538,539,544,550,551,554,556,559,560,561,562,565,566,568,653,666],[77,125,142,143,550,563,564,565,666],[77,125,142,143,538,567],[77,125,142,143,173,651],[77,125,142,143,550,551,554,556,559,666],[77,125,137,142,143,157,538,539,544,550,551,554,555,556,559,560,561,562,563,564,565,566,567,568,653,666],[77,125,137,142,143,157,173,538,539,544,547,550,551,554,555,556,559,560,561,562,563,564,565,566,567,568,651,652,653,655,656,658,659,660,665,666],[77,125,142,143,666],[77,125,142,143,494],[77,125,142,143,485,486],[77,125,142,143,482,483,485,487,488,493],[77,125,142,143,483,485],[77,125,142,143,493],[77,125,142,143,485],[77,125,142,143,482,483,485,488,489,490,491,492],[77,125,142,143,482,483,484],[77,125,142,143,500],[77,125,142,143,576],[77,125,142,143,495,578,579,580,615],[77,125,142,143,495,579,580,615],[77,125,142,143,495,579,615,618],[77,125,142,143,495,579,580,612,615],[77,125,142,143,495,578,579,580,612,615],[77,125,142,143,579,580,615,623,626],[77,125,142,143,495,578,579,580,611,615],[77,125,142,143,579,615,635],[77,125,142,143,495,579,615,635],[77,125,142,143,579,580,615,623,635],[77,125,142,143,495,579,611,615],[77,125,142,143,495,579,615,642],[77,125,142,143,579,615,642],[77,125,142,143,495,578,579,582,615,623,642],[77,125,142,143,680],[63,77,125,142,143,647,648],[63,77,125,142,143,648,649],[63,77,125,142,143,583,648,649],[77,125,142,143,648,649],[63,77,125,142,143,647,648,649],[63,77,125,142,143,647,648,671,672,673,674,675,676,677,678,679],[77,125,142,143,583],[77,125,142,143,472],[77,125,142,143,473,584],[77,125,142,143,473,584,586,609],[77,125,142,143,473,578,581,583,584,585,610],[77,125,142,143,473,578,582,611,613,624,625],[77,125,142,143,473,578],[77,125,142,143,473,576,578,582],[77,125,142,143,473,578,582],[77,125,142,143,473,578,581,582,611,612,613],[77,125,142,143,473,578,582,624,625],[77,125,142,143,473,578,582,625],[77,125,142,143,473,578,581,582,611],[77,125,142,143,473,614],[77,125,142,143,525],[77,125,142,143,625,666],[77,125,142,143,623,666],[77,125,142,143,624,666],[77,125,142,143,147,570]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"c8b374be904d32cd91065e4b388de6d119c1d78c583b081ef3cff5189e50a840","affectsGlobalScope":true},{"version":"7e29f41b158de217f94cb9676bf9cbd0cd9b5a46e1985141ed36e075c52bf6ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"dc0a7f107690ee5cd8afc8dbf05c4df78085471ce16bdd9881642ec738bc81fe","impliedFormat":1},{"version":"acd8fd5090ac73902278889c38336ff3f48af6ba03aa665eb34a75e7ba1dccc4","impliedFormat":1},{"version":"d6258883868fb2680d2ca96bc8b1352cab69874581493e6d52680c5ffecdb6cc","impliedFormat":1},{"version":"1b61d259de5350f8b1e5db06290d31eaebebc6baafd5f79d314b5af9256d7153","impliedFormat":1},{"version":"f258e3960f324a956fc76a3d3d9e964fff2244ff5859dcc6ce5951e5413ca826","impliedFormat":1},{"version":"643f7232d07bf75e15bd8f658f664d6183a0efaca5eb84b48201c7671a266979","impliedFormat":1},{"version":"0f6666b58e9276ac3a38fdc80993d19208442d6027ab885580d93aec76b4ef00","impliedFormat":1},{"version":"05fd364b8ef02fb1e174fbac8b825bdb1e5a36a016997c8e421f5fab0a6da0a0","impliedFormat":1},{"version":"631eff75b0e35d1b1b31081d55209abc43e16b49426546ab5a9b40bdd40b1f60","impliedFormat":1},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0fa06ada475b910e2106c98c68b10483dc8811d0c14a8a8dd36efb2672485b29","impliedFormat":1},{"version":"33e5e9aba62c3193d10d1d33ae1fa75c46a1171cf76fef750777377d53b0303f","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"4d631b81fa2f07a0e63a9a143d6a82c25c5f051298651a9b69176ba28930756d","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"58647d85d0f722a1ce9de50955df60a7489f0593bf1a7015521efe901c06d770","impliedFormat":1},{"version":"6b4e081d55ac24fc8a4631d5dd77fe249fa25900abd7d046abb87d90e3b45645","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"e208f73ef6a980104304b0d2ca5f6bf1b85de6009d2c7e404028b875020fa8f2","impliedFormat":1},{"version":"d163b6bc2372b4f07260747cbc6c0a6405ab3fbcea3852305e98ac43ca59f5bc","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6f137d651076822d4fe884287e68fd61785a0d3d1fdb250a5059b691fa897db","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"8b479a130ccb62e98f11f136d3ac80f2984fdc07616516d29881f3061f2dd472","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"bceb58df66ab8fb00170df20cd813978c5ab84be1d285710c4eb005d8e9d8efb","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"a3fc63c0d7b031693f665f5494412ba4b551fe644ededccc0ab5922401079c95","impliedFormat":1},{"version":"80523c00b8544a2000ae0143e4a90a00b47f99823eb7926c1e03c494216fc363","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"746911b62b329587939560deb5c036aca48aece03147b021fa680223255d5183","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c8d3e5a18ba35629954e48c4cc8f11dc88224650067a172685c736b27a34a4dc","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"2b55d426ff2b9087485e52ac4bc7cfafe1dc420fc76dad926cd46526567c501a","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"5b7aa3c4c1a5d81b411e8cb302b45507fea9358d3569196b27eb1a27ae3a90ef","affectsGlobalScope":true,"impliedFormat":1},{"version":"5987a903da92c7462e0b35704ce7da94d7fdc4b89a984871c0e2b87a8aae9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"8a1a0d0a4a06a8d278947fcb66bf684f117bf147f89b06e50662d79a53be3e9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"358765d5ea8afd285d4fd1532e78b88273f18cb3f87403a9b16fef61ac9fdcfe","impliedFormat":1},{"version":"9f55299850d4f0921e79b6bf344b47c420ce0f507b9dcf593e532b09ea7eeea1","impliedFormat":1},{"version":"2beff543f6e9a9701df88daeee3cdd70a34b4a1c11cb4c734472195a5cb2af54","impliedFormat":1},{"version":"2e07abf27aa06353d46f4448c0bbac73431f6065eef7113128a5cd804d0c384d","impliedFormat":1},{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1},{"version":"42bc0e1a903408137c3df2b06dfd7e402cdab5bbfa5fcfb871b22ebfdb30bd0b","impliedFormat":1},{"version":"9894dafe342b976d251aac58e616ac6df8db91fb9d98934ff9dd103e9e82578f","impliedFormat":1},{"version":"413df52d4ea14472c2fa5bee62f7a40abd1eb49be0b9722ee01ee4e52e63beb2","impliedFormat":1},{"version":"db6d2d9daad8a6d83f281af12ce4355a20b9a3e71b82b9f57cddcca0a8964a96","impliedFormat":1},{"version":"829b9e6028b29e6a8b1c01ddb713efe59da04d857089298fa79acbdb3cfcfdef","impliedFormat":1},{"version":"24f8562308dd8ba6013120557fa7b44950b619610b2c6cb8784c79f11e3c4f90","impliedFormat":1},{"version":"5f90b8c733a1bda63e42160b15a2301051e83a6f9d5332a59d16eb12f463270d","impliedFormat":1},{"version":"a86f82d646a739041d6702101afa82dcb935c416dd93cbca7fd754fd0282ce1f","impliedFormat":1},{"version":"ad0d1d75d129b1c80f911be438d6b61bfa8703930a8ff2be2f0e1f8a91841c64","impliedFormat":1},{"version":"ce75b1aebb33d510ff28af960a9221410a3eaf7f18fc5f21f9404075fba77256","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"496bbf339f3838c41f164238543e9fe5f1f10659cb30b68903851618464b98ba","impliedFormat":1},{"version":"5178eb4415a172c287c711dc60a619e110c3fd0b7de01ed0627e51a5336aa09c","impliedFormat":1},{"version":"ca6e5264278b53345bc1ce95f42fb0a8b733a09e3d6479c6ccfca55cdc45038c","impliedFormat":1},{"version":"9e2739b32f741859263fdba0244c194ca8e96da49b430377930b8f721d77c000","impliedFormat":1},{"version":"fb1d8e814a3eeb5101ca13515e0548e112bd1ff3fb358ece535b93e94adf5a3a","impliedFormat":1},{"version":"ffa495b17a5ef1d0399586b590bd281056cee6ce3583e34f39926f8dcc6ecdb5","impliedFormat":1},{"version":"98b18458acb46072947aabeeeab1e410f047e0cacc972943059ca5500b0a5e95","impliedFormat":1},{"version":"361e2b13c6765d7f85bb7600b48fde782b90c7c41105b7dab1f6e7871071ba20","impliedFormat":1},{"version":"c86fe861cf1b4c46a0fb7d74dffe596cf679a2e5e8b1456881313170f092e3fa","impliedFormat":1},{"version":"b6db56e4903e9c32e533b78ac85522de734b3d3a8541bf24d256058d464bf04b","impliedFormat":1},{"version":"24daa0366f837d22c94a5c0bad5bf1fd0f6b29e1fae92dc47c3072c3fdb2fbd5","impliedFormat":1},{"version":"570bb5a00836ffad3e4127f6adf581bfc4535737d8ff763a4d6f4cc877e60d98","impliedFormat":1},{"version":"889c00f3d32091841268f0b994beba4dceaa5df7573be12c2c829d7c5fbc232c","impliedFormat":1},{"version":"65f43099ded6073336e697512d9b80f2d4fec3182b7b2316abf712e84104db00","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"acf5a2ac47b59ca07afa9abbd2b31d001bf7448b041927befae2ea5b1951d9f9","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"d71291eff1e19d8762a908ba947e891af44749f3a2cbc5bd2ec4b72f72ea795f","impliedFormat":1},{"version":"c0480e03db4b816dff2682b347c95f2177699525c54e7e6f6aa8ded890b76be7","impliedFormat":1},{"version":"27ab780875bcbb65e09da7496f2ca36288b0c541abaa75c311450a077d54ec15","impliedFormat":1},{"version":"b620391fe8060cf9bedc176a4d01366e6574d7a71e0ac0ab344a4e76576fcbb8","impliedFormat":1},{"version":"380647d8f3b7f852cca6d154a376dbf8ac620a2f12b936594504a8a852e71d2f","impliedFormat":1},{"version":"208c9af9429dd3c76f5927b971263174aaa4bc7621ddec63f163640cbd3c473c","impliedFormat":1},{"version":"6459054aabb306821a043e02b89d54da508e3a6966601a41e71c166e4ea1474f","impliedFormat":1},{"version":"a23185bc5ef590c287c28a91baf280367b50ae4ea40327366ad01f6f4a8edbc5","impliedFormat":1},{"version":"bb37588926aba35c9283fe8d46ebf4e79ffe976343105f5c6d45f282793352b2","impliedFormat":1},{"version":"002eae065e6960458bda3cf695e578b0d1e2785523476f8a9170b103c709cd4f","impliedFormat":1},{"version":"c83bb0c9c5645a46c68356c2f73fdc9de339ce77f7f45a954f560c7e0b8d5ebb","impliedFormat":1},{"version":"05c97cddbaf99978f83d96de2d8af86aded9332592f08ce4a284d72d0952c391","impliedFormat":1},{"version":"72179f9dd22a86deaad4cc3490eb0fe69ee084d503b686985965654013f1391b","impliedFormat":1},{"version":"2e6114a7dd6feeef85b2c80120fdbfb59a5529c0dcc5bfa8447b6996c97a69f5","impliedFormat":1},{"version":"7b6ff760c8a240b40dab6e4419b989f06a5b782f4710d2967e67c695ef3e93c4","impliedFormat":1},{"version":"c8f004e6036aa1c764ad4ec543cf89a5c1893a9535c80ef3f2b653e370de45e6","impliedFormat":1},{"version":"dd80b1e600d00f5c6a6ba23f455b84a7db121219e68f89f10552c54ba46e4dc9","impliedFormat":1},{"version":"b064c36f35de7387d71c599bfcf28875849a1dbc733e82bd26cae3d1cd060521","impliedFormat":1},{"version":"6a148329edecbda07c21098639ef4254ef7869fb25a69f58e5d6a8b7b69d4236","impliedFormat":1},{"version":"8de9fe97fa9e00ec00666fa77ab6e91b35d25af8ca75dabcb01e14ad3299b150","impliedFormat":1},{"version":"f63ab283a1c8f5c79fabe7ca4ef85f9633339c4f0e822fce6a767f9d59282af2","impliedFormat":1},{"version":"dba114fb6a32b355a9cfc26ca2276834d72fe0e94cd2c3494005547025015369","impliedFormat":1},{"version":"a54c996c8870ef1728a2c1fa9b8eaec0bf4a8001cd2583c02dd5869289465b10","impliedFormat":1},{"version":"3e7efde639c6a6c3edb9847b3f61e308bf7a69685b92f665048c45132f51c218","impliedFormat":1},{"version":"df45ca1176e6ac211eae7ddf51336dc075c5314bc5c253651bae639defd5eec5","impliedFormat":1},{"version":"3754982006a3b32c502cff0867ca83584f7a43b1035989ca73603f400de13c96","impliedFormat":1},{"version":"a30ae9bb8a8fa7b90f24b8a0496702063ae4fe75deb27da731ed4a03b2eb6631","impliedFormat":1},{"version":"f974e4a06953682a2c15d5bd5114c0284d5abf8bc0fe4da25cb9159427b70072","impliedFormat":1},{"version":"50256e9c31318487f3752b7ac12ff365c8949953e04568009c8705db802776fb","impliedFormat":1},{"version":"7d73b24e7bf31dfb8a931ca6c4245f6bb0814dfae17e4b60c9e194a631fe5f7b","impliedFormat":1},{"version":"413586add0cfe7369b64979d4ec2ed56c3f771c0667fbde1bf1f10063ede0b08","impliedFormat":1},{"version":"06472528e998d152375ad3bd8ebcb69ff4694fd8d2effaf60a9d9f25a37a097a","impliedFormat":1},{"version":"50b5bc34ce6b12eccb76214b51aadfa56572aa6cc79c2b9455cdbb3d6c76af1d","impliedFormat":1},{"version":"b7e16ef7f646a50991119b205794ebfd3a4d8f8e0f314981ebbe991639023d0e","impliedFormat":1},{"version":"42c169fb8c2d42f4f668c624a9a11e719d5d07dacbebb63cbcf7ef365b0a75b3","impliedFormat":1},{"version":"a401617604fa1f6ce437b81689563dfdc377069e4c58465dbd8d16069aede0a5","impliedFormat":1},{"version":"e9dd71cf12123419c60dab867d44fbee5c358169f99529121eaef277f5c83531","impliedFormat":1},{"version":"5b6a189ba3a0befa1f5d9cb028eb9eec2af2089c32f04ff50e2411f63d70f25d","impliedFormat":1},{"version":"d6e73f8010935b7b4c7487b6fb13ea197cc610f0965b759bec03a561ccf8423a","impliedFormat":1},{"version":"174f3864e398f3f33f9a446a4f403d55a892aa55328cf6686135dfaf9e171657","impliedFormat":1},{"version":"824c76aec8d8c7e65769688cbee102238c0ef421ed6686f41b2a7d8e7e78a931","impliedFormat":1},{"version":"75b868be3463d5a8cfc0d9396f0a3d973b8c297401d00bfb008a42ab16643f13","impliedFormat":1},{"version":"15a234e5031b19c48a69ccc1607522d6e4b50f57d308ecb7fe863d44cd9f9eb3","impliedFormat":1},{"version":"d682336018141807fb602709e2d95a192828fcb8d5ba06dda3833a8ea98f69e3","impliedFormat":1},{"version":"6124e973eab8c52cabf3c07575204efc1784aca6b0a30c79eb85fe240a857efa","impliedFormat":1},{"version":"0d891735a21edc75df51f3eb995e18149e119d1ce22fd40db2b260c5960b914e","impliedFormat":1},{"version":"3b414b99a73171e1c4b7b7714e26b87d6c5cb03d200352da5342ab4088a54c85","impliedFormat":1},{"version":"4fbd3116e00ed3a6410499924b6403cc9367fdca303e34838129b328058ede40","impliedFormat":1},{"version":"b01bd582a6e41457bc56e6f0f9de4cb17f33f5f3843a7cf8210ac9c18472fb0f","impliedFormat":1},{"version":"0a437ae178f999b46b6153d79095b60c42c996bc0458c04955f1c996dc68b971","impliedFormat":1},{"version":"74b2a5e5197bd0f2e0077a1ea7c07455bbea67b87b0869d9786d55104006784f","impliedFormat":1},{"version":"4a7baeb6325920044f66c0f8e5e6f1f52e06e6d87588d837bdf44feb6f35c664","impliedFormat":1},{"version":"6dcf60530c25194a9ee0962230e874ff29d34c59605d8e069a49928759a17e0a","impliedFormat":1},{"version":"7274fbffbd7c9589d8d0ffba68157237afd5cecff1e99881ea3399127e60572f","impliedFormat":1},{"version":"1a42d2ec31a1fe62fdc51591768695ed4a2dc64c01be113e7ff22890bebb5e3f","impliedFormat":1},{"version":"1a82deef4c1d39f6882f28d275cad4c01f907b9b39be9cbc472fcf2cf051e05b","impliedFormat":1},{"version":"c5426dbfc1cf90532f66965a7aa8c1136a78d4d0f96d8180ecbfc11d7722f1a5","impliedFormat":1},{"version":"65a15fc47900787c0bd18b603afb98d33ede930bed1798fc984d5ebb78b26cf9","impliedFormat":1},{"version":"9d202701f6e0744adb6314d03d2eb8fc994798fc83d91b691b75b07626a69801","impliedFormat":1},{"version":"de9d2df7663e64e3a91bf495f315a7577e23ba088f2949d5ce9ec96f44fba37d","impliedFormat":1},{"version":"c7af78a2ea7cb1cd009cfb5bdb48cd0b03dad3b54f6da7aab615c2e9e9d570c5","impliedFormat":1},{"version":"1ee45496b5f8bdee6f7abc233355898e5bf9bd51255db65f5ff7ede617ca0027","impliedFormat":1},{"version":"0c7c947ff881c4274c0800deaa0086971e0bfe51f89a33bd3048eaa3792d4876","affectsGlobalScope":true,"impliedFormat":1},{"version":"db01d18853469bcb5601b9fc9826931cc84cc1a1944b33cad76fd6f1e3d8c544","affectsGlobalScope":true,"impliedFormat":1},{"version":"a8f8e6ab2fa07b45251f403548b78eaf2022f3c2254df3dc186cb2671fe4996d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa6c12a7c0f6b84d512f200690bfc74819e99efae69e4c95c4cd30f6884c526e","impliedFormat":1},{"version":"f1c32f9ce9c497da4dc215c3bc84b722ea02497d35f9134db3bb40a8d918b92b","impliedFormat":1},{"version":"b73c319af2cc3ef8f6421308a250f328836531ea3761823b4cabbd133047aefa","affectsGlobalScope":true,"impliedFormat":1},{"version":"e433b0337b8106909e7953015e8fa3f2d30797cea27141d1c5b135365bb975a6","impliedFormat":1},{"version":"15b36126e0089bfef173ab61329e8286ce74af5e809d8a72edcafd0cc049057f","impliedFormat":1},{"version":"ddff7fc6edbdc5163a09e22bf8df7bef75f75369ebd7ecea95ba55c4386e2441","impliedFormat":1},{"version":"106c6025f1d99fd468fd8bf6e5bda724e11e5905a4076c5d29790b6c3745e50c","impliedFormat":1},{"version":"a57b1802794433adec9ff3fed12aa79d671faed86c49b09e02e1ac41b4f1d33a","impliedFormat":1},{"version":"ad10d4f0517599cdeca7755b930f148804e3e0e5b5a3847adce0f1f71bbccd74","impliedFormat":1},{"version":"1042064ece5bb47d6aba91648fbe0635c17c600ebdf567588b4ca715602f0a9d","impliedFormat":1},{"version":"c49469a5349b3cc1965710b5b0f98ed6c028686aa8450bcb3796728873eb923e","impliedFormat":1},{"version":"4a889f2c763edb4d55cb624257272ac10d04a1cad2ed2948b10ed4a7fda2a428","impliedFormat":1},{"version":"7bb79aa2fead87d9d56294ef71e056487e848d7b550c9a367523ee5416c44cfa","impliedFormat":1},{"version":"72d63643a657c02d3e51cd99a08b47c9b020a565c55f246907050d3c8a5e77fb","impliedFormat":1},{"version":"1d415445ea58f8033ba199703e55ff7483c52ac6742075b803bd3e7bbe9f5d61","impliedFormat":1},{"version":"d6406c629bb3efc31aedb2de809bef471e475c86c7e67f3ef9b676b5d7e0d6b2","impliedFormat":1},{"version":"27ff4196654e6373c9af16b6165120e2dd2169f9ad6abb5c935af5abd8c7938c","impliedFormat":1},{"version":"71d8ba39a9e024d9e4bb922464d18542ed8d2c25ee78efa7890c27213cc6e5d3","impliedFormat":1},{"version":"8c030e515014c10a2b98f9f48408e3ba18023dfd3f56e3312c6c2f3ae1f55a16","impliedFormat":1},{"version":"dafc31e9e8751f437122eb8582b93d477e002839864410ff782504a12f2a550c","impliedFormat":1},{"version":"754498c5208ce3c5134f6eabd49b25cf5e1a042373515718953581636491f3c3","impliedFormat":1},{"version":"9c82171d836c47486074e4ca8e059735bf97b205e70b196535b5efd40cbe1bc5","impliedFormat":1},{"version":"f56bdc6884648806d34bc66d31cdb787c4718d04105ce2cd88535db214631f82","impliedFormat":1},{"version":"633d58a237f4bb25ec7d565e4ffa32cecdcee8660ac12189c4351c52557cee9e","impliedFormat":1},{"version":"2e4f37ffe8862b14d8e24ae8763daaa8340c0df0b859d9a9733def0eee7562d9","impliedFormat":1},{"version":"13283350547389802aa35d9f2188effaeac805499169a06ef5cd77ce2a0bd63f","impliedFormat":1},{"version":"ce791f6ea807560f08065d1af6014581eeb54a05abd73294777a281b6dfd73c2","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"49f95e989b4632c6c2a578cc0078ee19a5831832d79cc59abecf5160ea71abad","impliedFormat":1},{"version":"9666533332f26e8995e4d6fe472bdeec9f15d405693723e6497bf94120c566c8","impliedFormat":1},{"version":"ce0df82a9ae6f914ba08409d4d883983cc08e6d59eb2df02d8e4d68309e7848b","impliedFormat":1},{"version":"796273b2edc72e78a04e86d7c58ae94d370ab93a0ddf40b1aa85a37a1c29ecd7","impliedFormat":1},{"version":"5df15a69187d737d6d8d066e189ae4f97e41f4d53712a46b2710ff9f8563ec9f","impliedFormat":1},{"version":"e17cd049a1448de4944800399daa4a64c5db8657cc9be7ef46be66e2a2cd0e7c","impliedFormat":1},{"version":"43fa6ea8714e18adc312b30450b13562949ba2f205a1972a459180fa54471018","impliedFormat":1},{"version":"6e89c2c177347d90916bad67714d0fb473f7e37fb3ce912f4ed521fe2892cd0d","impliedFormat":1},{"version":"43ba4f2fa8c698f5c304d21a3ef596741e8e85a810b7c1f9b692653791d8d97a","impliedFormat":1},{"version":"4d4927cbee21750904af7acf940c5e3c491b4d5ebc676530211e389dd375607a","impliedFormat":1},{"version":"72105519d0390262cf0abe84cf41c926ade0ff475d35eb21307b2f94de985778","impliedFormat":1},{"version":"8a97e578a9bc40eb4f1b0ca78f476f2e9154ecbbfd5567ee72943bab37fc156a","impliedFormat":1},{"version":"c857e0aae3f5f444abd791ec81206020fbcc1223e187316677e026d1c1d6fe08","impliedFormat":1},{"version":"ccf6dd45b708fb74ba9ed0f2478d4eb9195c9dfef0ff83a6092fa3cf2ff53b4f","impliedFormat":1},{"version":"2d7db1d73456e8c5075387d4240c29a2a900847f9c1bff106a2e490da8fbd457","impliedFormat":1},{"version":"2b15c805f48e4e970f8ec0b1915f22d13ca6212375e8987663e2ef5f0205e832","impliedFormat":1},{"version":"f22d05663d873ee7a600faf78abb67f3f719d32266803440cf11d5db7ac0cab2","impliedFormat":1},{"version":"d93c544ad20197b3976b0716c6d5cd5994e71165985d31dcab6e1f77feb4b8f2","impliedFormat":1},{"version":"35069c2c417bd7443ae7c7cafd1de02f665bf015479fec998985ffbbf500628c","impliedFormat":1},{"version":"a8b1c79a833ee148251e88a2553d02ce1641d71d2921cce28e79678f3d8b96aa","impliedFormat":1},{"version":"126d4f950d2bba0bd45b3a86c76554d4126c16339e257e6d2fabf8b6bf1ce00c","impliedFormat":1},{"version":"7e0b7f91c5ab6e33f511efc640d36e6f933510b11be24f98836a20a2dc914c2d","impliedFormat":1},{"version":"045b752f44bf9bbdcaffd882424ab0e15cb8d11fa94e1448942e338c8ef19fba","impliedFormat":1},{"version":"2894c56cad581928bb37607810af011764a2f511f575d28c9f4af0f2ef02d1ab","impliedFormat":1},{"version":"0a72186f94215d020cb386f7dca81d7495ab6c17066eb07d0f44a5bf33c1b21a","impliedFormat":1},{"version":"2d3cc2211f352f46ea6b7cf2c751c141ffcdf514d6e7ae7ee20b7b6742da313f","impliedFormat":1},{"version":"c75445151ff8b77d9923191efed7203985b1a9e09eccf4b054e7be864e27923d","impliedFormat":1},{"version":"0aedb02516baf3e66b2c1db9fef50666d6ed257edac0f866ea32f1aa05aa474f","impliedFormat":1},{"version":"fa8a8fbf91ee2a4779496225f0312aac6635b0f21aa09cdafa4283fe32d519c5","affectsGlobalScope":true,"impliedFormat":1},{"version":"0e8aef93d79b000deb6ec336b5645c87de167168e184e84521886f9ecc69a4b5","impliedFormat":1},{"version":"56ccb49443bfb72e5952f7012f0de1a8679f9f75fc93a5c1ac0bafb28725fc5f","impliedFormat":1},{"version":"20fa37b636fdcc1746ea0738f733d0aed17890d1cd7cb1b2f37010222c23f13e","impliedFormat":1},{"version":"d90b9f1520366d713a73bd30c5a9eb0040d0fb6076aff370796bc776fd705943","impliedFormat":1},{"version":"bc03c3c352f689e38c0ddd50c39b1e65d59273991bfc8858a9e3c0ebb79c023b","impliedFormat":1},{"version":"19df3488557c2fc9b4d8f0bac0fd20fb59aa19dec67c81f93813951a81a867f8","affectsGlobalScope":true,"impliedFormat":1},{"version":"b25350193e103ae90423c5418ddb0ad1168dc9c393c9295ef34980b990030617","affectsGlobalScope":true,"impliedFormat":1},{"version":"bef86adb77316505c6b471da1d9b8c9e428867c2566270e8894d4d773a1c4dc2","impliedFormat":1},{"version":"de7052bfee2981443498239a90c04ea5cc07065d5b9bb61b12cb6c84313ad4ef","impliedFormat":1},{"version":"a3e7d932dc9c09daa99141a8e4800fc6c58c625af0d4bbb017773dc36da75426","impliedFormat":1},{"version":"43e96a3d5d1411ab40ba2f61d6a3192e58177bcf3b133a80ad2a16591611726d","impliedFormat":1},{"version":"4a2edd238d9104eac35b60d727f1123de5062f452b70ed8e0366cb36387dfdfd","impliedFormat":1},{"version":"ca921bf56756cb6fe957f6af693a35251b134fb932dc13f3dfff0bb7106f80b4","impliedFormat":1},{"version":"fee92c97f1aa59eb7098a0cc34ff4df7e6b11bae71526aca84359a2575f313d8","impliedFormat":1},{"version":"0bd0297484aacea217d0b76e55452862da3c5d9e33b24430e0719d1161657225","impliedFormat":1},{"version":"2ab6d334bcbf2aff3acfc4fd8c73ecd82b981d3c3aa47b3f3b89281772286904","impliedFormat":1},{"version":"d07cbc787a997d83f7bde3877fec5fb5b12ce8c1b7047eb792996ed9726b4dde","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"4805f6161c2c8cefb8d3b8bd96a080c0fe8dbc9315f6ad2e53238f9a79e528a6","impliedFormat":1},{"version":"b83cb14474fa60c5f3ec660146b97d122f0735627f80d82dd03e8caa39b4388c","impliedFormat":1},{"version":"f374cb24e93e7798c4d9e83ff872fa52d2cdb36306392b840a6ddf46cb925cb6","impliedFormat":1},{"version":"49179c6a23701c642bd99abe30d996919748014848b738d8e85181fc159685ff","impliedFormat":1},{"version":"b73cbf0a72c8800cf8f96a9acfe94f3ad32ca71342a8908b8ae484d61113f647","impliedFormat":1},{"version":"bae6dd176832f6423966647382c0d7ba9e63f8c167522f09a982f086cd4e8b23","impliedFormat":1},{"version":"20865ac316b8893c1a0cc383ccfc1801443fbcc2a7255be166cf90d03fac88c9","impliedFormat":1},{"version":"c9958eb32126a3843deedda8c22fb97024aa5d6dd588b90af2d7f2bfac540f23","impliedFormat":1},{"version":"461d0ad8ae5f2ff981778af912ba71b37a8426a33301daa00f21c6ccb27f8156","impliedFormat":1},{"version":"e927c2c13c4eaf0a7f17e6022eee8519eb29ef42c4c13a31e81a611ab8c95577","impliedFormat":1},{"version":"fcafff163ca5e66d3b87126e756e1b6dfa8c526aa9cd2a2b0a9da837d81bbd72","impliedFormat":1},{"version":"70246ad95ad8a22bdfe806cb5d383a26c0c6e58e7207ab9c431f1cb175aca657","impliedFormat":1},{"version":"f00f3aa5d64ff46e600648b55a79dcd1333458f7a10da2ed594d9f0a44b76d0b","impliedFormat":1},{"version":"772d8d5eb158b6c92412c03228bd9902ccb1457d7a705b8129814a5d1a6308fc","impliedFormat":1},{"version":"45490817629431853543adcb91c0673c25af52a456479588b6486daba34f68bb","impliedFormat":1},{"version":"802e797bcab5663b2c9f63f51bdf67eff7c41bc64c0fd65e6da3e7941359e2f7","impliedFormat":1},{"version":"8b4327413e5af38cd8cb97c59f48c3c866015d5d642f28518e3a891c469f240e","impliedFormat":1},{"version":"8514c62ce38e58457d967e9e73f128eedc1378115f712b9eef7127f7c88f82ae","impliedFormat":1},{"version":"f1289e05358c546a5b664fbb35a27738954ec2cc6eb4137350353099d154fc62","impliedFormat":1},{"version":"4b20fcf10a5413680e39f5666464859fc56b1003e7dfe2405ced82371ebd49b6","impliedFormat":1},{"version":"1d17ba45cfbe77a9c7e0df92f7d95f3eefd49ee23d1104d0548b215be56945ad","impliedFormat":1},{"version":"f7d628893c9fa52ba3ab01bcb5e79191636c4331ee5667ecc6373cbccff8ae12","impliedFormat":1},{"version":"1d879125d1ec570bf04bc1f362fdbe0cb538315c7ac4bcfcdf0c1e9670846aa6","impliedFormat":1},{"version":"a1ee88010a64e8647d07dba58ec43e6e05851b9ec7a62e4ca2b9c33be5abb2c8","impliedFormat":1},{"version":"46273e8c29816125d0d0b56ce9a849cc77f60f9a5ba627447501d214466f0ff3","impliedFormat":1},{"version":"d663134457d8d669ae0df34eabd57028bddc04fc444c4bc04bc5215afc91e1f4","impliedFormat":1},{"version":"e91f7b1344577a02f051b9b471f33044fef8334a76dc9e1de003d17595a5219b","impliedFormat":1},{"version":"3af3584f79c57853028ef9421ec172539e1fe01853296dc05a9d615ade4ffaf6","impliedFormat":1},{"version":"f82579d87701d639ff4e3930a9b24f4ee13ca74221a9a3a792feb47f01881a9c","impliedFormat":1},{"version":"d7e5d5245a8ba34a274717d085174b2c9827722778129b0081fefd341cca8f55","impliedFormat":1},{"version":"d9d32f94056181c31f553b32ce41d0ef75004912e27450738d57efcd2409c324","impliedFormat":1},{"version":"752513f35f6cff294ffe02d6027c41373adf7bfa35e593dbfd53d95c203635ee","impliedFormat":1},{"version":"6c800b281b9e89e69165fd11536195488de3ff53004e55905e6c0059a2d8591e","impliedFormat":1},{"version":"7d4254b4c6c67a29d5e7f65e67d72540480ac2cfb041ca484847f5ae70480b62","impliedFormat":1},{"version":"1a7e2ea171726446850ec72f4d1525d547ff7e86724cc9e7eec509725752a758","impliedFormat":1},{"version":"8c901126d73f09ecdea4785e9a187d1ac4e793e07da308009db04a7283ec2f37","impliedFormat":1},{"version":"db97922b767bd2675fdfa71e08b49c38b7d2c847a1cc4a7274cb77be23b026f1","impliedFormat":1},{"version":"aab290b8e4b7c399f2c09b957666fc95335eb4522b2dd9ead1bf0cb64da6d6ee","impliedFormat":1},{"version":"94fe3281392e1015b22f39535878610b4fa6f1388dc8d78746be3bc4e4bb8950","impliedFormat":1},{"version":"2652448ac55a2010a1f71dd141f828b682298d39728f9871e1cdf8696ef443fd","impliedFormat":1},{"version":"06c25ddfc2242bd06c19f66c9eae4c46d937349a267810f89783680a1d7b5259","impliedFormat":1},{"version":"120599fd965257b1f4d0ff794bc696162832d9d8467224f4665f713a3119078b","impliedFormat":1},{"version":"5433f33b0a20300cca35d2f229a7fc20b0e8477c44be2affeb21cb464af60c76","impliedFormat":1},{"version":"db036c56f79186da50af66511d37d9fe77fa6793381927292d17f81f787bb195","impliedFormat":1},{"version":"bd4131091b773973ca5d2326c60b789ab1f5e02d8843b3587effe6e1ea7c9d86","impliedFormat":1},{"version":"c7f6485931085bf010fbaf46880a9b9ec1a285ad9dc8c695a9e936f5a48f34b4","impliedFormat":1},{"version":"14f6b927888a1112d662877a5966b05ac1bf7ed25d6c84386db4c23c95a5363b","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"0427df5c06fafc5fe126d14b9becd24160a288deff40e838bfbd92a35f8d0d00","impliedFormat":1},{"version":"90c54a02432d04e4246c87736e53a6a83084357acfeeba7a489c5422b22f5c7a","impliedFormat":1},{"version":"49c346823ba6d4b12278c12c977fb3a31c06b9ca719015978cb145eb86da1c61","impliedFormat":1},{"version":"bfac6e50eaa7e73bb66b7e052c38fdc8ccfc8dbde2777648642af33cf349f7f1","impliedFormat":1},{"version":"92f7c1a4da7fbfd67a2228d1687d5c2e1faa0ba865a94d3550a3941d7527a45d","impliedFormat":1},{"version":"f53b120213a9289d9a26f5af90c4c686dd71d91487a0aa5451a38366c70dc64b","impliedFormat":1},{"version":"83fe880c090afe485a5c02262c0b7cdd76a299a50c48d9bde02be8e908fb4ae6","impliedFormat":1},{"version":"0a372c2d12a259da78e21b25974d2878502f14d89c6d16b97bd9c5017ab1bc12","impliedFormat":1},{"version":"57d67b72e06059adc5e9454de26bbfe567d412b962a501d263c75c2db430f40e","impliedFormat":1},{"version":"6511e4503cf74c469c60aafd6589e4d14d5eb0a25f9bf043dcbecdf65f261972","impliedFormat":1},{"version":"ec1ca97598eda26b7a5e6c8053623acbd88e43be7c4d29c77ccd57abc4c43999","impliedFormat":1},{"version":"6e2261cd9836b2c25eecb13940d92c024ebed7f8efe23c4b084145cd3a13b8a6","impliedFormat":1},{"version":"a67b87d0281c97dfc1197ef28dfe397fc2c865ccd41f7e32b53f647184cc7307","impliedFormat":1},{"version":"771ffb773f1ddd562492a6b9aaca648192ac3f056f0e1d997678ff97dbb6bf9b","impliedFormat":1},{"version":"232f70c0cf2b432f3a6e56a8dc3417103eb162292a9fd376d51a3a9ea5fbbf6f","impliedFormat":1},{"version":"a47e6d954d22dd9ebb802e7e431b560ed7c581e79fb885e44dc92ed4f60d4c07","impliedFormat":1},{"version":"f019e57d2491c159d47a107fd90219a1734bdd2e25cd8d1db3c8fae5c6b414c4","impliedFormat":1},{"version":"8a0e762ceb20c7e72504feef83d709468a70af4abccb304f32d6b9bac1129b2c","impliedFormat":1},{"version":"d1c9bf292a54312888a77bb19dba5e2503ad803f5393beafd45d78d2f4fe9b48","impliedFormat":1},{"version":"9252d498a77517aab5d8d4b5eb9d71e4b225bbc7123df9713e08181de63180f6","impliedFormat":1},{"version":"cb8d8ef7b9ce8ed3e6f1c814fcbf3f90dab0cb8863079236784fc350746e27c4","impliedFormat":1},{"version":"35e6379c3f7cb27b111ad4c1aa69538fd8e788ab737b8ff7596a1b40e96f4f90","impliedFormat":1},{"version":"1fffe726740f9787f15b532e1dc870af3cd964dbe29e191e76121aa3dd8693f2","impliedFormat":1},{"version":"3be035da7bee86b4c3abf392e0edaa44fc6e45092995eefe36b39118c8a84068","affectsGlobalScope":true,"impliedFormat":1},{"version":"8f828825d077c2fa0ea606649faeb122749273a353daab23924fe674e98ba44c","impliedFormat":1},{"version":"2896c2e673a5d3bd9b4246811f79486a073cbb03950c3d252fba10003c57411a","impliedFormat":1},{"version":"616775f16134fa9d01fc677ad3f76e68c051a056c22ab552c64cc281a9686790","impliedFormat":1},{"version":"65c24a8baa2cca1de069a0ba9fba82a173690f52d7e2d0f1f7542d59d5eb4db0","impliedFormat":1},{"version":"f9fe6af238339a0e5f7563acee3178f51db37f32a2e7c09f85273098cee7ec49","impliedFormat":1},{"version":"407a06ba04eede4074eec470ecba2784cbb3bf4e7de56833b097dd90a2aa0651","impliedFormat":1},{"version":"77e71242e71ebf8528c5802993697878f0533db8f2299b4d36aa015bae08a79c","impliedFormat":1},{"version":"98a787be42bd92f8c2a37d7df5f13e5992da0d967fab794adbb7ee18370f9849","impliedFormat":1},{"version":"5c96bad5f78466785cdad664c056e9e2802d5482ca5f862ed19ba34ffbb7b3a4","impliedFormat":1},{"version":"81d8603ac527e75cfec72bb9391228b58f161c2b33514a9d814c7f3ebd3ef466","impliedFormat":1},{"version":"5f3dc10ae646f375776b4e028d2bed039a93eebbba105694d8b910feebbe8b9c","impliedFormat":1},{"version":"bb0cd7862b72f5eba39909c9889d566e198fcaddf7207c16737d0c2246112678","impliedFormat":1},{"version":"4545c1a1ceca170d5d83452dd7c4994644c35cf676a671412601689d9a62da35","impliedFormat":1},{"version":"320f4091e33548b554d2214ce5fc31c96631b513dffa806e2e3a60766c8c49d9","impliedFormat":1},{"version":"a2d648d333cf67b9aeac5d81a1a379d563a8ffa91ddd61c6179f68de724260ff","impliedFormat":1},{"version":"d90d5f524de38889d1e1dbc2aeef00060d779f8688c02766ddb9ca195e4a713d","impliedFormat":1},{"version":"a3f41ed1b4f2fc3049394b945a68ae4fdefd49fa1739c32f149d32c0545d67f5","impliedFormat":1},{"version":"bad68fd0401eb90fe7da408565c8aee9c7a7021c2577aec92fa1382e8876071a","impliedFormat":1},{"version":"47699512e6d8bebf7be488182427189f999affe3addc1c87c882d36b7f2d0b0e","impliedFormat":1},{"version":"fec01479923e169fb52bd4f668dbeef1d7a7ea6e6d491e15617b46f2cacfa37d","impliedFormat":1},{"version":"8a8fb3097ba52f0ae6530ec6ab34e43e316506eb1d9aa29420a4b1e92a81442d","impliedFormat":1},{"version":"44e09c831fefb6fe59b8e65ad8f68a7ecc0e708d152cfcbe7ba6d6080c31c61e","impliedFormat":1},{"version":"1c0a98de1323051010ce5b958ad47bc1c007f7921973123c999300e2b7b0ecc0","impliedFormat":1},{"version":"4655709c9cb3fd6db2b866cab7c418c40ed9533ce8ea4b66b5f17ec2feea46a9","impliedFormat":1},{"version":"87affad8e2243635d3a191fa72ef896842748d812e973b7510a55c6200b3c2a4","impliedFormat":1},{"version":"ad036a85efcd9e5b4f7dd5c1a7362c8478f9a3b6c3554654ca24a29aa850a9c5","impliedFormat":1},{"version":"fedebeae32c5cdd1a85b4e0504a01996e4a8adf3dfa72876920d3dd6e42978e7","impliedFormat":1},{"version":"3eecb25bb467a948c04874d70452b14ae7edb707660aac17dc053e42f2088b00","impliedFormat":1},{"version":"cdf21eee8007e339b1b9945abf4a7b44930b1d695cc528459e68a3adc39a622e","impliedFormat":1},{"version":"330896c1a2b9693edd617be24fbf9e5895d6e18c7955d6c08f028f272b37314d","impliedFormat":1},{"version":"1d9c0a9a6df4e8f29dc84c25c5aa0bb1da5456ebede7a03e03df08bb8b27bae6","impliedFormat":1},{"version":"84380af21da938a567c65ef95aefb5354f676368ee1a1cbb4cae81604a4c7d17","impliedFormat":1},{"version":"1af3e1f2a5d1332e136f8b0b95c0e6c0a02aaabd5092b36b64f3042a03debf28","impliedFormat":1},{"version":"30d8da250766efa99490fc02801047c2c6d72dd0da1bba6581c7e80d1d8842a4","impliedFormat":1},{"version":"03566202f5553bd2d9de22dfab0c61aa163cabb64f0223c08431fb3fc8f70280","impliedFormat":1},{"version":"5f0292a40df210ab94b9fb44c8b775c51e96777e14e073900e392b295ca1061b","impliedFormat":1},{"version":"bc9ee0192f056b3d5527bcd78dc3f9e527a9ba2bdc0a2c296fbc9027147df4b2","impliedFormat":1},{"version":"8627ad129bcf56e82adff0ab5951627c993937aa99f5949c33240d690088b803","impliedFormat":1},{"version":"1de80059b8078ea5749941c9f863aa970b4735bdbb003be4925c853a8b6b4450","impliedFormat":1},{"version":"1d079c37fa53e3c21ed3fa214a27507bda9991f2a41458705b19ed8c2b61173d","impliedFormat":1},{"version":"5bf5c7a44e779790d1eb54c234b668b15e34affa95e78eada73e5757f61ed76a","impliedFormat":1},{"version":"5835a6e0d7cd2738e56b671af0e561e7c1b4fb77751383672f4b009f4e161d70","impliedFormat":1},{"version":"5c634644d45a1b6bc7b05e71e05e52ec04f3d73d9ac85d5927f647a5f965181a","impliedFormat":1},{"version":"4b7f74b772140395e7af67c4841be1ab867c11b3b82a51b1aeb692822b76c872","impliedFormat":1},{"version":"27be6622e2922a1b412eb057faa854831b95db9db5035c3f6d4b677b902ab3b7","impliedFormat":1},{"version":"a68d4b3182e8d776cdede7ac9630c209a7bfbb59191f99a52479151816ef9f9e","impliedFormat":99},{"version":"39644b343e4e3d748344af8182111e3bbc594930fff0170256567e13bbdbebb0","impliedFormat":99},{"version":"ed7fd5160b47b0de3b1571c5c5578e8e7e3314e33ae0b8ea85a895774ee64749","impliedFormat":99},{"version":"63a7595a5015e65262557f883463f934904959da563b4f788306f699411e9bac","impliedFormat":1},{"version":"ecbaf0da125974be39c0aac869e403f72f033a4e7fd0d8cd821a8349b4159628","impliedFormat":1},{"version":"4ba137d6553965703b6b55fd2000b4e07ba365f8caeb0359162ad7247f9707a6","impliedFormat":1},{"version":"ceec3c81b2d81f5e3b855d9367c1d4c664ab5046dff8fd56552df015b7ccbe8f","affectsGlobalScope":true,"impliedFormat":1},{"version":"8fac4a15690b27612d8474fb2fc7cc00388df52d169791b78d1a3645d60b4c8b","affectsGlobalScope":true,"impliedFormat":1},{"version":"064ac1c2ac4b2867c2ceaa74bbdce0cb6a4c16e7c31a6497097159c18f74aa7c","impliedFormat":1},{"version":"3dc14e1ab45e497e5d5e4295271d54ff689aeae00b4277979fdd10fa563540ae","impliedFormat":1},{"version":"1d63055b690a582006435ddd3aa9c03aac16a696fac77ce2ed808f3e5a06efab","impliedFormat":1},{"version":"b789bf89eb19c777ed1e956dbad0925ca795701552d22e68fd130a032008b9f9","impliedFormat":1},"85ae5aee75f011967cf2d25cbc342f62d69314e9d925f7f4aa3456fc2cffcca6",{"version":"e3a5855a21276d809e96969a73915d7435f415dbcbd8c1ea194d440666ea7b2d","signature":"435a1e418e8338be3f39614b96b81a9aa2700bc8c27bc6b98f064ff9ce17c363"},{"version":"e08660f21d0e8b367414e78706ae69a19b078fb67b0fe8c818ccaeeeedc00272","impliedFormat":1},{"version":"32727845ab5bd8a9ef3e4844c567c09f6d418fcf0f90d381c00652a6f23e7f6e","impliedFormat":1},{"version":"d3cfde44f8089768ebb08098c96d01ca260b88bccf238d55eee93f1c620ff5a5","impliedFormat":1},{"version":"293eadad9dead44c6fd1db6de552663c33f215c55a1bfa2802a1bceed88ff0ec","impliedFormat":1},{"version":"833e92c058d033cde3f29a6c7603f517001d1ddd8020bc94d2067a3bc69b2a8e","impliedFormat":1},{"version":"08b2fae7b0f553ad9f79faec864b179fc58bc172e295a70943e8585dd85f600c","impliedFormat":1},{"version":"f12edf1672a94c578eca32216839604f1e1c16b40a1896198deabf99c882b340","impliedFormat":1},{"version":"e3498cf5e428e6c6b9e97bd88736f26d6cf147dedbfa5a8ad3ed8e05e059af8a","impliedFormat":1},{"version":"dba3f34531fd9b1b6e072928b6f885aa4d28dd6789cbd0e93563d43f4b62da53","impliedFormat":1},{"version":"f672c876c1a04a223cf2023b3d91e8a52bb1544c576b81bf64a8fec82be9969c","impliedFormat":1},{"version":"e4b03ddcf8563b1c0aee782a185286ed85a255ce8a30df8453aade2188bbc904","impliedFormat":1},{"version":"2329d90062487e1eaca87b5e06abcbbeeecf80a82f65f949fd332cfcf824b87b","impliedFormat":1},{"version":"25b3f581e12ede11e5739f57a86e8668fbc0124f6649506def306cad2c59d262","impliedFormat":1},{"version":"4fdb529707247a1a917a4626bfb6a293d52cd8ee57ccf03830ec91d39d606d6d","impliedFormat":1},{"version":"a9ebb67d6bbead6044b43714b50dcb77b8f7541ffe803046fdec1714c1eba206","impliedFormat":1},{"version":"5780b706cece027f0d4444fbb4e1af62dc51e19da7c3d3719f67b22b033859b9","impliedFormat":1},{"version":"8324f3861a7a8db0f9d294f6a189182b2d231840cebb7f3ea5f4635773cdaf41","impliedFormat":1},{"version":"7a8ec10b0834eb7183e4bfcd929838ac77583828e343211bb73676d1e47f6f01","impliedFormat":1},{"version":"be57def447f85b42c8f509a8ce4125c1af5f26597c4a93ef617aae5e0b81fa02","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f00324f263189b385c3a9383b1f4dae6237697bcf0801f96aa35c340512d79c","impliedFormat":1},{"version":"ec8997c2e5cea26befc76e7bf990750e96babb16977673a9ff3b5c0575d01e48","impliedFormat":1},{"version":"3417168fd0f81011d7bf20d40e258bb5923219e0b9ba442122042c6f8ae49f81","signature":"50f8a125795ffacae7f3107820dc660812d53c75c1d9c3ac82fd3d4ee1073958"},{"version":"402e5c534fb2b85fa771170595db3ac0dd532112c8fa44fc23f233bc6967488b","impliedFormat":1},{"version":"7965dc3c7648e2a7a586d11781cabb43d4859920716bc2fdc523da912b06570d","impliedFormat":1},{"version":"90c2bd9a3e72fe08b8fa5982e78cb8dc855a1157b26e11e37a793283c52bf64b","impliedFormat":1},{"version":"a8122fe390a2a987079e06c573b1471296114677923c1c094c24a53ddd7344a2","impliedFormat":1},{"version":"70c2cb19c0c42061a39351156653aa0cf5ba1ecdc8a07424dd38e3a1f1e3c7f4","impliedFormat":1},{"version":"a8fb10fd8c7bc7d9b8f546d4d186d1027f8a9002a639bec689b5000dab68e35c","impliedFormat":1},{"version":"c9b467ea59b86bd27714a879b9ad43c16f186012a26d0f7110b1322025ceaa83","impliedFormat":1},{"version":"57ea19c2e6ba094d8087c721bac30ff1c681081dbd8b167ac068590ef633e7a5","impliedFormat":1},{"version":"cba81ec9ae7bc31a4dc56f33c054131e037649d6b9a2cfa245124c67e23e4721","impliedFormat":1},{"version":"ad193f61ba708e01218496f093c23626aa3808c296844a99189be7108a9c8343","impliedFormat":1},{"version":"a0544b3c8b70b2f319a99ea380b55ab5394ede9188cdee452a5d0ce264f258b2","impliedFormat":1},{"version":"8c654c17c334c7c168c1c36e5336896dc2c892de940886c1639bebd9fc7b9be4","impliedFormat":1},{"version":"6a4da742485d5c2eb6bcb322ae96993999ffecbd5660b0219a5f5678d8225bb0","impliedFormat":1},{"version":"c65ca21d7002bdb431f9ab3c7a6e765a489aa5196e7e0ef00aed55b1294df599","impliedFormat":1},{"version":"c8fc655c2c4bafc155ceee01c84ab3d6c03192ced5d3f2de82e20f3d1bd7f9fa","impliedFormat":1},{"version":"be5a7ff3b47f7e553565e9483bdcadb0ca2040ac9e5ec7b81c7e115a81059882","impliedFormat":1},{"version":"1a93f36ecdb60a95e3a3621b561763e2952da81962fae217ab5441ac1d77ffc5","impliedFormat":1},{"version":"2a771d907aebf9391ac1f50e4ad37952943515eeea0dcc7e78aa08f508294668","impliedFormat":1},{"version":"0146fd6262c3fd3da51cb0254bb6b9a4e42931eb2f56329edd4c199cb9aaf804","impliedFormat":1},{"version":"183f480885db5caa5a8acb833c2be04f98056bdcc5fb29e969ff86e07efe57ab","impliedFormat":99},{"version":"b558c9a18ea4e6e4157124465c3ef1063e64640da139e67be5edb22f534f2f08","impliedFormat":1},{"version":"01374379f82be05d25c08d2f30779fa4a4c41895a18b93b33f14aeef51768692","impliedFormat":1},{"version":"b0dee183d4e65cf938242efaf3d833c6b645afb35039d058496965014f158141","impliedFormat":1},{"version":"c0bbbf84d3fbd85dd60d040c81e8964cc00e38124a52e9c5dcdedf45fea3f213","impliedFormat":1},{"version":"22b70741240a963f6993bd655aa692749cd74ea735be3e98537652fce0bb4629","signature":"f65ce75c9085571e6321abf2bf9833709f4897e381f89e9925521833dbb7ab16"},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"ee70b8037ecdf0de6c04f35277f253663a536d7e38f1539d270e4e916d225a3f","affectsGlobalScope":true,"impliedFormat":1},{"version":"a660aa95476042d3fdcc1343cf6bb8fdf24772d31712b1db321c5a4dcc325434","impliedFormat":1},{"version":"282f98006ed7fa9bb2cd9bdbe2524595cfc4bcd58a0bb3232e4519f2138df811","impliedFormat":1},{"version":"6222e987b58abfe92597e1273ad7233626285bc2d78409d4a7b113d81a83496b","impliedFormat":1},{"version":"cbe726263ae9a7bf32352380f7e8ab66ee25b3457137e316929269c19e18a2be","impliedFormat":1},{"version":"8b96046bf5fb0a815cba6b0880d9f97b7f3a93cf187e8dcfe8e2792e97f38f87","impliedFormat":99},{"version":"bacf2c84cf448b2cd02c717ad46c3d7fd530e0c91282888c923ad64810a4d511","affectsGlobalScope":true,"impliedFormat":1},{"version":"82e687ebd99518bc63ea04b0c3810fb6e50aa6942decd0ca6f7a56d9b9a212a6","impliedFormat":99},{"version":"7f698624bbbb060ece7c0e51b7236520ebada74b747d7523c7df376453ed6fea","impliedFormat":1},{"version":"8f07f2b6514744ac96e51d7cb8518c0f4de319471237ea10cf688b8d0e9d0225","impliedFormat":1},{"version":"257b83faa134d971c738a6b9e4c47e59bb7b23274719d92197580dd662bfafc3","impliedFormat":99},{"version":"d2e64a6f25013b099e83bfadb2c388d7bef3e8f3fdb25528225bbc841e7e7e3a","impliedFormat":99},{"version":"369ba5259e66ca8c7d35e3234f7a2a0863a770fdb8266505747c65cf346a0804","impliedFormat":99},{"version":"64d984f55025daf604f670b7dfd090ea765f2098aee871174ef2ee3e94479098","impliedFormat":99},{"version":"f147b6710441cf3ec3234adf63b0593ce5e8c9b692959d21d3babc8454bcf743","impliedFormat":99},{"version":"e96d5373a66c2cfbbc7e6642cf274055aa2c7ff6bd37be7480c66faf9804db6d","impliedFormat":99},{"version":"02bcdd7a76c5c1c485cbf05626d24c86ac8f9a1d8dc31f8924108bbaa4cf3ba9","impliedFormat":99},{"version":"c874ab6feac6e0fdf9142727c9a876065777a5392f14b0bbcf869b1e69eb46b5","impliedFormat":99},{"version":"7c553fc9e34773ddbaabe0fa1367d4b109101d0868a008f11042bee24b5a925d","impliedFormat":99},{"version":"9962ce696fbdce2421d883ca4b062a54f982496625437ae4d3633376c5ad4a80","impliedFormat":99},{"version":"e3ea467c4a7f743f3548c9ed61300591965b1d12c08c8bb9aaff8a002ba95fce","impliedFormat":99},{"version":"4c17183a07a63bea2653fbfc0a942b027160ddbee823024789a415f9589de327","impliedFormat":99},{"version":"3e2203c892297ea44b87470fde51b3d48cfe3eeb6901995de429539462894464","impliedFormat":99},{"version":"c84bf7a4abc5e7fdf45971a71b25b0e0d34ccd5e720a866dd78bb71d60d41a3f","impliedFormat":99},{"version":"e01ea380015ed698c3c0e2ccd0db72f3fc3ef1abc4519f122aa1c1a8d419a505","impliedFormat":99},{"version":"5ada1f8a9580c0f7478fe03ae3e07e958f0b79bdfb9dd50eeb98c1324f40011b","impliedFormat":99},{"version":"a8301dc90b4bd9fba333226ee0f1681aeeff1bd90233a8f647e687cb4b7d3521","impliedFormat":99},{"version":"e3225dc0bec183183509d290f641786245e6652bc3dce755f7ef404060693c35","impliedFormat":99},{"version":"09a03870ed8c55d7453bc9ad684df88965f2f770f987481ca71b8a09be5205bc","impliedFormat":99},{"version":"e6233e1c976265e85aa8ad76c3881febe6264cb06ae3136f0257e1eab4a6cc5a","impliedFormat":99},{"version":"2cdd50ddc49e2d608ee848fc4ab0db9a2716624fabb4209c7c683d87e54d79c5","impliedFormat":99},{"version":"e431d664338b8470abb1750d699c7dfcebb1a25434559ef85bb96f1e82de5972","impliedFormat":99},{"version":"2c4254139d037c3caca66ce291c1308c1b5092cfcb151eb25980db932dd3b01a","impliedFormat":99},{"version":"970ae00ed018cb96352dc3f37355ef9c2d9f8aa94d7174ccd6d0ed855e462097","impliedFormat":99},{"version":"d2f8dee457ef7660b604226d471d55d927c3051766bdd80353553837492635c3","impliedFormat":99},{"version":"110a503289a2ef76141ffff3ffceb9a1c3662c32748eb9f6777a2bd0866d6fb1","impliedFormat":99},{"version":"69bf2422313487956e4dacf049f30cb91b34968912058d244cb19e4baa24da97","impliedFormat":99},{"version":"310e6b62c493ce991624169a1c1904015769d947be88dc67e00adc7ebebcfa87","impliedFormat":99},{"version":"62fefda288160bf6e435b21cc03d3fbac11193d8d3bd0e82d86623cca7691c29","impliedFormat":99},{"version":"fcc46a8bcbf9bef21023bba1995160a25f0bc590ca3563ec44c315b4f4c1b18a","impliedFormat":99},{"version":"669573548930fb7d0a0761b827e203dc623581e21febf0be80fb02414f217d74","impliedFormat":99},{"version":"f974db5be6d7428044e19c2848e72495a9b56a8d33b6fcab392e7fb5328eb8df","impliedFormat":99},{"version":"aa348c4fb2f8ac77df855f07fb66281c9f6e71746fdff3b13c7932aa7642b788","impliedFormat":99},{"version":"e31ddb3947ac1a832ac95473297de1db8108b985e880e45093764a9665168948","signature":"4b96dd19fd2949d28ce80e913412b0026dc421e5bf6c31d87c7b5eb11b5753b4"},{"version":"b845876de475c230a1e012150db8d2c2a62bd6835a93e8cd23ebb10f7de16266","impliedFormat":1},{"version":"8edadeb551395cad9fde0272dcc52341e2728b7d835dd61d51fb795b714ce37c","impliedFormat":1},{"version":"8227ae01e963d06ce97a69108abcf26dc0189f8d6ae3978c3ffcb20a0d0318b1","impliedFormat":1},{"version":"d5eb5865d4cbaa9985cc3cfb920b230cdcf3363f1e70903a08dc4baab80b0ce1","impliedFormat":1},{"version":"51ebca098538b252953b1ef83c165f25b52271bfb6049cd09d197dddd4cd43c5","impliedFormat":1},{"version":"f5235be804ad57625293c951fd0025e0b1647510e46d33c27c654299498fb8aa","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"3823252bab2628a0e648fdeeb5d3d4591db7cf16333b765600ed066be7585b14","signature":"e59fb293aae60df0982783b5486187e7c18cf7e94d1f2840fa875e1fdffec5a9","affectsGlobalScope":true},{"version":"8ad46f4f3d15be9b540c5dd1d0afd900a75aa87865ee4e79cd2ce57d8742e9ee","signature":"b5f5428793b0346ff64cd53a1bb7bce3ca623361b0e2f33503fdbb48537d9ed4"},{"version":"fb7f2588d761dfab941e9a6a05a78d0090c295cba4ba10ae758289d65e77b9ac","signature":"4d48c2d46b0b4e5c3f4b6a18bcc95e0917c345b3b6fb6fa023da1202f7b7a552"},{"version":"f098cf69c30d1174e558ee254175660a6ff8fa47b6a1f671e73cb73ddd448134","signature":"50955ef6a7337b449fbec2a73bfffec7f3352c990ff6e6be4f0347075a0ae3c3"},{"version":"a26a6a7efde800aef75c88e4a4f09ce35cf889c65caea2ba13cf004e9834ee2f","signature":"da80819354040c1980f2914f8f0f0a901c72e1a326d028d7adb023655d52ed4e"},{"version":"4ea388609698e374e84486e68f7e916e28511a91a2ca304f26127538f5b7a191","signature":"e5f1ef20602bf988067872570f3f7e42d63015ae4073346ffdb7ba0c30844695"},{"version":"b387ecdd85726fc45c48ae9dfca446880be05b2398ef7d364e532f03c8ed71d3","signature":"7b5bcebd705bd8bfc82a6b2de252e7a4b47fc43cbbc9fd856f640a0c1907c276"},{"version":"45ff332d508b6da5f86343f13b63974f42d1e71fb17000aceab3e5bcc9e01f38","signature":"df8629b4c11de29633552e0c9822a336514fb09d367b921e697a085d4b6f90b4"},{"version":"3127322ae738959e22dcd483b514b5a915feb27bcb639ea985007cbfa35b8d2d","signature":"44505ef5fecec39fb47f96ed4588a3634b2162cc30b15adffb1fd69055d9909b"},{"version":"b222b89486393de12ccd5b634182eabb13bfc89a1d6b107fa10a221d953a4838","impliedFormat":1},{"version":"e01cb91334bd604a880e6fbae5d5f56e63a8f8e2d877645190047a61bc757de2","impliedFormat":1},{"version":"9bde3b57a76e0e2e0ce0c855023ce8d3b6c0809f99135baade9d0fbfec15f2a3","impliedFormat":1},{"version":"2e7ff6f58158ec703c8cb7b4d4766e9475db0d847dc8d8640ab0176744c5e4b6","impliedFormat":1},{"version":"a982f5e040e4a828c6d7fff732515671f6fd599905225b6b4d1d05090914fcb5","impliedFormat":1},{"version":"aa802fae8eb4d043e2580a7dd77c11756573a24947e37c320dbf8a299ea960e9","impliedFormat":1},{"version":"95c87cdfa6829f548b3ba440e0c3bcb1b93c3ea8d90ac2215da8c6ae68cce6a7","impliedFormat":1},{"version":"34112a29f03c00ea76d396278e4cf87f5bf76fb86465e3310159dcda3fcc9b72","impliedFormat":1},{"version":"9dc56ac836e8c569879950b1a42adeea34255b9f4c2b83de5c3fb98a930af716","impliedFormat":1},{"version":"68dc008cd889ffd674f6a2b8a3445fba66083b7da8af5af63fc9118b60443a47","impliedFormat":1},{"version":"88dae717554bfd9d5c33ae7cfc32535cf77d3a34bf6f478fefa3e30d20dd8eb6","impliedFormat":1},{"version":"ee37922ad640688e97fce39a5f1f5676c190d898dd6a63fb29b282da11734a82","impliedFormat":1},{"version":"2af89ea0dac13629a68fe36cf1701d4357a480fccdd4997bfb923458a25d40d0","impliedFormat":1},{"version":"82ea0d4bc293b05993d7b6640063c834737a7db69be78f69b538fbdd96a0210e","impliedFormat":1},{"version":"0498b6a3cfa5f27dfd0f8f245118e905d1f8f8bd38bcfb92650e940909ecb59a","impliedFormat":1},{"version":"f27cb9fa7b78b19df4b0ae39e2b97dbebb54e91433096b49ef39f73cd25b5e0e","impliedFormat":1},{"version":"f6cc7cfd05001a9138a0dbe7c1e405fbb10700f939c9b75d84b9f2c2d54adf61","impliedFormat":1},{"version":"f3f896548650e7a5c2021fb3e62f9e82d556a5aa00a2ff8942c64a93f7a6d5d8","impliedFormat":1},{"version":"49357ee4ba1e42dd79910c1060dda2ecb1166c3c8c45111fedf3e73afafa3ce0","impliedFormat":1},{"version":"3a28904968592c8802f67b729993393161789ae7c5d033a5b9a2917e01db2614","impliedFormat":1},{"version":"d31f2710a55b0e1a54ddedbea84c2b4966285e0d63d2b65a2ed02effb530fab2","impliedFormat":1},{"version":"126a2bdbd6088c88d4a0f8502c043b881e574a0fd64f8f77f36ac9a8d3bc3783","impliedFormat":1},{"version":"7072554a2cbf847062f80d04fba1a6cecc5e830cc4792c6f64b35e127f8141a6","impliedFormat":1},{"version":"35ec36b4ebc1e236f7cbb1cba5be45b614f65a657cab2e2b0b33d6b1ee10423f","signature":"58c78df4fbfee123e28009dfa538fb9291c5b6df5284a5ace73e9d8310ef6715"},{"version":"54a0da8fae16cb8352d59b8109e566d318d6f6a833c76cf4f402ea63831cd4ce","signature":"ca3d93342aab9263d6e5dcaa50ebcb71510c10268a94095e124bfbbdaf2278b7","affectsGlobalScope":true},{"version":"4de385f70d87e9298e67622f58a83972e2553739ab9685094fcdfb5f1be724bc","signature":"968c07338d87a89b9d565ecd2e899fdd9a449d925dfd4c5fb645846c7f65a0c4"},{"version":"e8d82aa1c2c76597fe68c78ffba9b2b6301f430589e5a257bdea753867f51766","signature":"6bcb0994aa90328dc0c40fb92b8d643a5eb8f3b67ea02910ce12e82659a67733","affectsGlobalScope":true},{"version":"221eb271120cd4d89d9ddbfa86a8522dbc11bfa15279054005b3fec0090a4ae8","signature":"d3380e21e5fd13898c7d66630ee71cb4b11661793926b2dd3d6d299f3d28c262","affectsGlobalScope":true},{"version":"1997716ad9e79487029b2f2b5fb21a8345705e214fb2d9023a24e13b07299c55","signature":"5d094d040783e41837c68d4c3e967e87306ce11e90b51597045a280976b7b9bf"},{"version":"ec98c99f73a1500e8f0b332aa075bce592de771176214d0750cc6b756b77748e","signature":"3f408c8fd54940e6e6323cfcb3b13b4876274d6fba7b97ebcdc1db59ce75cea7"},{"version":"4f5b5f50068ba190707c4b983a7b4f3cfa1a3304005febf4fba24b0566b8e485","signature":"42cbc9d7230e3c63aaf6c6adcd7683fda07f8abbc2aad2ed6c683bcd314b2338"},{"version":"0371665ed19cf587cf074d8f177bcc5fb016211734fad381f132d3f7ecbe4b2f","signature":"116ef71a57257ed85808c3ded95ac9b15cf09ebc2045492e449fc011ec78f03c"},{"version":"9829a414d89aee87d219beb536d3a7769cafccfd95187e85bcd60e51a0dd77a0","signature":"8da604a4f6b32f67f99a7ab2fe6164078088b54058d286860074c592256d84c1"},{"version":"404a951395b6d33f7785bfe09d98e0bd2faffa5d5032b5e321f77fe8fae79cff","signature":"aeb871bf6e1eff136ab246a6075edef1950c43f207e6bc6c144e653cea0fd924"},{"version":"fe1693f5895dc736b71639ef0130825ac19d24ee8f08f5c8c436c8b4c2d95bb3","signature":"d54c5a048d6a78ba532fe21f448460058218cba9bbfb0af5e4f79f12f0419654"},{"version":"5cc5c9e9971b5d49b8d121f8026fcafb2af2262836650279a29904bd73fb3a55","signature":"036c603206c922e02649ba54428d742ecc7d1f324ae464e1880f7cb3533b4b57"},{"version":"22a40ba1fcadd55aa3b66b8d3e478122196443acd37d00928320a2184b8a1fa9","signature":"0e2d228bcb5cb60e9cb98f51bbaf5cbd5375581736b1040ab739d0abc5da96cd"},{"version":"362d90065c2dcfad9d969dfc43b5858f07d0011fffc2d34c41239f76a8b002aa","signature":"9076ed94a3b6f8d5ea554fc828d45ad3eb116ee23f85c413209950176651c693"},{"version":"a4eb8f0e80d683b42bc4c3a3b629d2cad96de47d6fddca836a91d9262c774f99","signature":"ccb3167030220d5b9b421a048b42e5ecbd03fc7db9efb247fc1db0e21ebfd4a6"},{"version":"be285a5e09fa89d0dc5e402a309ea399d406579b6349cd9c96fb070dbc4cc197","signature":"1f8b84a9f3f8e277e07d252c49a96bbe956433b3bd0001498c653b0be88efb5c"},{"version":"2284e7ea0fb8bd793b60f1f0d8b11c5921b9958e6c3455a39f8521d5801519d5","signature":"b5959485bdf9feb2de7125e9ac84ac272b6862e6bac7663c529d44d3c642debc"},{"version":"c7ea6b989ae71757c665195773a06229b6c400a8bc5b87ae55b44cb156fcd51f","signature":"0e2c3f98c1804024a67d8b7f3408ee650b8eb20a282cc62df20157b0010aa57c"},{"version":"651badeb01fec69a55df08d8f070c99d10b3b027fee82d61f705fe7bb683a746","signature":"4a9fb735c3fc6706354acafca41808d9a391bb1d2a60730cab56fe4003c06e45"},{"version":"c306f1ca2944898bd34a942552f03c987e2eb9357197ab48a0b547a319e2ae8e","signature":"59846f9e9eeccb4f6dd985ad897452d266011e12f1f2c86d3e996b17dd6a77ba"},{"version":"3c37961851f15e8898f0da7f7f5634031d3e16bb7c2cc1c7876d78df7b3458c0","signature":"4debdcfabbd568470cc4f1dfe3201b1d2e943cb4a424a22e20144134cdc328e4"},{"version":"9b60d9da98f0255c804ec0644ba5d7cde73a037597a5d8988c6575e360f5607f","signature":"1408c53f0c9fce53f69f915a35c640cbc3ab469b248dd8f87d0733eca8f534e1"},{"version":"4e5411ccf1bd32206479a5f1f5fd6d7e7e9b9d4e8148d9cdf6aa40dc0f200320","signature":"43e6bb65c5ded21309112a7d6133443d062e2101fba6fcd463e6a4f5c193253c"},{"version":"f9c9df7c918a823d2233c924156565ca40c4b1affd229b41ae7d572fe68720d0","signature":"942229a8d93d2a8837714fded74be03a0b317705a8a114d27913f2eb28e2514a"},{"version":"fbe120b1557a0fe25098879299cbd61c6d479d055228523596f00bba6c63af68","signature":"1a73e059471cd91f40d75bfd4209aa9a51ca679f563ca4843be691c9a1400297"},{"version":"b5ed547ed9bbd52889bc4d81776cf9a53b7358779399a4993718f02ed794b72c","signature":"b3d7afd74a29e7b47bb1ad626643c919fd50dd0b7b62695e6dbcfbb8ba0f84f6"},{"version":"bcafd309f599bfa21041602a0fa605697a99bc38ba94118ad95fb0bcf3c33095","signature":"371b4327d2f99334a1773dd24ec8e9f67c4979a157df36dac42d3c3008f85427"},{"version":"3ea9b7dffca73d95c05fe62119f18d37147f5001c006533cbd4a60d0ebe74111","signature":"35c66d321e015cb493a82b618645bf0567549497d89808567574d80d87b29721"},{"version":"1c4676a3924b7f33a2a350c200390db6132dce9497b8a800ddb0c97779c9bd0f","signature":"e2ad51d0ca0cb8d58e105afa86c92c55492644438a29f98fa0385a2a0a87a688"},{"version":"eb46ffd4c33d36b6dda6c9bb3f2d3f5f667d03147ba7bf7c93d6755c002903c6","signature":"371b4327d2f99334a1773dd24ec8e9f67c4979a157df36dac42d3c3008f85427"},{"version":"674922b2c5271c233a7e0e6828ac56f48a603fcff2d9dbaed06cbb1a90d49357","signature":"43bcc9b83211a27eed47479731ac19f23f14736b97c659642a67525dcf7f87e0"},{"version":"6cad4e92694951a5a6468ff738ac063f090041ad66bc7d014ba3cdc8552d7871","signature":"3baff830c951fe71fdfcb4451f63839606b04a9b91bd8f0bdc7344a3d1aecda1"},{"version":"61ab94986a86a555d7dc534dbe7ed537ca81d20e505eff14f410c05013f5a794","signature":"81585bae0373a65ca041937db5e3fc94b4e6b107de856446c567004e865115ab"},{"version":"810c81ba2aff9811d7c96334b13b20b7eff46f3a6f409115c17549b7adb49c4c","signature":"8548bc1d6c23c5533c9782f5130709e5e323334808c0cf5c12d67e056beb99e2"},{"version":"a20533fcf0c256a4cdecbf8c1fe5048211a12941d472f882b34ef2517abcba56","signature":"d87bd1fe16dceac65874250e6b14fb89c7afda170b74cbfd58bf33a8922c9b5d"},{"version":"6bc6c850b611869b6bc55aa85f028253e5b54baa8ba129fdf71eff28f47644a6","signature":"8548bc1d6c23c5533c9782f5130709e5e323334808c0cf5c12d67e056beb99e2"},{"version":"0ce752768e3edaaa0ca673093db2149b4ca746addaed4ffd8a0f0960c684bbda","signature":"a02bbce4e4949de343938313c14643a8d56ce4eb5d33e02f0d4c157b5bee103a"},{"version":"a01f4d8eab9895511579ea8d0b9f02ca2f64b9e4c9f0ede197a86229195d26f3","signature":"70a9a28a7f37925cadec8aa5f79d5c7756ebdb2d07066dcb4d706bc548b8913b"},{"version":"7b0005ae6b1da6e38f94bc1ca76bc6699ff89af31581d76717dc453ba12fb072","signature":"012d0ca77acc8e4f0edac2150c30fb876ecfd1d7555490b690c4b6d5d78b2f4e"},{"version":"9094f5c5fcc1a29ce038021567da32f0b88e00468a0f4fdf2c34992833895010","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"0309a01650023994ed96edbd675ea4fdc3779a823ce716ad876cc77afb792b62","impliedFormat":99},{"version":"f13d7beeea58e219daef3a40e0dc4f2bd7d9581ac04cedec236102a12dfd2090","impliedFormat":99},{"version":"48c411efce1848d1ed55de41d7deb93cbf7c04080912fd87aa517ed25ef42639","affectsGlobalScope":true,"impliedFormat":1},{"version":"a094636c05f3e75cb072684dd42cd25a4c1324bec4a866706c85c04cecd49613","affectsGlobalScope":true,"impliedFormat":99},{"version":"fe2d63fcfdde197391b6b70daf7be8c02a60afa90754a5f4a04bdc367f62793d","impliedFormat":99},{"version":"9a3e2c85ec1ab7a0874a19814cc73c691b716282cb727914093089c5a8475955","impliedFormat":99},{"version":"cbdc781d2429935c9c42acd680f2a53a9f633e8de03290ec6ea818e4f7bff19a","impliedFormat":99},{"version":"9f6d9f5dd710922f82f69abf9a324e28122b5f31ae6f6ce78427716db30a377e","impliedFormat":99},{"version":"ac2414a284bdecfd6ab7b87578744ab056cd04dd574b17853cd76830ef5b72f2","impliedFormat":99},{"version":"c3f921bbc9d2e65bd503a56fbc66da910e68467baedb0b9db0cc939e1876c0d7","impliedFormat":99},{"version":"c30a41267fc04c6518b17e55dcb2b810f267af4314b0b6d7df1c33a76ce1b330","impliedFormat":1},{"version":"72422d0bac4076912385d0c10911b82e4694fc106e2d70added091f88f0824ba","impliedFormat":1},{"version":"da251b82c25bee1d93f9fd80c5a61d945da4f708ca21285541d7aff83ecb8200","impliedFormat":1},{"version":"64db14db2bf37ac089766fdb3c7e1160fabc10e9929bc2deeede7237e4419fc8","impliedFormat":1},{"version":"98b94085c9f78eba36d3d2314affe973e8994f99864b8708122750788825c771","impliedFormat":1},{"version":"0cc99fbb161d78729d71fad66c6c363e3095862d6277160f29fa960744b785c6","affectsGlobalScope":true,"impliedFormat":99},{"version":"00ca9d3bbafeff8e06851d5a2a96f04f03cb0796fe22f527656f3735792017e8","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"8485051275168f7f612b9d48eb44041c7c992c8712a7106fb6111df9ab686aaf","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"4387a41d6502241b4042fb8aa5aa891420f8442e31eae78a5b85932e769b31a2","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"181f8edcda3b27f3a7d31ceb66a64c136e1c8be997fc0c6a466d64706dc25b06","signature":"01fc0a4e7b62a7a3f1cb3cfde004cc1a09c669d524ec67e6e4c9fb135edc04e8"},{"version":"e0f492965e29b01a38b00d3483e4b737b602459e7182ec8750ce30bbd70f3f29","signature":"1917e46bb20f4b8ae7329a48da3d80adae95340e41cc9d3f9c0efdaaaf0c83c8"},{"version":"51cd34a1359b96dff56a02e258bfc0f46ff21f90656147352b0327a817f45b02","signature":"0007f4c8720f6e3230232c627bd571a897b84d6fee55184785abbac208c9cfc9"},{"version":"b8f5a44d5b9eb4f75939e32b58fd6955e85a9473ae2baf5f7d0e68164a330cde","signature":"ac7a7801ca3eb7c0c7f7092c25cd78fdbe18c6f1ee201c88e0c0b796fd631f85"},{"version":"0258f3cbf489dd78a8a79ae1f5443c7bbc46d998ff49d604051bcb2142c29de6","signature":"a4d9dd496eebb4e35b48ae46317a288ec19fea7134cd406a74d2754c5866d05c"},{"version":"59e2388f70329204dca9654a18426edf998f1cbb87b450768bc47e8858e9c278","signature":"2fe87059fb00a4fe6ce541ebf44c5259c401d46392ca60af62af9af260526143"},{"version":"059fe9c223b7346114bfaa1689160b7819c965e8467613528809faddf6ea8927","signature":"20dac9f041c2e11569ab9fd1dfa337e53cd4fe5ffdbe1b34928c0c429876460f"},{"version":"5ea0d68267a67e6d42c8d06d7759423db243868553ff6de29a889375d16be0aa","signature":"75ad4b4b4f2c9154136e35342025c621872994118449dcdc01066f2f3391c99e"},{"version":"aac2fab9da2abedce0c232f08676b66c8f27173a61ac3a9bd5102c62d4fa81f2","signature":"6e633eac669f000d1feac3d0b3efac38fd94727b0c0c30ef12ea3f3d385f187c"},{"version":"26d0424f25f3ff2294273d9580460a561caa23f7fb9afa299dde18e672aefbf7","signature":"3c569ddb95ffbaefa6ca75998045b11df5e7056f4b1e0e0fbf9c1be1c4bfaa07"},{"version":"52c648529052539d70698b781208c3e57ddc82e045ae8fdb60c54e1838d2cdb9","signature":"bfe7d6e83896ea7ee5d9f198e4095e148050f7994d0c848653ec5b6cfc727c35"},{"version":"3d6cf5e9c053687f1d9858337122fc2d630d7ea693c67b66a353baa531c32b95","signature":"9b37defc1cf2817877d82929745263a4741c10b95e7ad1ae1b2386ec1056dc7f"},"2552a31fad45a9ed1bde87e51b038dc0e786cd364b597162263abbf57018949b",{"version":"2f9c3fd0e506287a4fda58b6256a9bcaf8034329fe8656af1e910957490f7b40","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},{"version":"ad673ea0e7d9305317f04a55f2156630b30800ed020ac605e21338aa7b034d8f","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"22fbd2eb96fdfc9dbcc49178e4da0c97f18041a81d3107021790e62eedbfee28","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"597c5690604951be6a78c5154e761c2610f4955ed6ce5e7d7fc2023efc4d5c0b","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"8df17b5e445bf40f3d99f1bca10a3b150ee7f60a22d8faaf2a684ff69db67175","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"849320fb96fc3f5eeb380c61c50d43aeac4a319b508fa1ec760a06097891e94f","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"91f443e7c22069220d39b1a6ded95121ae359aeeb1e5b8546ff206023a4a006b","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"a7f378c6abbf6c748e38bef3d8d591cee597b576b822dc3957bfbdfc6c2ed74e","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"d1ac2853bf6dc009924e5fe22fbda97f9ab27f7d777a5a77b0df09a20f555976","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"64ef0facca41a42da5ad03d67ea152ff645085fb23046a523838409edfdcc5cc","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"8ed965249f2fc55be3f279194f500c3cfb9173cae8cdf6888cc9969c021c1a1f","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"e1e88c274067db86818f0c32ce0dc2daf2f70b3ab42dd84dfb862e0aacdca9f3","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"62e7f8db393376b44589458d4a5d18647ebe2c0a265315959f80c7ff7ce5c965","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"9cac4da3e868bfb6378c4195972c7ebc7c28168c8bec818da1de07e315327a1c","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"e5c0832fca86e287d0e4ecf7fc9acb13eb8903b0a0258beb6995f695639f56ea","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"7ad12e75b22930b364e60c585138f2d92befd8cb045e46ce9203b7355197e56d","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"77f49f5df16e08608c89264a544f18daf463b9082a95c0ef9a84f2bb78aaa397","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"d7c82f9ac99d6f5ec87e34e5d8040a54526d2008c47b91732699beb760cbe784","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"cd50bb7557bc54fde2d37e42d9f00cda3c4d961b96e4ca16d9730ed8bcce2efa","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"f7ac2b5a2db2ea9bd02268f4fe810c4927a47368ce0f5a8d94b5ea2080d975a2","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"c81102ff11ec13a42c63bee5c32b4ed9c572890f02ba56259c3c147b662fd8e1","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"74ff705bc53d7e86f789331ed9e0b9ecd948b6cb8052d41744398485544c24cd","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"3f75c750cd55386705e2891a7bdf2e70e5e83d25507a9eb1a3ad3e976fe5c813","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"2fd1184a1954c3487f8b09e7314c8cb40ace4241654df3fc69c7db489ce47ede","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"6f1252aaa6926fd1f7fd067e0d9831f82aae97851c4e7f9a91bccf48d5b84a55","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"41bc23787838df96412a735d5420a544da272ce09f8b1f4cef4dda1260fcfd42","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"7fc106701726d7c9e7fad8fe26478072bc32f790b95f32302431443558dc7914","signature":"89b0f68f8f0b901f9dfff2b9e7255520283a783d6af7f2bc2953d771232317a2"},{"version":"381d27c35f5a5bf6c09dd238ec26fef30a03d12ea84589c621ebc208d7dc8378","affectsGlobalScope":true,"impliedFormat":99}],"root":[60,478,479,501,526,571,[577,586],[610,650],[667,709]],"options":{"allowJs":false,"esModuleInterop":true,"jsx":1,"module":99,"skipLibCheck":true,"strict":true,"target":9},"referencedMap":[[686,1],[687,2],[688,3],[690,4],[691,5],[689,6],[692,7],[693,8],[694,9],[695,10],[697,11],[696,12],[698,13],[699,14],[700,15],[701,16],[702,17],[703,18],[704,19],[705,20],[707,21],[708,22],[709,23],[706,24],[684,25],[685,26],[682,27],[60,28],[683,29],[478,30],[479,31],[575,32],[574,33],[225,28],[500,34],[576,35],[573,36],[572,28],[603,37],[606,28],[607,38],[604,37],[602,39],[605,40],[587,41],[588,41],[589,41],[590,41],[591,41],[592,42],[593,41],[594,41],[595,41],[596,41],[597,43],[599,44],[598,28],[600,41],[527,28],[122,45],[123,45],[124,46],[77,47],[125,48],[126,49],[127,50],[72,28],[75,51],[73,28],[74,28],[128,52],[129,53],[130,54],[131,55],[132,56],[133,57],[134,57],[135,58],[136,59],[137,60],[138,61],[78,28],[76,28],[139,62],[140,63],[141,64],[175,65],[142,39],[143,28],[144,66],[145,67],[146,68],[147,69],[148,70],[149,71],[150,72],[151,73],[152,74],[153,74],[154,75],[155,28],[156,76],[157,77],[159,78],[158,79],[160,80],[161,81],[162,82],[163,83],[164,84],[165,85],[166,86],[167,87],[168,88],[169,89],[170,90],[171,91],[172,92],[79,28],[80,28],[81,28],[119,93],[120,28],[121,28],[173,94],[174,95],[179,96],[335,97],[180,98],[178,99],[337,100],[336,101],[176,102],[333,28],[177,103],[61,28],[63,104],[332,97],[243,97],[653,28],[654,105],[655,106],[658,107],[657,28],[539,28],[550,108],[545,109],[548,110],[563,111],[552,28],[555,112],[554,113],[566,113],[553,114],[656,28],[547,115],[549,115],[541,116],[544,117],[560,116],[546,118],[540,28],[62,28],[663,119],[665,120],[664,121],[662,122],[661,28],[70,123],[424,124],[429,27],[431,125],[201,126],[229,127],[407,128],[224,129],[212,28],[193,28],[199,28],[397,130],[260,131],[200,28],[366,132],[234,133],[235,134],[331,135],[394,136],[349,137],[401,138],[402,139],[400,140],[399,28],[398,141],[231,142],[202,143],[281,28],[282,144],[197,28],[213,145],[203,146],[265,145],[262,145],[186,145],[227,147],[226,28],[406,148],[416,28],[192,28],[307,149],[308,150],[302,97],[452,28],[310,28],[311,151],[303,152],[458,153],[456,154],[451,28],[393,155],[392,28],[450,156],[304,97],[345,157],[343,158],[453,28],[457,28],[455,159],[454,28],[344,160],[445,161],[448,162],[272,163],[271,164],[270,165],[461,97],[269,166],[254,28],[464,28],[467,28],[466,97],[468,167],[182,28],[403,168],[404,169],[405,170],[215,28],[191,171],[181,28],[323,97],[184,172],[322,173],[321,174],[312,28],[313,28],[320,28],[315,28],[318,175],[314,28],[316,176],[319,177],[317,176],[198,28],[189,28],[190,145],[244,178],[245,179],[242,180],[240,181],[241,182],[237,28],[329,151],[351,151],[423,183],[432,184],[436,185],[410,186],[409,28],[257,28],[469,187],[419,188],[305,189],[306,190],[297,191],[287,28],[328,192],[288,193],[330,194],[325,195],[324,28],[326,28],[342,196],[411,197],[412,198],[290,199],[294,200],[285,201],[389,202],[418,203],[264,204],[367,205],[187,206],[417,207],[183,129],[238,28],[246,208],[378,209],[236,28],[377,210],[71,28],[372,211],[214,28],[283,212],[368,28],[188,28],[247,28],[376,213],[196,28],[252,214],[293,215],[408,216],[292,28],[375,28],[239,28],[380,217],[381,218],[194,28],[383,219],[385,220],[384,221],[217,28],[374,206],[387,222],[373,223],[379,224],[205,28],[208,28],[206,28],[210,28],[207,28],[209,28],[211,225],[204,28],[359,226],[358,28],[364,227],[360,228],[363,229],[362,229],[365,227],[361,228],[251,230],[352,231],[415,232],[471,28],[440,233],[442,234],[289,28],[441,235],[413,197],[470,236],[309,197],[195,28],[291,237],[248,238],[249,239],[250,240],[280,241],[388,241],[266,241],[353,242],[267,242],[233,243],[232,28],[357,244],[356,245],[355,246],[354,247],[414,248],[301,249],[339,250],[300,251],[334,252],[338,253],[396,254],[395,255],[391,256],[348,257],[350,258],[347,259],[386,260],[341,28],[428,28],[340,261],[390,28],[253,262],[286,168],[284,263],[255,264],[258,265],[465,28],[256,266],[259,266],[426,28],[425,28],[427,28],[463,28],[261,267],[299,97],[69,28],[346,268],[230,28],[219,269],[295,28],[434,97],[444,270],[279,97],[438,151],[278,271],[421,272],[277,270],[185,28],[446,273],[275,97],[276,97],[268,28],[218,28],[274,274],[273,275],[216,276],[296,73],[263,73],[382,28],[370,277],[369,28],[430,28],[327,278],[298,97],[422,279],[64,97],[67,280],[68,281],[65,97],[66,28],[228,282],[223,283],[222,28],[221,284],[220,28],[420,285],[433,286],[435,287],[437,288],[439,289],[443,290],[477,291],[447,291],[476,292],[449,293],[459,294],[460,295],[462,296],[472,297],[475,171],[474,28],[473,298],[497,299],[480,28],[481,299],[496,300],[499,301],[498,302],[518,303],[516,304],[517,305],[505,306],[506,304],[513,307],[504,308],[509,309],[519,28],[510,310],[515,311],[521,312],[520,313],[503,314],[511,315],[512,316],[507,317],[514,303],[508,318],[529,319],[528,320],[609,321],[601,322],[608,323],[371,41],[502,28],[524,324],[523,28],[522,28],[525,325],[564,28],[542,28],[543,326],[58,28],[59,28],[10,28],[11,28],[13,28],[12,28],[2,28],[14,28],[15,28],[16,28],[17,28],[18,28],[19,28],[20,28],[21,28],[3,28],[22,28],[23,28],[4,28],[24,28],[28,28],[25,28],[26,28],[27,28],[29,28],[30,28],[31,28],[5,28],[32,28],[33,28],[34,28],[35,28],[6,28],[39,28],[36,28],[37,28],[38,28],[40,28],[7,28],[41,28],[46,28],[47,28],[42,28],[43,28],[44,28],[45,28],[8,28],[51,28],[48,28],[49,28],[50,28],[52,28],[9,28],[53,28],[54,28],[55,28],[57,28],[56,28],[1,28],[97,327],[107,328],[96,327],[117,329],[88,330],[87,331],[116,298],[110,332],[115,333],[90,334],[104,335],[89,336],[113,337],[85,338],[84,298],[114,339],[86,340],[91,341],[92,28],[95,341],[82,28],[118,342],[108,343],[99,344],[100,345],[102,346],[98,347],[101,348],[111,298],[93,349],[94,350],[103,351],[83,352],[106,343],[105,341],[109,28],[112,353],[561,354],[558,355],[559,354],[562,356],[557,28],[538,357],[535,358],[533,359],[534,28],[531,360],[530,28],[532,361],[536,28],[537,362],[570,363],[565,364],[556,365],[551,28],[659,366],[567,367],[660,368],[568,369],[652,370],[651,371],[569,372],[666,373],[710,374],[495,375],[487,376],[494,377],[489,28],[490,28],[488,378],[491,379],[482,28],[483,28],[484,375],[486,380],[492,28],[493,381],[485,382],[501,383],[577,384],[616,385],[617,386],[619,387],[621,388],[622,388],[620,389],[627,390],[628,390],[629,390],[630,385],[632,385],[631,385],[633,385],[634,391],[636,392],[637,393],[638,394],[639,393],[640,393],[641,395],[644,396],[645,397],[646,396],[643,398],[670,31],[681,399],[647,28],[671,28],[676,400],[677,400],[678,401],[679,402],[672,403],[673,403],[674,404],[675,404],[648,28],[680,405],[583,28],[578,384],[649,406],[579,407],[581,28],[585,408],[586,28],[610,409],[584,28],[624,28],[623,28],[582,28],[611,410],[642,411],[580,412],[625,28],[618,413],[612,414],[614,415],[626,416],[635,417],[613,418],[615,419],[526,420],[650,383],[667,421],[668,422],[669,423],[571,424]],"affectedFilesPendingEmit":[686,687,688,690,691,689,692,693,694,695,697,696,698,699,700,701,702,703,704,705,707,708,709,706,684,685,683,479,501,577,616,617,619,621,622,620,627,628,629,630,632,631,633,634,636,637,638,639,640,641,644,645,646,643,670,681,647,671,676,677,678,679,672,673,674,675,648,680,583,578,649,579,581,585,586,610,584,624,623,582,611,642,580,625,618,612,614,626,635,613,615,526,650,667,668,669,571],"version":"5.9.3"} \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..314408d --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from "vitest/config"; +import path from "node:path"; + +export default defineConfig({ + resolve: { + alias: { + "@": path.resolve(__dirname, "src") + } + }, + test: { + environment: "node", + include: ["tests/**/*.test.ts"] + } +});