commit 4681b1a3c889ef27e5e2c816095f79218b596468 Author: Josh Myers <15sha@COMMAND-SUIT.Nanotech.ops.com> Date: Thu Apr 9 20:36:10 2026 -0700 initial commit diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..8e83af2 --- /dev/null +++ b/.env.example @@ -0,0 +1,9 @@ +# Database +DATABASE_URL=postgresql://user:password@localhost:5432/erp_platform + +# Authentication +NEXTAUTH_SECRET=your-secret-key-here +NEXTAUTH_URL=http://localhost:3000 + +# AI Integration +ANTHROPIC_API_KEY=your-anthropic-api-key-here diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..379af33 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Dependencies +node_modules +/.pnp +.pnp.js + +# Testing +/coverage + +# Next.js +/.next/ +/out/ + +# Production +/build + +# Misc +.DS_Store +*.pem + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE +.vscode +.idea +*.swp +*.swo +*~ + +# OS +Thumbs.db + +# Prisma +prisma/migrations diff --git a/API_ENDPOINTS.md b/API_ENDPOINTS.md new file mode 100644 index 0000000..a7b41aa --- /dev/null +++ b/API_ENDPOINTS.md @@ -0,0 +1,243 @@ +# Bank Transaction and Payment Recording Endpoints + +## Bank Transaction Import API + +### Endpoint: POST `/api/bank-transactions/import` + +Import multiple bank transactions in bulk. + +**Request Body:** +```json +{ + "bankAccountId": "uuid-of-bank-account", + "transactions": [ + { + "transactionDate": "2024-01-15", + "transactionType": "DEBIT", + "amount": 150.50, + "description": "Office Supplies Purchase", + "referenceNumber": "REF-001", + "oppositeParty": "Office Depot" + }, + { + "transactionDate": "2024-01-16", + "transactionType": "CREDIT", + "amount": 2500.00, + "description": "Customer Payment - Acme Corp", + "referenceNumber": "INV-2024-001", + "oppositeParty": "Acme Corp" + } + ] +} +``` + +**Response (201 Created):** +```json +{ + "success": true, + "imported": 2, + "message": "Successfully imported 2 transaction(s)" +} +``` + +**Notes:** +- `transactionType` must be one of: `DEBIT`, `CREDIT` +- `amount` must be a positive number +- `referenceNumber` and `oppositeParty` are optional +- The bank account must exist and belong to the organization + +--- + +## CSV Parser API + +### Endpoint: POST `/api/bank-transactions/parse-csv` + +Parse a CSV file to extract transactions for preview before import. + +**Request:** Form Data with file upload +``` +Content-Type: multipart/form-data + +file: +``` + +**Supported CSV Formats:** + +#### Format 1: Date, Description, Amount +```csv +Date,Description,Amount +2024-01-15,Office Supplies,150.50 +2024-01-16,Client Payment,2500.00 +``` + +#### Format 2: Date, Description, Debit, Credit +```csv +Date,Description,Debit,Credit +2024-01-15,Office Supplies,150.50,0 +2024-01-16,Client Payment,0,2500.00 +``` + +**Response (200 OK):** +```json +{ + "success": true, + "count": 2, + "transactions": [ + { + "transactionDate": "2024-01-15", + "description": "Office Supplies", + "transactionType": "DEBIT", + "amount": 150.50 + }, + { + "transactionDate": "2024-01-16", + "description": "Client Payment", + "transactionType": "CREDIT", + "amount": 2500.00 + } + ], + "message": "Parsed 2 transaction(s) from CSV" +} +``` + +**Error Response (400 Bad Request):** +```json +{ + "error": "CSV must have 'Date' and 'Description' columns" +} +``` + +--- + +## Payment Recording API + +### Endpoint: POST `/api/payments` + +Record a payment against an invoice. + +**Request Body:** +```json +{ + "paymentDate": "2024-01-20", + "paymentMethod": "ACH", + "paymentAmount": 1500.00, + "customerId": "uuid-of-customer", + "invoiceId": "uuid-of-invoice", + "paymentAllocations": [ + { + "invoiceId": "uuid-of-invoice", + "allocatedAmount": 1500.00 + } + ] +} +``` + +**Response (201 Created):** +```json +{ + "id": "uuid-of-payment", + "paymentNumber": "PAY-2024-0001", + "paymentDate": "2024-01-20", + "paymentMethod": "ACH", + "paymentAmount": 1500.00, + "totalPaymentAmount": 1500.00, + "status": "COMPLETED", + "memo": null, + "vendorId": null, + "customerId": "uuid-of-customer", + "invoiceId": "uuid-of-invoice", + "paymentAllocations": [ + { + "id": "uuid-of-allocation", + "invoiceId": "uuid-of-invoice", + "invoiceNumber": "INV-AR-2024-0001", + "allocatedAmount": 1500.00, + "allocationDate": "2024-01-20T00:00:00.000Z" + } + ] +} +``` + +**Supported Payment Methods:** +- `ACH` +- `WIRE` +- `CHECK` +- `CREDIT_CARD` +- `BANK_TRANSFER` +- `CASH` +- `OTHER` + +**Notes:** +- The payment automatically updates the invoice's `paidAmount` and `balanceDue` +- Invoice status is updated to `PAID` when balance due reaches 0, or `PARTIALLY_PAID` if there's still a balance + +--- + +## UI Components + +### AR Invoice Detail Page + +**Location:** `/src/app/(dashboard)/finance/ar/invoice/[invoiceId]/page.tsx` + +Features: +- "Record Payment" button in the Actions section +- Payment recording modal with form +- Auto-opens when navigating with query parameter `?action=payment` +- Displays payment history +- Updates automatically after successful payment + +**Payment Form Fields:** +- Payment Amount (required, defaults to balance due suggestion) +- Payment Date (required, defaults to today) +- Payment Method (required, dropdown with standard methods) + +--- + +## Example Workflow + +### 1. Upload and Parse CSV + +```bash +curl -X POST http://localhost:3000/api/bank-transactions/parse-csv \ + -F "file=@transactions.csv" +``` + +### 2. Review Parsed Transactions + +The response shows all parsed transactions for preview. + +### 3. Import Transactions + +```bash +curl -X POST http://localhost:3000/api/bank-transactions/import \ + -H "Content-Type: application/json" \ + -d '{ + "bankAccountId": "account-uuid", + "transactions": [...parsed transactions...] + }' +``` + +### 4. Record Payment + +Navigate to `/finance/ar/invoice/{invoiceId}` and click "Record Payment" button, or directly navigate to `/finance/ar/invoice/{invoiceId}?action=payment` to auto-open the payment modal. + +--- + +## Error Handling + +All endpoints return appropriate HTTP status codes: + +- `200 OK` - Successful read operation +- `201 Created` - Successful create operation +- `400 Bad Request` - Validation error or missing required fields +- `404 Not Found` - Resource not found (bank account, invoice, etc.) +- `409 Conflict` - Duplicate record +- `500 Internal Server Error` - Server error + +Error responses include an `error` field with a descriptive message: + +```json +{ + "error": "Missing required fields: bankAccountId, transactions" +} +``` diff --git a/DEVELOPMENT_GUIDE.md b/DEVELOPMENT_GUIDE.md new file mode 100644 index 0000000..9d469ff --- /dev/null +++ b/DEVELOPMENT_GUIDE.md @@ -0,0 +1,357 @@ +# Development Guide: Bank Transactions & Payment Recording + +Complete implementation of bank transaction CSV import and AR invoice payment recording for the ERP platform. + +## Quick Links + +### Documentation +- **API_ENDPOINTS.md** - Complete API reference with examples +- **IMPLEMENTATION_SUMMARY.md** - Technical architecture and implementation details +- **EXAMPLE_CSVs.md** - Sample CSV files and testing guide +- **FRONTEND_INTEGRATION_GUIDE.md** - Frontend code examples and patterns + +### Code Files +- **API: Bank Transaction Import** - `/src/app/api/bank-transactions/import/route.ts` +- **API: CSV Parser** - `/src/app/api/bank-transactions/parse-csv/route.ts` +- **UI: AR Invoice Detail** - `/src/app/(dashboard)/finance/ar/invoice/[invoiceId]/page.tsx` +- **UI: AR List Page** - `/src/app/(dashboard)/finance/ar/page.tsx` + +## What Was Built + +### Task 1: Bank Transaction CSV Import Endpoint + +Two new API endpoints for importing bank transactions from CSV files: + +1. **POST `/api/bank-transactions/parse-csv`** + - Accept CSV file upload + - Parse and validate + - Return preview of transactions + - No external dependencies (pure TypeScript CSV parser) + +2. **POST `/api/bank-transactions/import`** + - Bulk import validated transactions + - Atomic operation (all or nothing) + - Verify bank account ownership + - Return count of imported transactions + +**Features:** +- Supports 2 CSV formats (Amount or Debit/Credit columns) +- Handles quoted fields with commas +- Handles escaped quotes +- Auto-detects CSV format +- Comprehensive validation +- Organization isolation + +### Task 2: AR Invoice Payment Recording + +Enhanced AR invoice detail page with payment recording capability: + +1. **Payment Recording Modal** + - Form for entering payment details + - Payment amount (validated > 0) + - Payment date (date picker) + - Payment method (dropdown with 7 options) + - Error handling and loading states + +2. **Integration with Existing Payment API** + - Uses existing `/api/payments` endpoint + - Automatically updates invoice balances + - Updates invoice status (PAID or PARTIALLY_PAID) + - Creates payment allocations + +3. **AR List Page Integration** + - "Record Payment" action in context menu + - Navigates to invoice detail with auto-opening modal + - Direct payment entry from list + +**Features:** +- Modal auto-opens with query parameter `?action=payment` +- Form validation on client and server +- Error display with helpful messages +- Loading state during submission +- Auto-refresh after successful payment +- Maintains invoice context + +## Architecture + +### Authentication & Multi-Tenancy +- All endpoints use `getOrganization()` for tenant isolation +- Bank account ownership verified before import +- Organization ID included in all queries + +### Error Handling +- Standard HTTP status codes +- Descriptive error messages +- Input validation on both client and server +- Proper exception handling with try-catch + +### Data Flow + +#### CSV Import +``` +User uploads CSV + ↓ +Parse endpoint validates and extracts transactions + ↓ +UI displays preview of parsed transactions + ↓ +User confirms import + ↓ +Import endpoint validates and bulk inserts + ↓ +Success response with transaction count + ↓ +Transactions appear in bank account +``` + +#### Payment Recording +``` +User clicks "Record Payment" button + ↓ +Modal form opens + ↓ +User enters payment details + ↓ +User submits form + ↓ +Payment endpoint creates payment record + ↓ +Invoice balances updated + ↓ +Invoice status updated + ↓ +Modal closes, page refreshes +``` + +## API Reference + +### Parse CSV +```bash +POST /api/bank-transactions/parse-csv +Content-Type: multipart/form-data + +file: [CSV file] +``` + +Response: +```json +{ + "success": true, + "count": 100, + "transactions": [ + { + "transactionDate": "2024-01-15", + "description": "Office Supplies", + "transactionType": "DEBIT", + "amount": 150.50 + } + ] +} +``` + +### Import Transactions +```bash +POST /api/bank-transactions/import +Content-Type: application/json + +{ + "bankAccountId": "uuid", + "transactions": [...] +} +``` + +Response: +```json +{ + "success": true, + "imported": 100, + "message": "Successfully imported 100 transaction(s)" +} +``` + +### Record Payment +```bash +POST /api/payments +Content-Type: application/json + +{ + "paymentDate": "2024-01-20", + "paymentMethod": "ACH", + "paymentAmount": 1500.00, + "customerId": "uuid", + "invoiceId": "uuid", + "paymentAllocations": [...] +} +``` + +Response: Created payment object with payment number and allocations + +## Development Workflow + +### 1. Testing CSV Import + +**Prepare Test Data:** +1. Create or download CSV file (see EXAMPLE_CSVs.md) +2. Ensure correct format with Date, Description, Amount columns +3. Verify bank account exists in system + +**Test Parse Endpoint:** +```bash +curl -X POST http://localhost:3000/api/bank-transactions/parse-csv \ + -F "file=@test.csv" +``` + +**Test Import Endpoint:** +```bash +curl -X POST http://localhost:3000/api/bank-transactions/import \ + -H "Content-Type: application/json" \ + -d '{ + "bankAccountId": "your-account-id", + "transactions": [... parsed transactions ...] + }' +``` + +### 2. Testing Payment Recording + +**Manual Testing:** +1. Log into application +2. Navigate to AR invoices +3. Click on any open invoice +4. Click "Record Payment" button +5. Enter payment details +6. Submit form +7. Verify invoice status updates + +**Test with Query Parameter:** +``` +/finance/ar/invoice/{invoiceId}?action=payment +``` +Should auto-open payment modal. + +### 3. Frontend Integration + +Build the CSV import UI using FRONTEND_INTEGRATION_GUIDE.md as reference: +- File upload component +- CSV preview table +- Bank account selector +- Import confirmation + +## CSV Format Examples + +### Format 1: Date, Description, Amount +```csv +Date,Description,Amount +2024-01-15,Office Supplies,150.50 +2024-01-16,Client Payment,2500.00 +``` + +### Format 2: Date, Description, Debit, Credit +```csv +Date,Description,Debit,Credit +2024-01-15,Office Supplies,150.50,0 +2024-01-16,Client Payment,0,2500.00 +``` + +### Format 3: With Quoted Descriptions +```csv +Date,Description,Amount +2024-01-15,"Office Supplies, Inc., Springfield",150.50 +2024-01-16,"Client Payment, Invoice #INV-123",2500.00 +``` + +See EXAMPLE_CSVs.md for more examples and bank-specific formats. + +## Common Issues & Troubleshooting + +### CSV Not Parsing +- Check column headers (Date, Description required) +- Verify file is valid CSV format +- Check for special characters in descriptions +- Ensure amounts are numeric without currency symbols + +### Import Fails +- Verify bank account ID is correct +- Check organization ownership +- Validate transaction types are DEBIT or CREDIT +- Ensure amounts are positive numbers + +### Payment Not Recording +- Verify customer exists +- Verify invoice exists and belongs to customer +- Check invoice status (some statuses may be readonly) +- Verify payment amount is greater than 0 + +### Modal Not Opening +- Check URL has `?action=payment` query parameter +- Verify invoice detail page loads successfully +- Check browser console for JavaScript errors +- Clear browser cache and reload + +## Performance Considerations + +### CSV Import +- Supports files up to 10MB (50,000+ transactions) +- Bulk import in single database operation +- No row-by-row processing overhead +- Consider pagination for preview if 1000+ transactions + +### Payment Recording +- Modal form lightweight component +- Single API call per payment +- Invoice refetch may take few seconds +- Fallback to page refresh if needed + +## Security Notes + +### Authentication +- All endpoints require valid session +- Organization isolation enforced +- Bank account ownership verified + +### Input Validation +- Transaction amounts must be positive +- Transaction types must be valid enum +- Bank account must belong to organization +- Customer and invoice must exist and match organization + +### Data Protection +- CSV data validated before import +- Transactions created with status PENDING +- Organization ID required for all queries +- Proper HTTP status codes for errors + +## Future Enhancements + +1. **CSV Column Mapping** + - Allow users to map custom CSV columns + - Save mappings for future imports + +2. **Batch Payment Import** + - Import payments from CSV + - Auto-match to invoices + - Reconciliation matching + +3. **Payment Verification** + - Confirm payment details (routing numbers, etc.) + - Store payment references + - Payment reconciliation workflow + +4. **Webhook Support** + - Receive payment notifications + - Auto-create payment records + - Real-time reconciliation + +5. **Advanced Reporting** + - Import history and audit trail + - Failed transaction log + - Reconciliation reports + +## Support & Questions + +For questions about implementation, refer to: +1. **API_ENDPOINTS.md** - API specifications +2. **IMPLEMENTATION_SUMMARY.md** - Technical details +3. **FRONTEND_INTEGRATION_GUIDE.md** - Code examples +4. **EXAMPLE_CSVs.md** - CSV format guide + +All code follows existing ERP platform patterns and conventions. diff --git a/EXAMPLE_CSVs.md b/EXAMPLE_CSVs.md new file mode 100644 index 0000000..87a1edb --- /dev/null +++ b/EXAMPLE_CSVs.md @@ -0,0 +1,300 @@ +# Example Bank CSV Files + +## Format 1: Date, Description, Amount + +This is the most common format from bank exports. + +### Example: `bank_export_standard.csv` +```csv +Date,Description,Amount +2024-01-02,ACH WITHDRAWAL - RENT PAYMENT,5000.00 +2024-01-03,DEPOSIT - ACME CORP PAYMENT,15000.50 +2024-01-04,ELECTRONIC PAYMENT - UTILITIES,850.25 +2024-01-05,"CHECK #1001 - OFFICE SUPPLIES, INC",1250.00 +2024-01-08,BANK FEE,25.00 +2024-01-10,DEPOSIT - CUSTOMER ABC LLC,3500.00 +2024-01-12,ACH WITHDRAWAL - PAYROLL,12500.00 +2024-01-15,WIRE TRANSFER OUT - SUPPLIER PAYMENT,8900.00 +2024-01-16,DEPOSIT - RETURNED CHECK,500.00 +2024-01-18,ONLINE PAYMENT - LOAN PAYMENT,2000.00 +2024-01-20,ACH WITHDRAWAL - TAXES QUARTERLY,5000.00 +2024-01-22,DEPOSIT - CONSULTING SERVICES,4500.00 +2024-01-25,CHECK #1002 - EQUIPMENT LEASE,1800.00 +2024-01-28,BANK INTEREST CREDIT,150.00 +2024-01-30,ACH WITHDRAWAL - INSURANCE,750.00 +``` + +**How it's parsed:** +- Debit: Single amount (interpreted as DEBIT/withdrawal) +- Credit: Single amount (if negative, interpreted as CREDIT/deposit) +- All amounts are assumed DEBIT by default +- Date format: YYYY-MM-DD + +--- + +## Format 2: Date, Description, Debit, Credit + +This format explicitly shows debits and credits, common in business bank statements. + +### Example: `bank_export_debit_credit.csv` +```csv +Date,Description,Debit,Credit +2024-01-02,ACH WITHDRAWAL - RENT PAYMENT,5000.00, +2024-01-03,DEPOSIT - ACME CORP PAYMENT,,15000.50 +2024-01-04,ELECTRONIC PAYMENT - UTILITIES,850.25, +2024-01-05,"CHECK #1001 - OFFICE SUPPLIES, INC",1250.00, +2024-01-08,BANK FEE,25.00, +2024-01-10,DEPOSIT - CUSTOMER ABC LLC,,3500.00 +2024-01-12,ACH WITHDRAWAL - PAYROLL,12500.00, +2024-01-15,WIRE TRANSFER OUT - SUPPLIER PAYMENT,8900.00, +2024-01-16,DEPOSIT - RETURNED CHECK,,500.00 +2024-01-18,ONLINE PAYMENT - LOAN PAYMENT,2000.00, +2024-01-20,ACH WITHDRAWAL - TAXES QUARTERLY,5000.00, +2024-01-22,DEPOSIT - CONSULTING SERVICES,,4500.00 +2024-01-25,CHECK #1002 - EQUIPMENT LEASE,1800.00, +2024-01-28,BANK INTEREST CREDIT,,150.00 +2024-01-30,ACH WITHDRAWAL - INSURANCE,750.00, +``` + +**How it's parsed:** +- If Debit column has value: transaction type is DEBIT, amount is Debit value +- If Credit column has value: transaction type is CREDIT, amount is Credit value +- Both columns cannot have values in same row +- Empty string or 0 in column means no transaction + +--- + +## Format 3: With Quoted Descriptions (Commas in Description) + +Handles bank statements where description contains commas. + +### Example: `bank_export_quoted.csv` +```csv +Date,Description,Amount +2024-01-05,"CHECK #1001 - OFFICE SUPPLIES, INC, Springfield, IL",1250.00 +2024-01-10,"DEPOSIT - CUSTOMER ABC LLC, Invoice #INV-2024-001, Reference: PO-5555",3500.00 +2024-02-01,"WIRE TRANSFER - VENDOR XYZ, Invoice #INV-12345, Amount $8900, Reference Code ABC123",8900.00 +2024-02-15,"ACH PAYMENT - MULTIPLE INVOICES, Details: INV-001 $500, INV-002 $750, INV-003 $1000",2250.00 +``` + +**Key Features:** +- Descriptions with commas are wrapped in quotes: `"Description, with, commas"` +- Quotes are properly handled by the CSV parser +- Real-world bank statements often include detailed transaction info + +--- + +## Format 4: Mixed with Escaped Quotes + +Handles descriptions that contain both commas AND quotes. + +### Example: `bank_export_escaped_quotes.csv` +```csv +Date,Description,Amount +2024-01-20,"VENDOR INVOICE - Widget Corp, Item: ""Ultra Premium Widgets"", Qty: 500",2500.00 +2024-02-10,"CUSTOMER DEPOSIT - ABC Corp, Receipt: ""2024-Feb-Invoice"", Amount: USD 5000",5000.00 +``` + +**Key Features:** +- Quotes inside quoted strings are escaped with double-quotes: `"The ""thing"" is..."` +- Parser handles these correctly +- Uncommon but can appear in detailed bank statements + +--- + +## API Request Examples + +### Parse CSV (Form Data) + +```bash +curl -X POST http://localhost:3000/api/bank-transactions/parse-csv \ + -F "file=@bank_export_standard.csv" +``` + +**Response:** +```json +{ + "success": true, + "count": 15, + "transactions": [ + { + "transactionDate": "2024-01-02", + "description": "ACH WITHDRAWAL - RENT PAYMENT", + "transactionType": "DEBIT", + "amount": 5000.00 + }, + { + "transactionDate": "2024-01-03", + "description": "DEPOSIT - ACME CORP PAYMENT", + "transactionType": "DEBIT", + "amount": 15000.50 + }, + ... + ], + "message": "Parsed 15 transaction(s) from CSV" +} +``` + +### Import Transactions (JSON) + +```bash +curl -X POST http://localhost:3000/api/bank-transactions/import \ + -H "Content-Type: application/json" \ + -d '{ + "bankAccountId": "550e8400-e29b-41d4-a716-446655440000", + "transactions": [ + { + "transactionDate": "2024-01-02", + "description": "ACH WITHDRAWAL - RENT PAYMENT", + "transactionType": "DEBIT", + "amount": 5000.00, + "referenceNumber": "ACH-123456", + "oppositeParty": "Landlord LLC" + }, + { + "transactionDate": "2024-01-03", + "description": "DEPOSIT - ACME CORP PAYMENT", + "transactionType": "DEBIT", + "amount": 15000.50, + "referenceNumber": "INV-2024-001", + "oppositeParty": "Acme Corp" + } + ] + }' +``` + +**Response:** +```json +{ + "success": true, + "imported": 2, + "message": "Successfully imported 2 transaction(s)" +} +``` + +--- + +## Common Bank CSV Exports + +### Chase Business Banking +Typically uses: `Date, Description, Amount` +- Date format: MM/DD/YYYY +- Description includes transaction type and details +- Single amount column (positive = debit) + +### Bank of America +Typically uses: `Date, Description, Debit, Credit` +- Date format: MM/DD/YYYY +- Description is brief +- Explicit debit/credit columns + +### Wells Fargo Business +Typically uses: `Date, Description, Amount` +- Date format: M/D/YYYY +- Description is detailed +- Amount is always positive + +### Quickbooks Export +Typically uses: `Date, Reference, Amount, Description` +- Can be remapped to standard format +- Date format: M/D/YYYY +- Amount includes sign (negative = credit) + +--- + +## Data Quality Notes + +### Best Practices for CSV Uploads + +1. **Remove headers:** API expects headers in first row +2. **Check date format:** Should be YYYY-MM-DD or MM/DD/YYYY +3. **Consistent amounts:** All positive numbers (debit/credit indicated by column) +4. **No special formatting:** Avoid currency symbols ($), commas in amounts (500.00, not 500,00) +5. **Quoted descriptions:** Use quotes if description contains commas +6. **No summary rows:** Remove total/balance rows at end of file + +### Invalid Examples (Will Fail) + +```csv +Date,Description,$Amount +1/2/24,Rent Payment,"$5,000.00" +1/3/24,Deposit,15000.50 +``` +**Problems:** +- Currency symbol in header ($Amount) +- Non-standard date format (1/2/24) +- Currency formatting in amount ($5,000.00) + +### Valid Examples (Will Succeed) + +```csv +Date,Description,Amount +2024-01-02,Rent Payment,5000.00 +2024-01-03,Deposit,15000.50 +``` + +--- + +## Testing Workflow + +### Step 1: Prepare CSV +Use one of the example files above or export from your bank. + +### Step 2: Parse for Preview +```bash +curl -X POST http://localhost:3000/api/bank-transactions/parse-csv \ + -F "file=@bank_export.csv" +``` +Review the parsed transactions in the response. + +### Step 3: Adjust if Needed +If parsing fails, check: +- CSV has required columns (Date, Description, Amount or Debit/Credit) +- Date format is standard (YYYY-MM-DD or MM/DD/YYYY) +- Descriptions with commas are quoted +- No extra rows (headers, totals, etc.) + +### Step 4: Import +Once happy with preview, send parsed transactions to import endpoint. + +```bash +curl -X POST http://localhost:3000/api/bank-transactions/import \ + -H "Content-Type: application/json" \ + -d '{ + "bankAccountId": "your-account-uuid", + "transactions": [... from parse response ...] + }' +``` + +### Step 5: Verify in UI +Log in and check that transactions appear in: +- Bank Transactions list view +- Bank Account details +- Cash position report + +--- + +## Troubleshooting + +### "CSV must have 'Date' and 'Description' columns" +- Check header row for exact column names +- Use: `Date` and `Description` (case-sensitive) +- Or: `date`, `description` (lowercase works too) + +### "CSV must have 'Amount' or 'Debit'/'Credit' columns" +- Format 1: Include `Amount` column +- Format 2: Include both `Debit` AND `Credit` columns +- Cannot mix formats in same file + +### "CSV file is empty" +- Check that file was uploaded successfully +- File must have at least header + 1 data row + +### "Cannot read property 'toLowerCase' of null" +- Likely missing required columns +- Verify CSV header row has Date and Description + +### Transactions show with wrong type (DEBIT vs CREDIT) +- In Format 1 (single Amount column), all treated as DEBIT +- Use Format 2 (Debit/Credit columns) for mixed transaction types +- Or ensure negative amounts are handled correctly diff --git a/FRONTEND_INTEGRATION_GUIDE.md b/FRONTEND_INTEGRATION_GUIDE.md new file mode 100644 index 0000000..b106761 --- /dev/null +++ b/FRONTEND_INTEGRATION_GUIDE.md @@ -0,0 +1,607 @@ +# Frontend Integration Guide + +## Bank Transaction CSV Import UI + +### Where to Add the UI + +Create a new page or add to an existing bank management section: +- Suggested location: `/src/app/(dashboard)/finance/treasury/bank-transactions/import` +- Or: Add as a tab in `/finance/treasury` page + +### Component Structure + +```tsx +'use client'; + +import { useState } from 'react'; +import { Upload, CheckCircle, AlertCircle, Loader2 } from 'lucide-react'; + +interface ParsedTransaction { + transactionDate: string; + description: string; + transactionType: 'DEBIT' | 'CREDIT'; + amount: number; +} + +export default function BankTransactionImportPage() { + const [file, setFile] = useState(null); + const [parsing, setParsing] = useState(false); + const [parseError, setParseError] = useState(null); + const [parsedTransactions, setParsedTransactions] = useState([]); + const [importing, setImporting] = useState(false); + const [importError, setImportError] = useState(null); + const [bankAccountId, setBankAccountId] = useState(''); + + // Step 1: Parse CSV + const handleFileParse = async (e: React.ChangeEvent) => { + const selectedFile = e.target.files?.[0]; + if (!selectedFile) return; + + setFile(selectedFile); + setParsing(true); + setParseError(null); + + try { + const formData = new FormData(); + formData.append('file', selectedFile); + + const response = await fetch('/api/bank-transactions/parse-csv', { + method: 'POST', + body: formData, + }); + + if (!response.ok) { + const error = await response.json(); + setParseError(error.error || 'Failed to parse CSV'); + setParsedTransactions([]); + return; + } + + const data = await response.json(); + setParsedTransactions(data.transactions); + } catch (error) { + setParseError( + error instanceof Error ? error.message : 'Error parsing CSV file' + ); + setParsedTransactions([]); + } finally { + setParsing(false); + } + }; + + // Step 2: Import transactions + const handleImport = async () => { + if (!bankAccountId) { + setImportError('Please select a bank account'); + return; + } + + if (parsedTransactions.length === 0) { + setImportError('No transactions to import'); + return; + } + + setImporting(true); + setImportError(null); + + try { + const response = await fetch('/api/bank-transactions/import', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + bankAccountId, + transactions: parsedTransactions, + }), + }); + + if (!response.ok) { + const error = await response.json(); + setImportError(error.error || 'Failed to import transactions'); + return; + } + + const data = await response.json(); + // Success - reset form and show success message + setFile(null); + setParsedTransactions([]); + setBankAccountId(''); + // Show success toast/notification + console.log(`Successfully imported ${data.imported} transactions`); + } catch (error) { + setImportError( + error instanceof Error ? error.message : 'Error importing transactions' + ); + } finally { + setImporting(false); + } + }; + + return ( +
+ {/* File Upload Section */} +
+

+ Upload Bank Transactions +

+ +
+ +
+ +
+

+ Supported formats: CSV with columns for Date, Description, and Amount + (or Debit/Credit) +

+
+ + {parsing && ( +
+ + Parsing CSV... +
+ )} + + {parseError && ( +
+

Error parsing CSV

+

{parseError}

+
+ )} +
+ + {/* Preview Section */} + {parsedTransactions.length > 0 && ( +
+

+ Preview: {parsedTransactions.length} Transactions +

+ +
+ + + + + + + + + + + {parsedTransactions.map((tx, idx) => ( + + + + + + + ))} + +
+ Date + + Description + + Type + + Amount +
{tx.transactionDate} + {tx.description.length > 50 + ? tx.description.substring(0, 50) + '...' + : tx.description} + + + {tx.transactionType} + + + ${tx.amount.toFixed(2)} +
+
+ + {/* Bank Account Selection */} +
+ + +
+ + {importError && ( +
+

Import Error

+

{importError}

+
+ )} + +
+ + +
+
+ )} +
+ ); +} +``` + +--- + +## Payment Recording UI + +### Already Implemented + +The payment recording modal is already built into the AR Invoice Detail page: + +**Location:** `/src/app/(dashboard)/finance/ar/invoice/[invoiceId]/page.tsx` + +**How to Use:** +1. Navigate to any AR invoice +2. Click "Record Payment" button in Actions section +3. Fill in the payment form: + - Amount (required) + - Date (required) + - Method (required: ACH, WIRE, CHECK, etc.) +4. Click "Record Payment" +5. Page refreshes to show updated invoice status + +**Direct Navigation:** +Users can also navigate directly to the payment form: +``` +/finance/ar/invoice/{invoiceId}?action=payment +``` + +This auto-opens the payment modal. + +--- + +## Bank Account Selection Component + +### Reusable Component for Bank Account Dropdown + +```tsx +import { useState, useEffect } from 'react'; + +interface BankAccount { + id: string; + accountName: string; + accountNumberMasked: string; + bankName: string; + currentBalance: number; +} + +interface BankAccountSelectProps { + value: string; + onChange: (value: string) => void; + required?: boolean; + disabled?: boolean; +} + +export function BankAccountSelect({ + value, + onChange, + required = false, + disabled = false, +}: BankAccountSelectProps) { + const [accounts, setAccounts] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + const fetchAccounts = async () => { + try { + const response = await fetch('/api/bank-accounts'); + if (response.ok) { + const data = await response.json(); + setAccounts(data); + } + } catch (error) { + console.error('Failed to fetch bank accounts', error); + } finally { + setLoading(false); + } + }; + + fetchAccounts(); + }, []); + + return ( + + ); +} +``` + +--- + +## Form Validation Helpers + +### Utility Functions for Form Validation + +```tsx +export function validateAmount(value: string | number): string | null { + const amount = parseFloat(String(value)); + if (isNaN(amount)) { + return 'Amount must be a valid number'; + } + if (amount <= 0) { + return 'Amount must be greater than 0'; + } + return null; +} + +export function validateDate(value: string): string | null { + const date = new Date(value); + if (isNaN(date.getTime())) { + return 'Invalid date format'; + } + // Don't allow future dates + if (date > new Date()) { + return 'Date cannot be in the future'; + } + return null; +} + +export function validateFileSize( + file: File, + maxSizeMB: number = 10 +): string | null { + const maxBytes = maxSizeMB * 1024 * 1024; + if (file.size > maxBytes) { + return `File size must be less than ${maxSizeMB}MB`; + } + return null; +} + +export function validateCSVFile(file: File): string | null { + if (!file.name.endsWith('.csv')) { + return 'File must be a CSV file (.csv)'; + } + const sizeError = validateFileSize(file, 10); + if (sizeError) return sizeError; + return null; +} +``` + +--- + +## API Integration Patterns + +### Fetch Bank Accounts + +```tsx +async function fetchBankAccounts() { + const response = await fetch('/api/bank-accounts'); + if (!response.ok) throw new Error('Failed to fetch accounts'); + return response.json(); +} +``` + +### Parse CSV + +```tsx +async function parseCSV(file: File) { + const formData = new FormData(); + formData.append('file', file); + + const response = await fetch('/api/bank-transactions/parse-csv', { + method: 'POST', + body: formData, + }); + + if (!response.ok) { + const error = await response.json(); + throw new Error(error.error); + } + + return response.json(); +} +``` + +### Import Transactions + +```tsx +async function importTransactions( + bankAccountId: string, + transactions: any[] +) { + const response = await fetch('/api/bank-transactions/import', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + bankAccountId, + transactions, + }), + }); + + if (!response.ok) { + const error = await response.json(); + throw new Error(error.error); + } + + return response.json(); +} +``` + +### Record Payment + +```tsx +async function recordPayment( + customerId: string, + invoiceId: string, + paymentData: { + paymentDate: string; + paymentMethod: string; + paymentAmount: number; + } +) { + const response = await fetch('/api/payments', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + customerId, + invoiceId, + ...paymentData, + paymentAllocations: [ + { + invoiceId, + allocatedAmount: paymentData.paymentAmount, + }, + ], + }), + }); + + if (!response.ok) { + const error = await response.json(); + throw new Error(error.error); + } + + return response.json(); +} +``` + +--- + +## Toast/Notification Integration + +Add success/error notifications to your pages: + +```tsx +import { useState } from 'react'; + +function useNotification() { + const [notification, setNotification] = useState<{ + type: 'success' | 'error' | 'info'; + message: string; + } | null>(null); + + return { + notification, + showSuccess: (message: string) => { + setNotification({ type: 'success', message }); + setTimeout(() => setNotification(null), 3000); + }, + showError: (message: string) => { + setNotification({ type: 'error', message }); + setTimeout(() => setNotification(null), 5000); + }, + showInfo: (message: string) => { + setNotification({ type: 'info', message }); + setTimeout(() => setNotification(null), 3000); + }, + }; +} + +// Usage in component +const { notification, showSuccess } = useNotification(); + +const handleImport = async () => { + try { + const result = await importTransactions(bankAccountId, transactions); + showSuccess(`Successfully imported ${result.imported} transactions`); + } catch (error) { + showError(error instanceof Error ? error.message : 'Import failed'); + } +}; +``` + +--- + +## Testing Checklist + +- [ ] CSV upload accepts .csv files +- [ ] CSV parse shows correct transaction count +- [ ] CSV preview shows transactions with correct types and amounts +- [ ] Bank account dropdown populates from API +- [ ] Import button is disabled until account is selected +- [ ] Import shows loading state during submission +- [ ] Import success message appears +- [ ] Payment form validates amount > 0 +- [ ] Payment form validates date not in future +- [ ] Payment method dropdown has all options +- [ ] Payment submit shows loading state +- [ ] Payment success refreshes invoice +- [ ] Error messages display with helpful text +- [ ] Modal closes on cancel or success +- [ ] Query parameter ?action=payment opens modal + +--- + +## Performance Considerations + +1. **Batch Imports:** All transactions imported in single API call +2. **File Size:** Limit CSV files to 10MB (handles 50k+ transactions) +3. **Preview Table:** Paginate if more than 1000 transactions +4. **Debouncing:** Debounce file input changes +5. **Caching:** Cache bank accounts list with SWR or React Query + +--- + +## Accessibility Notes + +- Form labels properly associated with inputs +- Error messages clearly displayed in red +- Loading states show spinner with text +- Keyboard navigation: Tab through form +- Screen reader support: ARIA labels on all inputs diff --git a/README.md b/README.md new file mode 100644 index 0000000..1e8c27d --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# [ERP Platform] - AI-Native Financial Operations + +An AI-native enterprise resource planning platform that consolidates ERP, treasury management, AP payments, FP&A, forecasting, financial reporting, multi-entity consolidation, and business intelligence into a single system. + +## Quick Start + +```bash +# 1. Install dependencies +npm install + +# 2. Copy environment variables +cp .env.example .env + +# 3. Set up your database (requires PostgreSQL) +# Update DATABASE_URL in .env, then: +npx prisma db push +npx prisma generate + +# 4. Run the dev server +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000) to see the platform. + +## Tech Stack + +- **Frontend:** Next.js 14 (App Router) + React + TypeScript +- **Styling:** Tailwind CSS + Radix UI primitives +- **Database:** PostgreSQL + Prisma ORM +- **AI:** Anthropic Claude API (embedded assistant) +- **Charts:** Recharts + +## Project Structure + +``` +src/ + app/ # Next.js App Router pages + (dashboard)/ # Authenticated layout group + dashboard/ # Main dashboard + general-ledger/ # GL module (chart of accounts, journal entries) + new-entry/ # Create journal entry form + ap-ar/ # Accounts Payable/Receivable (upcoming) + treasury/ # Treasury management (upcoming) + fpa/ # FP&A module (upcoming) + forecasting/ # Forecasting module (upcoming) + tax/ # Tax compliance (upcoming) + reporting/ # Financial reporting (upcoming) + settings/ # Platform settings (upcoming) + components/ + layout/ # Sidebar, Header, AI Assistant + modules/ # Module-specific components + ui/ # Reusable UI components (Button, Card, Badge, DataTable) + lib/ + auth/ # RBAC logic and permissions + db/ # Prisma client + utils/ # Utility functions + types/ # TypeScript type definitions +prisma/ + schema.prisma # Database schema +``` + +## What's Built + +- Platform shell with sidebar navigation, header, and responsive layout +- Role-based "View As" switcher (CEO, CFO, Controller, Manager, Analyst, Clerk) +- Multi-entity selector +- AI Assistant slide-out panel +- General Ledger module with Chart of Accounts, Journal Entries, and Trial Balance +- New journal entry form with real-time debit/credit validation +- Core database schema covering all modules +- RBAC permission system +- Reusable UI component library diff --git a/complete_replace.sh b/complete_replace.sh new file mode 100644 index 0000000..e6cee96 --- /dev/null +++ b/complete_replace.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +files=( + "src/app/(dashboard)/admin/users/page.tsx" + "src/app/(dashboard)/admin/roles/page.tsx" + "src/app/(dashboard)/admin/workflows/page.tsx" + "src/app/(dashboard)/admin/approvals/page.tsx" + "src/app/(dashboard)/admin/integrations/page.tsx" + "src/app/(dashboard)/admin/settings/page.tsx" + "src/app/(dashboard)/admin/activity-log/page.tsx" + "src/app/(dashboard)/planning/budgets/page.tsx" + "src/app/(dashboard)/planning/forecasting/page.tsx" + "src/app/(dashboard)/planning/cash-forecast/page.tsx" + "src/app/(dashboard)/planning/fpa/page.tsx" + "src/app/(dashboard)/planning/projects/page.tsx" + "src/app/(dashboard)/compliance/tax/page.tsx" + "src/app/(dashboard)/compliance/tax-reporting/page.tsx" + "src/app/(dashboard)/compliance/reporting/page.tsx" + "src/app/(dashboard)/compliance/leases/page.tsx" + "src/app/(dashboard)/compliance/report-builder/page.tsx" + "src/app/(dashboard)/equity/cap-table/page.tsx" +) + +declare -a replacements=( + 's/border-slate-50/border-[#222228]/g' + 's/text-slate-200/text-[#5A5A6E]/g' + 's/text-slate-300/text-[#5A5A6E]/g' + 's/bg-slate-200/bg-[#222228]/g' + 's/bg-slate-300/bg-[#222228]/g' + 's/hover:bg-slate-200/hover:bg-[#2A2A32]/g' + 's/hover:bg-slate-300/hover:bg-[#3A3A45]/g' + 's/ring-slate-300/ring-[#3A3A45]/g' + 's/ring-blue-500/ring-indigo-500/g' + 's/border-blue-500/border-indigo-500/g' + 's/focus:ring-blue-500/focus:ring-indigo-500/g' + 's/focus:border-blue-500/focus:border-indigo-500/g' +) + +for file in "${files[@]}"; do + if [ -f "$file" ]; then + echo "Final processing $file..." + for replacement in "${replacements[@]}"; do + sed -i "$replacement" "$file" + done + fi +done + +echo "Complete!" diff --git a/fix_final.sh b/fix_final.sh new file mode 100644 index 0000000..717e56a --- /dev/null +++ b/fix_final.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +files=( + "src/app/(dashboard)/admin/roles/page.tsx" + "src/app/(dashboard)/planning/budgets/page.tsx" + "src/app/(dashboard)/equity/cap-table/page.tsx" +) + +declare -a final_replacements=( + 's/divide-slate-50/divide-[#222228]/g' + 's/hover:bg-slate-400/hover:bg-[#2A2A32]/g' + 's/border-gray-100/border-[#2A2A32]/g' + 's/bg-gray-200/bg-[#222228]/g' + 's/bg-gray-300/bg-[#2A2A32]/g' + 's/text-gray-200/text-[#5A5A6E]/g' + 's/hover:bg-gray-300/hover:bg-[#2A2A32]/g' +) + +for file in "${files[@]}"; do + if [ -f "$file" ]; then + echo "Final fix: $file" + for replacement in "${final_replacements[@]}"; do + sed -i "$replacement" "$file" + done + fi +done + +echo "Final fixes complete!" diff --git a/fix_remaining.sh b/fix_remaining.sh new file mode 100644 index 0000000..a0b08d7 --- /dev/null +++ b/fix_remaining.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +files=( + "src/app/(dashboard)/admin/users/page.tsx" + "src/app/(dashboard)/admin/roles/page.tsx" + "src/app/(dashboard)/admin/workflows/page.tsx" + "src/app/(dashboard)/admin/approvals/page.tsx" + "src/app/(dashboard)/admin/integrations/page.tsx" + "src/app/(dashboard)/admin/settings/page.tsx" + "src/app/(dashboard)/admin/activity-log/page.tsx" + "src/app/(dashboard)/planning/budgets/page.tsx" + "src/app/(dashboard)/planning/forecasting/page.tsx" + "src/app/(dashboard)/planning/cash-forecast/page.tsx" + "src/app/(dashboard)/planning/fpa/page.tsx" + "src/app/(dashboard)/planning/projects/page.tsx" + "src/app/(dashboard)/compliance/tax/page.tsx" + "src/app/(dashboard)/compliance/tax-reporting/page.tsx" + "src/app/(dashboard)/compliance/reporting/page.tsx" + "src/app/(dashboard)/compliance/leases/page.tsx" + "src/app/(dashboard)/compliance/report-builder/page.tsx" + "src/app/(dashboard)/equity/cap-table/page.tsx" +) + +# Additional specific replacements +declare -a final_fixes=( + 's/border-slate-300/border-[#3A3A45]/g' + 's/border-gray-300/border-[#3A3A45]/g' + 's/ring-slate/ring-[#3A3A45]/g' + 's/disabled:bg-slate-300/disabled:bg-[#222228]/g' +) + +for file in "${files[@]}"; do + if [ -f "$file" ]; then + for fix in "${final_fixes[@]}"; do + sed -i "$fix" "$file" + done + fi +done + +echo "Final fixes applied!" diff --git a/instrumentation.ts b/instrumentation.ts new file mode 100644 index 0000000..69d8463 --- /dev/null +++ b/instrumentation.ts @@ -0,0 +1,36 @@ +/** + * Next.js Instrumentation Hook + * + * https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation + * + * This file is automatically loaded by Next.js when the server starts. + * We use it to boot the EVE auto-sync cron job in the Node.js runtime. + * + * IMPORTANT: We only run on the server (Node.js runtime), not on the + * Edge runtime — node-cron requires Node.js APIs. + */ + +export async function register() { + // Only boot in the Node.js runtime — not Edge, not Workers + if (process.env.NEXT_RUNTIME !== "nodejs") { + return; + } + + // Skip during builds (Next.js runs instrumentation during `next build` too) + if (process.env.NEXT_PHASE === "phase-production-build") { + return; + } + + console.log("[instrumentation] Booting EVE auto-sync cron..."); + + // Dynamic import keeps node-cron out of the Edge bundle + const { startAutoSyncCron } = await import("@/lib/eve/cron"); + + // Default: tick every minute. Override with EVE_SYNC_CRON env var. + // Examples: + // "* * * * *" — every minute (default) + // "*/30 * * * * *" — every 30 seconds (uses 6-field syntax) + // "*/5 * * * *" — every 5 minutes + const schedule = process.env.EVE_SYNC_CRON || "* * * * *"; + startAutoSyncCron(schedule); +} diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..40c3d68 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..eb03076 --- /dev/null +++ b/next.config.js @@ -0,0 +1,54 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + + // Enable compression + compress: true, + + // Optimize package imports (tree-shake large libraries) + experimental: { + optimizePackageImports: ['lucide-react', 'recharts'], + // Enable instrumentation.ts hook (boots EVE auto-sync cron at startup). + // This is on by default in Next 15+, but Next 14 needs the opt-in flag. + instrumentationHook: true, + // node-cron is a Node-only module — keep it server-side, never bundled + serverComponentsExternalPackages: ['node-cron'], + }, + + // Image optimization + images: { + formats: ['image/avif', 'image/webp'], + }, + + // Cache headers for static assets and API routes + async headers() { + return [ + { + source: '/_next/static/:path*', + headers: [ + { key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }, + ], + }, + { + source: '/api/currencies', + headers: [ + { key: 'Cache-Control', value: 'private, max-age=3600, stale-while-revalidate=7200' }, + ], + }, + { + source: '/api/fiscal-periods', + headers: [ + { key: 'Cache-Control', value: 'private, max-age=3600, stale-while-revalidate=7200' }, + ], + }, + { + source: '/api/accounts', + headers: [ + { key: 'Cache-Control', value: 'private, max-age=300, stale-while-revalidate=600' }, + ], + }, + ]; + }, +}; + +module.exports = nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7550bad --- /dev/null +++ b/package-lock.json @@ -0,0 +1,8867 @@ +{ + "name": "erp-platform", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "erp-platform", + "version": "0.1.0", + "dependencies": { + "@next/swc-linux-x64-gnu": "*", + "@prisma/client": "^5.6.0", + "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", + "@types/bcryptjs": "^2.4.6", + "@types/jsonwebtoken": "^9.0.5", + "@types/node": "^20.10.0", + "@types/react": "^18.2.42", + "@types/react-dom": "^18.2.17", + "autoprefixer": "^10.4.16", + "bcryptjs": "^2.4.3", + "class-variance-authority": "^0.7.0", + "clsx": "^2.0.0", + "jsonwebtoken": "^9.0.2", + "lucide-react": "^0.292.0", + "next": "14.2.21", + "postcss": "^8.4.31", + "prisma": "^5.6.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "recharts": "^2.10.3", + "tailwind-merge": "^2.2.0", + "tailwindcss": "^3.4.0", + "typescript": "^5.3.3" + }, + "devDependencies": { + "eslint": "^8.54.0", + "eslint-config-next": "14.2.21", + "tsx": "^4.7.0" + }, + "optionalDependencies": { + "@next/swc-linux-x64-gnu": "*" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@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/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@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/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@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==", + "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==", + "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==", + "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==", + "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": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.21.tgz", + "integrity": "sha512-lXcwcJd5oR01tggjWJ6SrNNYFGuOOMB9c251wUNkjCpkoXOPkDeF/15c3mnVlBqrW4JJXb2kVxDFhC4GduJt2A==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.21.tgz", + "integrity": "sha512-bxfiExnMkpwo4bBhCqnDhdgFyxSp6Xt6xu4Ne7En6MpgqwiER95Or+q1WDUDX4e888taeIAdPIAVaY+Wv0kiwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.21.tgz", + "integrity": "sha512-HwEjcKsXtvszXz5q5Z7wCtrHeTTDSTgAbocz45PHMUjU3fBYInfvhR+ZhavDRUYLonm53aHZbB09QtJVJj8T7g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.21.tgz", + "integrity": "sha512-TSAA2ROgNzm4FhKbTbyJOBrsREOMVdDIltZ6aZiKvCi/v0UwFmwigBGeqXDA97TFMpR3LNNpw52CbVelkoQBxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.21.tgz", + "integrity": "sha512-0Dqjn0pEUz3JG+AImpnMMW/m8hRtl1GQCNbO66V1yp6RswSTiKmnHf3pTX6xMdJYSemf3O4Q9ykiL0jymu0TuA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.21.tgz", + "integrity": "sha512-Ggfw5qnMXldscVntwnjfaQs5GbBbjioV4B4loP+bjqNEb42fzZlAaK+ldL0jm2CTJga9LynBMhekNfV8W4+HBw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.21.tgz", + "integrity": "sha512-iAEBPzWNbciah4+0yI4s7Pce6BIoxTQ0AGCkxn/UBuzJFkYyJt71MadYQkjPqCQCJAFQ26sYh7MOKdU+VQFgPg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.21.tgz", + "integrity": "sha512-plykgB3vL2hB4Z32W3ktsfqyuyGAPxqwiyrAi2Mr8LlEUhNn9VgkiAl5hODSBpzIfWweX3er1f5uNpGDygfQVQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.21.tgz", + "integrity": "sha512-w5bacz4Vxqrh06BjWgua3Yf7EMDb8iMcVhNrNx8KnJXt8t+Uu0Zg4JHLDL/T7DkTCEEfKXO/Er1fcfWxn2xfPA==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.21", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.21.tgz", + "integrity": "sha512-sT6+llIkzpsexGYZq8cjjthRyRGe5cJVhqh12FmlbxHqna6zsDDK8UNaV7g41T6atFHCJUPeLb3uyAwrBwy0NA==", + "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==", + "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==", + "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==", + "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/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@prisma/client": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.22.0.tgz", + "integrity": "sha512-M0SVXfyHnQREBKxCgyo7sffrKttwE6R8PMq330MIUF0pTwjUhLbW84pFDlf06B27XyCR++VtjugEnIHdr07SVA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.13" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, + "node_modules/@prisma/debug": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.22.0.tgz", + "integrity": "sha512-AUt44v3YJeggO2ZU5BkXI7M4hu9BF2zzH2iF2V5pyXT/lRTyWiElZ7It+bRH1EshoMRxHgpYg4VB6rCM+mG5jQ==", + "license": "Apache-2.0" + }, + "node_modules/@prisma/engines": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.22.0.tgz", + "integrity": "sha512-UNjfslWhAt06kVL3CjkuYpHAWSO6L4kDCVPegV6itt7nD1kSJavd3vhgAEhjglLJJKEdJ7oIqDJ+yHk6qO8gPA==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.22.0", + "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2", + "@prisma/fetch-engine": "5.22.0", + "@prisma/get-platform": "5.22.0" + } + }, + "node_modules/@prisma/engines-version": { + "version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2.tgz", + "integrity": "sha512-2PTmxFR2yHW/eB3uqWtcgRcgAbG1rwG9ZriSvQw+nnb7c4uCr3RAcGMb6/zfE88SKlC1Nj2ziUvc96Z379mHgQ==", + "license": "Apache-2.0" + }, + "node_modules/@prisma/fetch-engine": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.22.0.tgz", + "integrity": "sha512-bkrD/Mc2fSvkQBV5EpoFcZ87AvOgDxbG99488a5cexp5Ccny+UM6MAe/UFkUC0wLYD9+9befNOqGiIJhhq+HbA==", + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.22.0", + "@prisma/engines-version": "5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2", + "@prisma/get-platform": "5.22.0" + } + }, + "node_modules/@prisma/get-platform": { + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.22.0.tgz", + "integrity": "sha512-pHhpQdr1UPFpt+zFfnPazhulaZYCUqeIcPpJViYoq9R+D/yw4fjE+CtnsnKzPYm0ddUbeXUzjGVGIRVgPDCk4Q==", + "license": "Apache-2.0", + "dependencies": { + "@prisma/debug": "5.22.0" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz", + "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.3", + "@radix-ui/react-primitive": "2.1.4", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz", + "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", + "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", + "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-is-hydrated": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", + "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.5.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@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/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.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/bcryptjs": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", + "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", + "license": "MIT" + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.8.tgz", + "integrity": "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/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/jsonwebtoken": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", + "license": "MIT", + "dependencies": { + "@types/ms": "*", + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", + "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.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/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/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/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/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/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-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==", + "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==", + "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==", + "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-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "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/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==", + "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.14", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.14.tgz", + "integrity": "sha512-fOVLPAsFTsQfuCkvahZkzq6nf8KvGWanlYoTh0SVA0A/PIUxQGU2AOZAoD95n2gFLVDW/jP6sbGLny95nmEuHA==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "license": "MIT" + }, + "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==", + "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==", + "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==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/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==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001784", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001784.tgz", + "integrity": "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "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==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/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==", + "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/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==", + "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==", + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "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/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/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "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==", + "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/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "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/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/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==", + "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/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-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==", + "devOptional": 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==", + "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", + "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": "14.2.21", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.21.tgz", + "integrity": "sha512-bi1Mn6LxWdQod9qvOBuhBhN4ZpBYH5DuyDunbZt6lye3zlohJyM0T5/oFokRPNl2Mqt3/+uwHxr8XKOkPe852A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "14.2.21", + "@rushstack/eslint-patch": "^1.3.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.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.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-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.0.0-canary-7118f5dd7-20230705", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz", + "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==", + "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" + } + }, + "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/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/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/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "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==", + "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==", + "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==", + "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/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "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.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "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==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "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==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/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/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/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==", + "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/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "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==", + "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==", + "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==", + "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-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-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==", + "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==", + "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/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "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==", + "license": "MIT", + "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==", + "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/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/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/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/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==", + "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==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/lucide-react": { + "version": "0.292.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.292.0.tgz", + "integrity": "sha512-rRgUkpEHWpa5VCT66YscInCQmQuPCB1RFRzkkxMxg4b+jaL0V12E3riWWR2Sh5OIiUhCwGW/ZExuEO4Az32E6Q==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } + }, + "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==", + "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==", + "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/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "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": "14.2.21", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.21.tgz", + "integrity": "sha512-rZmLwucLHr3/zfDMYbJXbw0ZeoBpirxkXuvsJbk7UPorvPYZhP7vq7aHbKnU7dQNCYIimRrbB2pp3xmf+wsYUg==", + "deprecated": "This version has a security vulnerability. Please upgrade to a patched version. See https://nextjs.org/blog/security-update-2025-12-11 for more details.", + "license": "MIT", + "dependencies": { + "@next/env": "14.2.21", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.21", + "@next/swc-darwin-x64": "14.2.21", + "@next/swc-linux-arm64-gnu": "14.2.21", + "@next/swc-linux-arm64-musl": "14.2.21", + "@next/swc-linux-x64-gnu": "14.2.21", + "@next/swc-linux-x64-musl": "14.2.21", + "@next/swc-win32-arm64-msvc": "14.2.21", + "@next/swc-win32-ia32-msvc": "14.2.21", + "@next/swc-win32-x64-msvc": "14.2.21" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "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-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-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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "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==", + "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/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==", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/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==", + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "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==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "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-import/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "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/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "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==", + "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==", + "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==", + "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==", + "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": "5.22.0", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz", + "integrity": "sha512-vtpjW3XuYCSnMsNVBjLMNkTj6OZbudcPPTPYHqX0CJfpcdWciI1dM8uHETwmDxxiqEwCIE6WvXucWUetJgfu/A==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@prisma/engines": "5.22.0" + }, + "bin": { + "prisma": "build/index.js" + }, + "engines": { + "node": ">=16.13" + }, + "optionalDependencies": { + "fsevents": "2.3.3" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/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==", + "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==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recharts": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", + "integrity": "sha512-UT/q6fwS3c1dHbXv2uFgYJ9BMFHu3fwnd7AYZaEQhXuYQ4hgsxLvsUXzGdKeZrW5xopzDCvuA2N41WJ88I7zIw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.4", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, + "node_modules/recharts/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "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": "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/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==", + "devOptional": 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==", + "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/rimraf/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/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "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-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/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.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/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/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/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/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-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "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.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "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" + }, + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz", + "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "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/tailwindcss/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "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/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==", + "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==", + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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==", + "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==", + "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==", + "devOptional": true, + "license": "MIT", + "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/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==", + "license": "Apache-2.0", + "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==", + "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==", + "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/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/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/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/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" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c3ae5d0 --- /dev/null +++ b/package.json @@ -0,0 +1,60 @@ +{ + "name": "eve-online-erp", + "version": "0.1.0", + "private": true, + "prisma": { + "seed": "tsx prisma/seed.ts" + }, + "scripts": { + "dev": "next dev", + "dev:https": "node scripts/dev-https.js", + "build": "next build", + "start": "next start", + "lint": "next lint", + "db:push": "prisma db push", + "db:generate": "prisma generate", + "db:studio": "prisma studio", + "db:seed": "tsx prisma/seed.ts", + "cert:generate": "bash scripts/generate-cert.sh" + }, + "dependencies": { + "@prisma/client": "^5.6.0", + "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", + "@types/bcryptjs": "^2.4.6", + "@types/jsonwebtoken": "^9.0.5", + "@types/node": "^20.10.0", + "@types/react": "^18.2.42", + "@types/react-dom": "^18.2.17", + "autoprefixer": "^10.4.16", + "bcryptjs": "^2.4.3", + "class-variance-authority": "^0.7.0", + "clsx": "^2.0.0", + "jsonwebtoken": "^9.0.2", + "lucide-react": "^0.292.0", + "next": "14.2.21", + "node-cron": "^3.0.3", + "postcss": "^8.4.31", + "prisma": "^5.6.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "recharts": "^2.10.3", + "tailwind-merge": "^2.2.0", + "tailwindcss": "^3.4.0", + "typescript": "^5.3.3" + }, + "devDependencies": { + "@types/node-cron": "^3.0.11", + "eslint": "^8.54.0", + "eslint-config-next": "14.2.21", + "tsx": "^4.7.0" + }, + "optionalDependencies": { + "@next/swc-linux-x64-gnu": "*" + } +} diff --git a/postcss.config.mjs b/postcss.config.mjs new file mode 100644 index 0000000..2ef30fc --- /dev/null +++ b/postcss.config.mjs @@ -0,0 +1,9 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; + +export default config; diff --git a/prisma/schema.prisma b/prisma/schema.prisma new file mode 100644 index 0000000..13b60d8 --- /dev/null +++ b/prisma/schema.prisma @@ -0,0 +1,2071 @@ +// Prisma schema for AI-native ERP Platform +// Multi-tenant, comprehensive financial and operational management system + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +generator client { + provider = "prisma-client-js" +} + +// ============================================================================ +// ENUMS +// ============================================================================ + +enum UserStatus { + ACTIVE + INACTIVE + SUSPENDED + PENDING_ACTIVATION +} + +enum RoleType { + CEO + CFO + CONTROLLER + MANAGER + ANALYST + CLERK + CUSTOM +} + +enum PermissionModule { + DASHBOARD + CHART_OF_ACCOUNTS + JOURNAL_ENTRIES + INVOICES + PAYMENTS + VENDORS + CUSTOMERS + BANK_ACCOUNTS + TREASURY + REPORTS + SETTINGS + USERS + INTEGRATIONS + AUDIT_LOG +} + +enum PermissionAction { + VIEW + CREATE + EDIT + APPROVE + DELETE + ADMIN +} + +enum InvoiceStatus { + DRAFT + PENDING_APPROVAL + APPROVED + PARTIALLY_PAID + PAID + OVERDUE + CANCELLED + VOID +} + +enum PaymentStatus { + DRAFT + SCHEDULED + PROCESSING + COMPLETED + FAILED + REVERSED + CANCELLED +} + +enum PaymentMethod { + ACH + WIRE + CHECK + CREDIT_CARD + BANK_TRANSFER + CASH + OTHER +} + +enum InvoiceType { + ACCOUNTS_PAYABLE + ACCOUNTS_RECEIVABLE +} + +enum AccountType { + ASSET + LIABILITY + EQUITY + REVENUE + EXPENSE + GAIN_LOSS +} + +enum FiscalPeriodStatus { + OPEN + CLOSED + LOCKED +} + +enum ConnectorStatus { + ACTIVE + INACTIVE + ERROR + PAUSED + TESTING +} + +enum ConnectorType { + BANK_FEED + ACCOUNTING_SOFTWARE + ERP_SYSTEM + PAYMENT_PROCESSOR + DOCUMENT_STORAGE + CUSTOM_API +} + +enum ConnectorHealthStatus { + HEALTHY + WARNING + ERROR + UNKNOWN +} + +enum AIActionType { + CATEGORIZATION + ANOMALY_DETECTION + RECONCILIATION + FORECAST + RECOMMENDATION + DATA_TRANSFORMATION + VALIDATION + HEALING +} + +enum AIActionStatus { + PENDING + EXECUTED + APPROVED + REJECTED + IN_PROGRESS + COMPLETED + FAILED +} + +enum TransactionType { + DEBIT + CREDIT + REVERSAL + ADJUSTMENT +} + +enum EntityType { + SUBSIDIARY + DIVISION + DEPARTMENT + LOCATION + COST_CENTER +} + +// ============================================================================ +// MULTI-TENANCY & ORGANIZATION +// ============================================================================ + +model Organization { + id String @id @default(uuid()) @db.Uuid + name String @db.VarChar(255) + legalName String? @db.VarChar(255) + taxId String? @db.VarChar(50) + website String? @db.VarChar(255) + description String? @db.Text + logoUrl String? @db.VarChar(500) + status String @default("ACTIVE") @db.VarChar(50) + industry String? @db.VarChar(100) + + // Fiscal configuration + currentFiscalYearId String? @db.Uuid + fiscalYearStartMonth Int @default(1) // 1-12 + fiscalYearStartDay Int @default(1) // 1-31 + + // Settings + defaultCurrency String @default("USD") @db.VarChar(3) + timezone String @default("UTC") @db.VarChar(50) + language String @default("en") @db.VarChar(10) + dateFormat String @default("YYYY-MM-DD") @db.VarChar(20) + + // Metadata + settings Json? + customFields Json? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + entities Entity[] + users User[] + roles Role[] + permissions Permission[] + groups Group[] + chartOfAccounts ChartOfAccount[] + journalEntries JournalEntry[] + journalEntryLines JournalEntryLine[] + fiscalPeriods FiscalPeriod[] + invoices Invoice[] + payments Payment[] + paymentAllocations PaymentAllocation[] + vendors Vendor[] + customers Customer[] + bankAccounts BankAccount[] + bankTransactions BankTransaction[] + bankReconciliations BankReconciliation[] + currencies Currency[] + connectors Connector[] + aiActions AIAction[] + dashboardConfigs DashboardConfig[] + auditLogs AuditLog[] + shareholders Shareholder[] + leases Lease[] + budgetLines BudgetLine[] + purchaseOrders PurchaseOrder[] + documents Document[] + subscriptions Subscription[] + forecasts Forecast[] + drivers PlanningDriver[] + planningScenarios PlanningScenario[] + closePeriods ClosePeriod[] + closeTasks CloseTask[] + revenueContracts RevenueContract[] + revenueScheduleLines RevenueScheduleLine[] + fixedAssets FixedAsset[] + eveCharacters EveCharacter[] + + @@index([name]) + @@index([status]) + @@map("organizations") +} + +model Entity { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + name String @db.VarChar(255) + type EntityType @default(SUBSIDIARY) + code String @db.VarChar(50) + parentEntityId String? @db.Uuid + description String? @db.Text + status String @default("ACTIVE") @db.VarChar(50) + + // Settings + defaultCurrency String @default("USD") @db.VarChar(3) + isConsolidated Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + parentEntity Entity? @relation("EntityHierarchy", fields: [parentEntityId], references: [id], onDelete: SetNull) + childEntities Entity[] @relation("EntityHierarchy") + journalEntryLines JournalEntryLine[] + invoices Invoice[] + bankAccounts BankAccount[] + + @@index([organizationId]) + @@index([parentEntityId]) + @@index([code]) + @@map("entities") +} + +// ============================================================================ +// AUTHENTICATION & RBAC +// ============================================================================ + +model User { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + email String @db.VarChar(255) + emailVerified DateTime? + passwordHash String? @db.VarChar(255) + name String @db.VarChar(255) + firstName String? @db.VarChar(100) + lastName String? @db.VarChar(100) + avatarUrl String? @db.VarChar(500) + phone String? @db.VarChar(20) + + status UserStatus @default(ACTIVE) + lastLoginAt DateTime? + lastLoginIp String? @db.VarChar(50) + + // Preferences + timezone String? @db.VarChar(50) + language String? @db.VarChar(10) + preferences Json? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + userRoles UserRole[] + userGroups UserGroup[] + sessions Session[] + aiActionsTriggered AIAction[] @relation("TriggeredBy") + aiActionsApproved AIAction[] @relation("ApprovedBy") + journalEntriesPosted JournalEntry[] @relation("PostedBy") + journalEntriesApproved JournalEntry[] @relation("ApprovedBy") + dashboardConfigs DashboardConfig[] + eveCharacters EveCharacter[] + + @@unique([organizationId, email]) + @@index([organizationId]) + @@index([email]) + @@index([status]) + @@map("users") +} + +model Role { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + name String @db.VarChar(255) + roleType RoleType @default(CUSTOM) + description String? @db.Text + isSystem Boolean @default(false) + status String @default("ACTIVE") @db.VarChar(50) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + permissions Permission[] + userRoles UserRole[] + + @@unique([organizationId, name]) + @@index([organizationId]) + @@index([roleType]) + @@map("roles") +} + +model Permission { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + roleId String @db.Uuid + module PermissionModule + action PermissionAction + description String? @db.Text + conditions Json? // Additional conditions (e.g., entity-level restrictions) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) + + @@unique([roleId, module, action]) + @@index([organizationId]) + @@index([roleId]) + @@map("permissions") +} + +model Group { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + name String @db.VarChar(255) + description String? @db.Text + status String @default("ACTIVE") @db.VarChar(50) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + userGroups UserGroup[] + + @@unique([organizationId, name]) + @@index([organizationId]) + @@map("groups") +} + +model UserRole { + id String @id @default(uuid()) @db.Uuid + userId String @db.Uuid + roleId String @db.Uuid + assignedAt DateTime @default(now()) + expiresAt DateTime? + createdBy String? @db.VarChar(255) + + // Relations + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + role Role @relation(fields: [roleId], references: [id], onDelete: Cascade) + + @@unique([userId, roleId]) + @@index([userId]) + @@index([roleId]) + @@map("user_roles") +} + +model UserGroup { + id String @id @default(uuid()) @db.Uuid + userId String @db.Uuid + groupId String @db.Uuid + joinedAt DateTime @default(now()) + + // Relations + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + group Group @relation(fields: [groupId], references: [id], onDelete: Cascade) + + @@unique([userId, groupId]) + @@index([userId]) + @@index([groupId]) + @@map("user_groups") +} + +model Session { + id String @id @default(uuid()) @db.Uuid + userId String @db.Uuid + token String @db.VarChar(500) + expiresAt DateTime + ipAddress String? @db.VarChar(50) + userAgent String? @db.Text + revokedAt DateTime? + + createdAt DateTime @default(now()) + + // Relations + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId]) + @@index([token]) + @@index([expiresAt]) + @@map("sessions") +} + +// ============================================================================ +// FINANCIAL CORE - CHART OF ACCOUNTS & JOURNAL +// ============================================================================ + +model ChartOfAccount { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + accountCode String @db.VarChar(50) + accountName String @db.VarChar(255) + accountType AccountType + parentAccountId String? @db.Uuid + description String? @db.Text + status String @default("ACTIVE") @db.VarChar(50) + + // Account settings + isControlAccount Boolean @default(false) + isDetailAccount Boolean @default(true) + isBankAccount Boolean @default(false) + currencyCode String @default("USD") @db.VarChar(3) + + // Hierarchy + level Int @default(1) + hierarchy String @db.VarChar(500) // Denormalized for performance + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + parentAccount ChartOfAccount? @relation("AccountHierarchy", fields: [parentAccountId], references: [id], onDelete: SetNull) + childAccounts ChartOfAccount[] @relation("AccountHierarchy") + journalEntryLines JournalEntryLine[] + budgetLines BudgetLine[] + + @@unique([organizationId, accountCode]) + @@index([organizationId]) + @@index([accountType]) + @@index([status]) + @@index([parentAccountId]) + @@map("chart_of_accounts") +} + +model FiscalPeriod { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + fiscalYear Int + periodNumber Int // 1-12 or 1-13 + periodName String @db.VarChar(50) + startDate DateTime + endDate DateTime + status FiscalPeriodStatus @default(OPEN) + closedAt DateTime? + closedBy String? @db.VarChar(255) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + journalEntries JournalEntry[] + + @@unique([organizationId, fiscalYear, periodNumber]) + @@index([organizationId]) + @@index([status]) + @@index([startDate, endDate]) + @@map("fiscal_periods") +} + +model JournalEntry { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + fiscalPeriodId String @db.Uuid + entryNumber String @db.VarChar(50) + entryDate DateTime + description String @db.Text + sourceModule String @db.VarChar(100) // AP, AR, PAYROLL, etc. + referenceId String? @db.VarChar(255) // Links to source document + + status String @default("DRAFT") @db.VarChar(50) + totalDebits Decimal @default(0) @db.Decimal(19, 4) + totalCredits Decimal @default(0) @db.Decimal(19, 4) + isBalanced Boolean @default(false) + + postedAt DateTime? + postedBy String? @db.Uuid + approvedAt DateTime? + approvedBy String? @db.Uuid + + memo String? @db.Text + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + fiscalPeriod FiscalPeriod @relation(fields: [fiscalPeriodId], references: [id], onDelete: Restrict) + postedByUser User? @relation("PostedBy", fields: [postedBy], references: [id], onDelete: SetNull) + approvedByUser User? @relation("ApprovedBy", fields: [approvedBy], references: [id], onDelete: SetNull) + journalEntryLines JournalEntryLine[] + + @@unique([organizationId, entryNumber]) + @@index([organizationId]) + @@index([entryDate]) + @@index([fiscalPeriodId]) + @@index([status]) + @@index([sourceModule]) + @@map("journal_entries") +} + +model JournalEntryLine { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + journalEntryId String @db.Uuid + entityId String @db.Uuid + accountId String @db.Uuid + + debitAmount Decimal @default(0) @db.Decimal(19, 4) + creditAmount Decimal @default(0) @db.Decimal(19, 4) + currencyCode String @default("USD") @db.VarChar(3) + exchangeRate Decimal @default(1) @db.Decimal(19, 8) + + lineNumber Int + description String? @db.Text + memo String? @db.Text + department String? @db.VarChar(100) + project String? @db.VarChar(100) + costCenter String? @db.VarChar(100) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + journalEntry JournalEntry @relation(fields: [journalEntryId], references: [id], onDelete: Cascade) + entity Entity @relation(fields: [entityId], references: [id], onDelete: Restrict) + account ChartOfAccount @relation(fields: [accountId], references: [id], onDelete: Restrict) + + @@index([organizationId]) + @@index([journalEntryId]) + @@index([accountId]) + @@index([entityId]) + @@map("journal_entry_lines") +} + +// ============================================================================ +// CURRENCY & EXCHANGE RATES +// ============================================================================ + +model Currency { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + currencyCode String @db.VarChar(3) + currencyName String @db.VarChar(100) + symbolFormat String @db.VarChar(10) + decimalPlaces Int @default(2) + isActive Boolean @default(true) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@unique([organizationId, currencyCode]) + @@index([organizationId]) + @@map("currencies") +} + +// ============================================================================ +// VENDORS & CUSTOMERS +// ============================================================================ + +model Vendor { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + vendorCode String @db.VarChar(50) + vendorName String @db.VarChar(255) + vendorType String? @db.VarChar(100) + + // Contact Info + email String? @db.VarChar(255) + phone String? @db.VarChar(20) + website String? @db.VarChar(255) + + // Address + street1 String? @db.VarChar(255) + street2 String? @db.VarChar(255) + city String? @db.VarChar(100) + stateProvince String? @db.VarChar(100) + postalCode String? @db.VarChar(20) + country String? @db.VarChar(100) + + // Tax & Legal + taxId String? @db.VarChar(50) + vendorTaxId String? @db.VarChar(50) + + // Payment Terms + paymentTermDays Int @default(0) + defaultCurrency String @default("USD") @db.VarChar(3) + + status String @default("ACTIVE") @db.VarChar(50) + creditLimit Decimal? @db.Decimal(19, 4) + isOnHold Boolean @default(false) + + // Audit + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + invoices Invoice[] + payments Payment[] + purchaseOrders PurchaseOrder[] + + @@unique([organizationId, vendorCode]) + @@index([organizationId]) + @@index([status]) + @@map("vendors") +} + +model Customer { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + customerCode String @db.VarChar(50) + customerName String @db.VarChar(255) + customerType String? @db.VarChar(100) + + // Contact Info + email String? @db.VarChar(255) + phone String? @db.VarChar(20) + website String? @db.VarChar(255) + contactPerson String? @db.VarChar(255) + + // Address + street1 String? @db.VarChar(255) + street2 String? @db.VarChar(255) + city String? @db.VarChar(100) + stateProvince String? @db.VarChar(100) + postalCode String? @db.VarChar(20) + country String? @db.VarChar(100) + + // Tax & Legal + taxId String? @db.VarChar(50) + + // Business Terms + paymentTermDays Int @default(0) + defaultCurrency String @default("USD") @db.VarChar(3) + creditLimit Decimal? @db.Decimal(19, 4) + + status String @default("ACTIVE") @db.VarChar(50) + isOnCredit Boolean @default(false) + + // Audit + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + invoices Invoice[] + payments Payment[] + subscriptions Subscription[] + revenueContracts RevenueContract[] + + @@unique([organizationId, customerCode]) + @@index([organizationId]) + @@index([status]) + @@map("customers") +} + +// ============================================================================ +// INVOICES +// ============================================================================ + +model Invoice { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + entityId String @db.Uuid + invoiceNumber String @db.VarChar(50) + invoiceType InvoiceType + + // Party Info + vendorId String? @db.Uuid + customerId String? @db.Uuid + + invoiceDate DateTime + dueDate DateTime? + expectedPaymentDate DateTime? + + // Amount + subtotalAmount Decimal @db.Decimal(19, 4) + taxAmount Decimal @default(0) @db.Decimal(19, 4) + totalAmount Decimal @db.Decimal(19, 4) + paidAmount Decimal @default(0) @db.Decimal(19, 4) + balanceDue Decimal @db.Decimal(19, 4) + currencyCode String @default("USD") @db.VarChar(3) + exchangeRate Decimal @default(1) @db.Decimal(19, 8) + + // Details + description String? @db.Text + poNumber String? @db.VarChar(100) + referenceNumber String? @db.VarChar(100) + + status InvoiceStatus @default(DRAFT) + approvedAt DateTime? + approvedBy String? @db.VarChar(255) + cancelledAt DateTime? + cancelledBy String? @db.VarChar(255) + cancelReason String? @db.Text + + daysOverdue Int? + + // Audit + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + entity Entity @relation(fields: [entityId], references: [id], onDelete: Restrict) + vendor Vendor? @relation(fields: [vendorId], references: [id], onDelete: SetNull) + customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull) + invoiceLines InvoiceLine[] + payments Payment[] + paymentAllocations PaymentAllocation[] + + @@unique([organizationId, invoiceNumber]) + @@index([organizationId]) + @@index([invoiceType]) + @@index([status]) + @@index([invoiceDate]) + @@index([dueDate]) + @@index([vendorId]) + @@index([customerId]) + @@map("invoices") +} + +model InvoiceLine { + id String @id @default(uuid()) @db.Uuid + invoiceId String @db.Uuid + lineNumber Int + description String @db.Text + quantity Decimal @db.Decimal(19, 4) + unitPrice Decimal @db.Decimal(19, 4) + lineAmount Decimal @db.Decimal(19, 4) + + glAccountCode String? @db.VarChar(50) + department String? @db.VarChar(100) + project String? @db.VarChar(100) + taxCode String? @db.VarChar(50) + taxAmount Decimal @default(0) @db.Decimal(19, 4) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade) + + @@index([invoiceId]) + @@map("invoice_lines") +} + +// ============================================================================ +// PAYMENTS +// ============================================================================ + +model Payment { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + paymentNumber String @db.VarChar(50) + + // Party & Invoice Info + vendorId String? @db.Uuid + customerId String? @db.Uuid + invoiceId String? @db.Uuid + + // Payment Details + paymentDate DateTime + paymentMethod PaymentMethod + paymentReference String? @db.VarChar(255) + + // Account Info + bankAccountId String? @db.Uuid + checkNumber String? @db.VarChar(50) + + // Amount + paymentAmount Decimal @db.Decimal(19, 4) + currencyCode String @default("USD") @db.VarChar(3) + exchangeRate Decimal @default(1) @db.Decimal(19, 8) + feeAmount Decimal @default(0) @db.Decimal(19, 4) + totalPaymentAmount Decimal @db.Decimal(19, 4) + + // Status + status PaymentStatus @default(DRAFT) + approvedAt DateTime? + approvedBy String? @db.VarChar(255) + processedAt DateTime? + processedBy String? @db.VarChar(255) + failureReason String? @db.Text + + // Metadata + memo String? @db.Text + + // Audit + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + vendor Vendor? @relation(fields: [vendorId], references: [id], onDelete: SetNull) + customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull) + invoice Invoice? @relation(fields: [invoiceId], references: [id], onDelete: SetNull) + bankAccount BankAccount? @relation(fields: [bankAccountId], references: [id], onDelete: SetNull) + paymentAllocations PaymentAllocation[] + + @@unique([organizationId, paymentNumber]) + @@index([organizationId]) + @@index([paymentDate]) + @@index([status]) + @@index([vendorId]) + @@index([customerId]) + @@map("payments") +} + +model PaymentAllocation { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + paymentId String @db.Uuid + invoiceId String @db.Uuid + + allocatedAmount Decimal @db.Decimal(19, 4) + allocationDate DateTime @default(now()) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + payment Payment @relation(fields: [paymentId], references: [id], onDelete: Cascade) + invoice Invoice @relation(fields: [invoiceId], references: [id], onDelete: Cascade) + + @@unique([paymentId, invoiceId]) + @@index([organizationId]) + @@index([paymentId]) + @@index([invoiceId]) + @@map("payment_allocations") +} + +// ============================================================================ +// TREASURY & BANK ACCOUNTS +// ============================================================================ + +model BankAccount { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + entityId String @db.Uuid + accountName String @db.VarChar(255) + bankName String @db.VarChar(255) + accountNumber String @db.VarChar(50) // Typically masked + accountNumberMasked String @db.VarChar(50) + routingNumber String? @db.VarChar(20) + swiftCode String? @db.VarChar(20) + ibanCode String? @db.VarChar(50) + + currencyCode String @default("USD") @db.VarChar(3) + currentBalance Decimal @db.Decimal(19, 4) + availableBalance Decimal? @db.Decimal(19, 4) + lastBalanceUpdate DateTime? + + accountType String @db.VarChar(50) // Checking, Savings, etc. + status String @default("ACTIVE") @db.VarChar(50) + + // Integration + connectorId String? @db.Uuid + externalAccountId String? @db.VarChar(255) + lastSyncAt DateTime? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + entity Entity @relation(fields: [entityId], references: [id], onDelete: Restrict) + connector Connector? @relation(fields: [connectorId], references: [id], onDelete: SetNull) + bankTransactions BankTransaction[] + payments Payment[] + + @@unique([organizationId, accountNumber]) + @@index([organizationId]) + @@index([status]) + @@map("bank_accounts") +} + +model BankTransaction { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + bankAccountId String @db.Uuid + + transactionDate DateTime + postDate DateTime? + transactionType TransactionType + + amount Decimal @db.Decimal(19, 4) + description String @db.Text + + // Matching + invoiceId String? @db.Uuid + paymentId String? @db.Uuid + journalEntryId String? @db.Uuid + reconciled Boolean @default(false) + reconciledAt DateTime? + + // Bank-provided fields + checkNumber String? @db.VarChar(50) + referenceNumber String? @db.VarChar(255) + oppositeParty String? @db.VarChar(255) + + status String @default("PENDING") @db.VarChar(50) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + bankAccount BankAccount @relation(fields: [bankAccountId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([bankAccountId]) + @@index([transactionDate]) + @@index([reconciled]) + @@map("bank_transactions") +} + +model BankReconciliation { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + bankAccountId String @db.Uuid + + // Period covered + periodStart DateTime + periodEnd DateTime + statementDate DateTime + statementBalance Decimal @db.Decimal(19, 4) + + // Computed at completion + beginningBalance Decimal @default(0) @db.Decimal(19, 4) + endingBookBalance Decimal @default(0) @db.Decimal(19, 4) + clearedDeposits Decimal @default(0) @db.Decimal(19, 4) + clearedWithdrawals Decimal @default(0) @db.Decimal(19, 4) + outstandingDeposits Decimal @default(0) @db.Decimal(19, 4) + outstandingWithdrawals Decimal @default(0) @db.Decimal(19, 4) + difference Decimal @default(0) @db.Decimal(19, 4) + + status String @default("DRAFT") @db.VarChar(20) + // DRAFT | COMPLETED | REOPENED + + reconciledTransactionCount Int @default(0) + notes String? @db.Text + + completedAt DateTime? + completedBy String? @db.VarChar(255) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([bankAccountId]) + @@index([statementDate]) + @@map("bank_reconciliations") +} + +model CashPosition { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + + snapshotDate DateTime + totalCash Decimal @db.Decimal(19, 4) + totalAvailable Decimal @db.Decimal(19, 4) + + // Breakdown + cashByEntity Json? // Map of entity -> cash amount + cashByCurrency Json? // Map of currency -> cash amount + + createdAt DateTime @default(now()) + + @@index([organizationId]) + @@index([snapshotDate]) + @@map("cash_positions") +} + +// ============================================================================ +// INTEGRATIONS +// ============================================================================ + +model Connector { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + + name String @db.VarChar(255) + type ConnectorType + provider String @db.VarChar(100) + description String? @db.Text + + status ConnectorStatus @default(INACTIVE) + healthStatus ConnectorHealthStatus @default(UNKNOWN) + + // Configuration + config Json? // Encrypted config with credentials + configVersion Int @default(1) + + // Sync tracking + lastSyncAt DateTime? + lastSyncStatus String? @db.VarChar(50) + lastErrorMessage String? @db.Text + nextScheduledSync DateTime? + syncFrequencyMinutes Int @default(60) + + // Features + isBidirectional Boolean @default(false) + supportsRealtime Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + connectorLogs ConnectorLog[] + bankAccounts BankAccount[] + + @@unique([organizationId, name]) + @@index([organizationId]) + @@index([status]) + @@index([type]) + @@map("connectors") +} + +model ConnectorLog { + id String @id @default(uuid()) @db.Uuid + connectorId String @db.Uuid + + syncStartTime DateTime + syncEndTime DateTime? + duration Int? // milliseconds + + status String @db.VarChar(50) // SUCCESS, PARTIAL, FAILED + recordsSynced Int @default(0) + recordsProcessed Int @default(0) + recordsFailed Int @default(0) + + errorMessage String? @db.Text + errorDetails Json? + + // AI Healing + aiHealingAttempted Boolean @default(false) + aiHealingAction String? @db.Text + aiHealingSuccess Boolean @default(false) + + // Metadata + syncType String @db.VarChar(50) // FULL, INCREMENTAL + metadata Json? + + // Relations + connector Connector @relation(fields: [connectorId], references: [id], onDelete: Cascade) + + @@index([connectorId]) + @@index([syncStartTime]) + @@index([status]) + @@map("connector_logs") +} + +// ============================================================================ +// AI AUDIT TRAIL +// ============================================================================ + +model AIAction { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + + actionType AIActionType + module String @db.VarChar(100) + + inputSummary String @db.Text + outputSummary String @db.Text + + modelUsed String @db.VarChar(100) + modelVersion String? @db.VarChar(50) + + confidence Decimal? @db.Decimal(5, 4) // 0.0-1.0 + + // User tracking + triggeredByUserId String @db.Uuid + approvedByUserId String? @db.Uuid + + status AIActionStatus @default(PENDING) + + // Approval tracking + approvalComment String? @db.Text + approvalDate DateTime? + rejectionReason String? @db.Text + rejectionDate DateTime? + + // Related records + relatedEntityType String? @db.VarChar(100) // Journal, Invoice, Payment, etc. + relatedEntityId String? @db.Uuid + + // Metadata + parameters Json? + result Json? + + executedAt DateTime? + duration Int? // milliseconds + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + triggeredBy User @relation("TriggeredBy", fields: [triggeredByUserId], references: [id], onDelete: Restrict) + approvedBy User? @relation("ApprovedBy", fields: [approvedByUserId], references: [id], onDelete: SetNull) + + @@index([organizationId]) + @@index([actionType]) + @@index([module]) + @@index([status]) + @@index([createdAt]) + @@index([triggeredByUserId]) + @@map("ai_actions") +} + +// ============================================================================ +// DASHBOARD +// ============================================================================ + +model DashboardConfig { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + userId String @db.Uuid + + name String @db.VarChar(255) + description String? @db.Text + isDefault Boolean @default(false) + + layoutConfig Json // Dashboard layout and widget arrangement + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + widgets Widget[] + + @@unique([organizationId, userId, isDefault]) + @@index([organizationId]) + @@index([userId]) + @@map("dashboard_configs") +} + +model Widget { + id String @id @default(uuid()) @db.Uuid + dashboardConfigId String @db.Uuid + + widgetType String @db.VarChar(100) + title String @db.VarChar(255) + description String? @db.Text + + position Int // Position in grid + rows Int @default(1) + cols Int @default(1) + + config Json? // Widget-specific config + dataSource String? @db.VarChar(255) + refreshInterval Int? // seconds + + isVisible Boolean @default(true) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + dashboardConfig DashboardConfig @relation(fields: [dashboardConfigId], references: [id], onDelete: Cascade) + + @@index([dashboardConfigId]) + @@map("widgets") +} + +// ─── Audit Trail ───────────────────────────────────────────────── + +model AuditLog { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + userId String? @db.Uuid + userName String? @db.VarChar(255) + + action String @db.VarChar(50) // CREATE, UPDATE, DELETE, APPROVE, REJECT, POST, VOID, LOGIN, EXPORT + module String @db.VarChar(100) // general-ledger, ap, ar, treasury, etc. + entityType String @db.VarChar(100) // JournalEntry, Invoice, Payment, etc. + entityId String? @db.VarChar(255) + entityLabel String? @db.VarChar(500) // Human-readable label (e.g., "JE-2024-001") + + description String @db.Text // "Created journal entry JE-2024-001" + changes Json? // { field: { old: x, new: y } } + metadata Json? // Extra context + + ipAddress String? @db.VarChar(50) + userAgent String? @db.Text + + createdAt DateTime @default(now()) + + // Relations + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([organizationId, createdAt]) + @@index([organizationId, module]) + @@index([organizationId, entityType, entityId]) + @@index([userId]) + @@map("audit_logs") +} + +// ─── Cap Table ─────────────────────────────────────────────────── + +model Shareholder { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + name String @db.VarChar(255) + type String @db.VarChar(50) // founder, employee, investor, advisor + sharesOwned Int + shareClass String @db.VarChar(50) // Common, Series A, Series B, Options + vestingCliffMonths Int @default(0) + vestingTotalMonths Int @default(0) + vestedPercent Decimal @default(0) @db.Decimal(5,2) + grantDate DateTime + exercisePrice Decimal @default(0) @db.Decimal(19,4) + status String @default("ACTIVE") @db.VarChar(50) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@map("shareholders") +} + +// ─── Real Estate & Leases ──────────────────────────────────────── + +model Lease { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + description String @db.VarChar(500) + type String @db.VarChar(50) // Operating, Finance + startDate DateTime + endDate DateTime + monthlyPayment Decimal @db.Decimal(19,4) + totalCommitment Decimal @db.Decimal(19,4) + discountRate Decimal @db.Decimal(5,2) + rouAsset Decimal @default(0) @db.Decimal(19,4) + leaseLiability Decimal @default(0) @db.Decimal(19,4) + currentPortion Decimal @default(0) @db.Decimal(19,4) + nonCurrentPortion Decimal @default(0) @db.Decimal(19,4) + status String @default("Active") @db.VarChar(50) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([status]) + @@map("leases") +} + +// ─── Budget ────────────────────────────────────────────────────── + +model BudgetLine { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + accountId String @db.Uuid + fiscalYear Int + monthlyAmounts Json // Array of 12 monthly budget amounts + annualBudget Decimal @db.Decimal(19,4) + notes String? @db.Text + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + account ChartOfAccount @relation(fields: [accountId], references: [id], onDelete: Cascade) + + @@unique([organizationId, accountId, fiscalYear]) + @@index([organizationId]) + @@index([fiscalYear]) + @@map("budget_lines") +} + +// ─── Procurement ───────────────────────────────────────────────── + +model PurchaseOrder { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + poNumber String @db.VarChar(50) + vendorId String @db.Uuid + orderDate DateTime + expectedDate DateTime? + status String @default("DRAFT") @db.VarChar(50) // DRAFT, SUBMITTED, APPROVED, RECEIVED, CANCELLED + subtotal Decimal @default(0) @db.Decimal(19,4) + taxAmount Decimal @default(0) @db.Decimal(19,4) + totalAmount Decimal @default(0) @db.Decimal(19,4) + notes String? @db.Text + approvedBy String? @db.VarChar(255) + approvedAt DateTime? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + vendor Vendor @relation(fields: [vendorId], references: [id], onDelete: Restrict) + lines PurchaseOrderLine[] + + @@unique([organizationId, poNumber]) + @@index([organizationId]) + @@index([vendorId]) + @@index([status]) + @@map("purchase_orders") +} + +model PurchaseOrderLine { + id String @id @default(uuid()) @db.Uuid + purchaseOrderId String @db.Uuid + lineNumber Int + description String @db.Text + quantity Decimal @db.Decimal(19,4) + unitPrice Decimal @db.Decimal(19,4) + lineAmount Decimal @db.Decimal(19,4) + glAccountCode String? @db.VarChar(50) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + purchaseOrder PurchaseOrder @relation(fields: [purchaseOrderId], references: [id], onDelete: Cascade) + + @@index([purchaseOrderId]) + @@map("purchase_order_lines") +} + +// ─── Documents ─────────────────────────────────────────────────── + +model Document { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + name String @db.VarChar(255) + description String? @db.Text + category String @db.VarChar(100) // contract, invoice, receipt, report, legal, other + fileSize Int @default(0) // bytes + mimeType String @db.VarChar(100) + storagePath String @db.VarChar(500) // local path or URL + status String @default("ACTIVE") @db.VarChar(50) + tags Json? // array of tags + uploadedBy String? @db.VarChar(255) + + // Link to related entity + relatedEntityType String? @db.VarChar(100) + relatedEntityId String? @db.Uuid + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([category]) + @@index([status]) + @@map("documents") +} + +// ─── Billing & Subscriptions ───────────────────────────────────── + +model Subscription { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + customerId String @db.Uuid + planName String @db.VarChar(255) + status String @default("ACTIVE") @db.VarChar(50) // ACTIVE, PAUSED, CANCELLED, EXPIRED + billingCycle String @db.VarChar(50) // MONTHLY, QUARTERLY, ANNUAL + amount Decimal @db.Decimal(19,4) + currencyCode String @default("USD") @db.VarChar(3) + startDate DateTime + endDate DateTime? + nextBillingDate DateTime? + cancelledAt DateTime? + notes String? @db.Text + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([customerId]) + @@index([status]) + @@map("subscriptions") +} + +// ─── Financial Planning & Forecasting ──────────────────────────── + +model Forecast { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + name String @db.VarChar(255) + description String? @db.Text + scenarioType String @db.VarChar(50) // BASE, OPTIMISTIC, PESSIMISTIC, CUSTOM + startDate DateTime + endDate DateTime + assumptions Json? // revenue growth rate, expense factors, etc. + projections Json? // monthly projections data + status String @default("DRAFT") @db.VarChar(50) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([scenarioType]) + @@map("forecasts") +} + +// ─── Driver-Based Planning ─────────────────────────────────────── + +model PlanningDriver { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + key String @db.VarChar(100) // stable machine key e.g. "revenue_growth" + name String @db.VarChar(255) + category String @db.VarChar(50) // REVENUE | COST | HEADCOUNT | PRICING | CHURN | UNIT | OTHER + unit String @db.VarChar(50) // PERCENT | CURRENCY | COUNT | RATIO + value Decimal @db.Decimal(19,6) // current/base value + minValue Decimal? @db.Decimal(19,6) + maxValue Decimal? @db.Decimal(19,6) + description String? @db.Text + formula String? @db.Text // optional expression for derived drivers + tags Json? // array of string tags + isActive Boolean @default(true) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@unique([organizationId, key]) + @@index([organizationId]) + @@index([category]) + @@map("planning_drivers") +} + +model PlanningScenario { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + name String @db.VarChar(255) + description String? @db.Text + scenarioType String @default("CUSTOM") @db.VarChar(50) // BASE | OPTIMISTIC | PESSIMISTIC | CUSTOM + horizon Int @default(12) // months + driverOverrides Json // { [driverKey]: number } + assumptions Json? // free-form notes / flags + results Json? // cached computed output + isBaseline Boolean @default(false) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([scenarioType]) + @@index([isBaseline]) + @@map("planning_scenarios") +} + +// ─── Month-End Close ───────────────────────────────────────────── + +model ClosePeriod { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + year Int + month Int // 1-12 + periodLabel String @db.VarChar(50) // e.g. "Mar 2026" + status String @default("OPEN") @db.VarChar(20) // OPEN | IN_PROGRESS | REVIEW | CLOSED + targetCloseDate DateTime? + startedAt DateTime? + actualCloseDate DateTime? + closedBy String? @db.VarChar(255) + notes String? @db.Text + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + tasks CloseTask[] + + @@unique([organizationId, year, month]) + @@index([organizationId]) + @@index([status]) + @@map("close_periods") +} + +model CloseTask { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + closePeriodId String? @db.Uuid // null = template task + taskKey String @db.VarChar(100) // stable key for template lookup + order Int @default(0) + title String @db.VarChar(255) + description String? @db.Text + category String @db.VarChar(50) // AP | AR | BANK | PAYROLL | FIXED_ASSETS | REVENUE | PREPAID | INTERCO | RECON | REVIEW | REPORTING | LOCK + owner String? @db.VarChar(255) + status String @default("PENDING") @db.VarChar(20) // PENDING | IN_PROGRESS | BLOCKED | REVIEW | DONE | SKIPPED + dependsOn Json? // array of taskKey strings + estimatedMinutes Int? + actualMinutes Int? + completedAt DateTime? + completedBy String? @db.VarChar(255) + dueDate DateTime? + notes String? @db.Text + automatable Boolean @default(false) + aiAssisted Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + closePeriod ClosePeriod? @relation(fields: [closePeriodId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([closePeriodId]) + @@index([status]) + @@index([category]) + @@map("close_tasks") +} + +// ─── Revenue Recognition (ASC 606) ─────────────────────────────── + +model RevenueContract { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + customerId String? @db.Uuid + contractNumber String @db.VarChar(100) + name String @db.VarChar(255) + description String? @db.Text + + // Performance obligation + totalValue Decimal @db.Decimal(19,2) + currency String @default("USD") @db.VarChar(3) + + // Service period + startDate DateTime + endDate DateTime + + // Recognition method + recognitionMethod String @default("STRAIGHT_LINE") @db.VarChar(30) + // STRAIGHT_LINE | POINT_IN_TIME | MILESTONE | USAGE_BASED + + billingFrequency String @default("MONTHLY") @db.VarChar(20) + // ONE_TIME | MONTHLY | QUARTERLY | ANNUAL + + status String @default("ACTIVE") @db.VarChar(20) + // DRAFT | ACTIVE | COMPLETED | CANCELLED + + // GL accounts for posting + deferredAccountCode String? @db.VarChar(50) // liability account + revenueAccountCode String? @db.VarChar(50) // P&L revenue account + + notes String? @db.Text + metadata Json? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + customer Customer? @relation(fields: [customerId], references: [id], onDelete: SetNull) + scheduleLines RevenueScheduleLine[] + + @@unique([organizationId, contractNumber]) + @@index([organizationId]) + @@index([customerId]) + @@index([status]) + @@map("revenue_contracts") +} + +model RevenueScheduleLine { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + contractId String @db.Uuid + + periodYear Int + periodMonth Int // 1-12 + periodLabel String @db.VarChar(50) // "Mar 2026" + + amount Decimal @db.Decimal(19,2) + cumulativeRecognized Decimal? @db.Decimal(19,2) + cumulativeDeferred Decimal? @db.Decimal(19,2) + + status String @default("SCHEDULED") @db.VarChar(20) + // SCHEDULED | RECOGNIZED | POSTED + + recognizedAt DateTime? + postedAt DateTime? + journalEntryId String? @db.Uuid + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + contract RevenueContract @relation(fields: [contractId], references: [id], onDelete: Cascade) + + @@index([organizationId]) + @@index([contractId]) + @@index([organizationId, periodYear, periodMonth]) + @@index([status]) + @@map("revenue_schedule_lines") +} + +// ─── Fixed Assets Register ─────────────────────────────────────── + +model FixedAsset { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + + // Identification + assetTag String @db.VarChar(100) + name String @db.VarChar(255) + description String? @db.Text + category String @db.VarChar(100) // Equipment | Furniture | Vehicles | Software | Leasehold | Buildings | Land | Intangible + serialNumber String? @db.VarChar(100) + location String? @db.VarChar(255) + custodian String? @db.VarChar(255) + + // Optional GL link (asset & accumulated depreciation accounts) + assetAccountCode String? @db.VarChar(50) + accumDepreciationAccountCode String? @db.VarChar(50) + depreciationExpenseAccountCode String? @db.VarChar(50) + + // Financials + acquisitionDate DateTime + originalCost Decimal @db.Decimal(19,2) + salvageValue Decimal @default(0) @db.Decimal(19,2) + usefulLifeYears Int + depreciationMethod String @default("STRAIGHT_LINE") @db.VarChar(30) + // STRAIGHT_LINE | DOUBLE_DECLINING | UNITS_OF_PRODUCTION + + // Tracking + accumulatedDepreciation Decimal @default(0) @db.Decimal(19,2) + lastDepreciationDate DateTime? + + // Status + status String @default("ACTIVE") @db.VarChar(20) + // ACTIVE | DISPOSED | FULLY_DEPRECIATED | IDLE + disposalDate DateTime? + disposalProceeds Decimal? @db.Decimal(19,2) + disposalNotes String? @db.Text + + metadata Json? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + createdBy String? @db.VarChar(255) + + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + + @@unique([organizationId, assetTag]) + @@index([organizationId]) + @@index([category]) + @@index([status]) + @@map("fixed_assets") +} + + +// ============================================================================ +// EVE ONLINE SSO & ESI INTEGRATION +// ============================================================================ + +enum EsiSyncStatus { + IDLE + RUNNING + COMPLETED + FAILED +} + +/// Stores EVE SSO OAuth2 tokens for authenticated characters. +/// Each ERP user can link one or more EVE characters. +model EveCharacter { + id String @id @default(uuid()) @db.Uuid + userId String @db.Uuid + organizationId String @db.Uuid + + // EVE character identity (from JWT sub claim) + characterId Int @unique + characterName String @db.VarChar(255) + characterOwnerHash String @db.VarChar(255) + + // Corporation affiliation + corporationId Int? + corporationName String? @db.VarChar(255) + allianceId Int? + allianceName String? @db.VarChar(255) + + // OAuth2 tokens (encrypted at rest in production) + accessToken String @db.Text + refreshToken String @db.Text + tokenExpiresAt DateTime + scopes String @db.Text // Space-separated granted scopes + + // Status + isActive Boolean @default(true) + isPrimary Boolean @default(false) // Primary character for this user + lastSyncAt DateTime? + tokenError String? @db.Text // Last token refresh error, if any + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade) + syncJobs EsiSyncJob[] + + @@index([userId]) + @@index([organizationId]) + @@index([corporationId]) + @@map("eve_characters") +} + +/// Tracks ESI data sync operations per endpoint. +/// Used for rate limiting, caching (ETag/Expires), and error tracking. +model EsiSyncJob { + id String @id @default(uuid()) @db.Uuid + eveCharacterId String @db.Uuid + organizationId String @db.Uuid + + // What we're syncing + endpoint String @db.VarChar(255) // e.g. "corporations/{id}/wallets" + corporationId Int? + division Int? // Wallet division (1-7) + + // Sync state + status EsiSyncStatus @default(IDLE) + lastSuccessAt DateTime? + lastFailureAt DateTime? + lastErrorMessage String? @db.Text + consecutiveFailures Int @default(0) + + // ESI cache headers + etag String? @db.VarChar(255) + cachedUntil DateTime? // From Expires header + pagesFetched Int @default(0) // For paginated endpoints + totalPages Int? + + // Stats + recordsSynced Int @default(0) + lastRunDurationMs Int? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Relations + eveCharacter EveCharacter @relation(fields: [eveCharacterId], references: [id], onDelete: Cascade) + + @@unique([eveCharacterId, endpoint, division]) + @@index([organizationId]) + @@index([status]) + @@index([cachedUntil]) + @@map("esi_sync_jobs") +} + +/// Cached ESI wallet journal entries before they're mapped to GL journal entries. +/// Raw data from /corporations/{id}/wallets/{division}/journal/ +model EsiWalletJournal { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + corporationId Int + division Int + + // ESI fields + esiId BigInt // ESI journal ref_id + date DateTime + refType String @db.VarChar(100) // e.g. "market_transaction", "contract_price" + firstPartyId Int? + firstPartyType String? @db.VarChar(50) // character, corporation, etc. + secondPartyId Int? + secondPartyType String? @db.VarChar(50) + amount Decimal @db.Decimal(19, 4) // ISK amount (positive or negative) + balance Decimal @db.Decimal(19, 4) // Running balance after entry + reason String? @db.Text + description String? @db.Text + taxAmount Decimal? @db.Decimal(19, 4) + taxReceiverId Int? + contextId BigInt? + contextIdType String? @db.VarChar(50) + + // ERP mapping + journalEntryId String? @db.Uuid // Link to GL JournalEntry once mapped + isMapped Boolean @default(false) + mappedAt DateTime? + + createdAt DateTime @default(now()) + + @@unique([corporationId, division, esiId]) + @@index([organizationId]) + @@index([corporationId, division, date]) + @@index([isMapped]) + @@index([refType]) + @@map("esi_wallet_journal") +} + +/// Cached ESI wallet transactions (market buys/sells). +/// From /corporations/{id}/wallets/{division}/transactions/ +model EsiWalletTransaction { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + corporationId Int + division Int + + // ESI fields + transactionId BigInt + date DateTime + typeId Int // EVE type ID (item) + typeName String? @db.VarChar(255) + quantity Int + unitPrice Decimal @db.Decimal(19, 4) + clientId Int // Buyer/seller character/corp + clientName String? @db.VarChar(255) + locationId BigInt // Station/structure ID + locationName String? @db.VarChar(255) + isBuy Boolean // true = purchase, false = sale + journalRefId BigInt // Links to wallet journal entry + + // ERP mapping + invoiceId String? @db.Uuid // Link to AR/AP invoice once mapped + isMapped Boolean @default(false) + mappedAt DateTime? + + createdAt DateTime @default(now()) + + @@unique([corporationId, division, transactionId]) + @@index([organizationId]) + @@index([corporationId, division, date]) + @@index([isMapped]) + @@index([typeId]) + @@map("esi_wallet_transactions") +} + +/// Cached ESI market orders. +/// Sell orders → Accounts Receivable, Buy orders → Accounts Payable +model EsiMarketOrder { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + corporationId Int + + // ESI fields + orderId BigInt @unique + typeId Int + typeName String? @db.VarChar(255) + locationId BigInt + locationName String? @db.VarChar(255) + regionId Int + price Decimal @db.Decimal(19, 4) + volumeTotal Int + volumeRemain Int + isBuyOrder Boolean + issued DateTime + duration Int // Days + minVolume Int @default(1) + state String @db.VarChar(50) // active, cancelled, expired, fulfilled + escrow Decimal? @db.Decimal(19, 4) // For buy orders + walletDivision Int + + // ERP mapping + invoiceId String? @db.Uuid + isMapped Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([organizationId]) + @@index([corporationId, state]) + @@index([typeId]) + @@map("esi_market_orders") +} + +/// Cached ESI industry jobs. +/// Maps to Project Accounting for cost tracking per manufacturing run. +model EsiIndustryJob { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + corporationId Int + + // ESI fields + jobId Int @unique + installerId Int + installerName String? @db.VarChar(255) + facilityId BigInt + activityId Int // 1=manufacturing, 3=TE, 4=ME, 5=copying, 8=invention + blueprintId BigInt + blueprintTypeId Int + blueprintTypeName String? @db.VarChar(255) + blueprintLocationId BigInt + outputLocationId BigInt + runs Int + cost Decimal? @db.Decimal(19, 4) // Installation cost + licensedRuns Int? + probability Float? + productTypeId Int? + productTypeName String? @db.VarChar(255) + status String @db.VarChar(50) // active, cancelled, delivered, paused, ready, reverted + startDate DateTime + endDate DateTime + pauseDate DateTime? + completedDate DateTime? + completedCharacterId Int? + successfulRuns Int? + + // ERP mapping - links to Project in ERP + projectId String? @db.VarChar(255) + isMapped Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([organizationId]) + @@index([corporationId, status]) + @@index([activityId]) + @@map("esi_industry_jobs") +} + +/// Cached ESI blueprints. +/// Maps to Fixed Assets with ME/TE as capital improvements. +model EsiBlueprint { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + corporationId Int + + // ESI fields + itemId BigInt @unique + typeId Int + typeName String? @db.VarChar(255) + locationId BigInt + locationFlag String @db.VarChar(100) + quantity Int // -1 = original, -2 = copy, >0 = stack of BPCs + materialEfficiency Int // 0-10 + timeEfficiency Int // 0-20 + runs Int // -1 = BPO (infinite), >0 = BPC runs remaining + + // ERP mapping - links to FixedAsset + fixedAssetId String? @db.Uuid + isMapped Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([organizationId]) + @@index([corporationId]) + @@index([typeId]) + @@map("esi_blueprints") +} + +/// Cached ESI corporation contracts. +/// Maps to Purchase Orders with fulfillment tracking. +model EsiContract { + id String @id @default(uuid()) @db.Uuid + organizationId String @db.Uuid + corporationId Int + + // ESI fields + contractId Int @unique + issuerId Int + issuerCorporationId Int + assigneeId Int + acceptorId Int @default(0) + contractType String @db.VarChar(50) // item_exchange, courier, auction, unknown + status String @db.VarChar(50) // outstanding, in_progress, finished, etc. + title String? @db.VarChar(255) + availability String @db.VarChar(50) // public, personal, corporation, alliance + forCorporation Boolean + dateIssued DateTime + dateExpired DateTime + dateAccepted DateTime? + dateCompleted DateTime? + daysToComplete Int? + price Decimal @db.Decimal(19, 4) + reward Decimal @default(0) @db.Decimal(19, 4) + collateral Decimal @default(0) @db.Decimal(19, 4) + buyout Decimal? @db.Decimal(19, 4) + volume Decimal? @db.Decimal(19, 4) + startLocationId BigInt? + endLocationId BigInt? + + // ERP mapping + purchaseOrderId String? @db.VarChar(255) + isMapped Boolean @default(false) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([organizationId]) + @@index([corporationId, status]) + @@index([contractType]) + @@map("esi_contracts") +} diff --git a/prisma/seed.ts b/prisma/seed.ts new file mode 100644 index 0000000..eac1fa2 --- /dev/null +++ b/prisma/seed.ts @@ -0,0 +1,1758 @@ +import { PrismaClient, AccountType, RoleType, FiscalPeriodStatus, InvoiceStatus } from "@prisma/client"; +import bcrypt from "bcryptjs"; + +const prisma = new PrismaClient(); + +async function main() { + console.log("🌱 Starting database seed..."); + + // Create Organization + console.log("📊 Creating organization..."); + const organization = await prisma.organization.create({ + data: { + name: "Acme Holdings", + legalName: "Acme Holdings Inc.", + fiscalYearStartMonth: 1, + fiscalYearStartDay: 1, + defaultCurrency: "USD", + timezone: "America/New_York", + }, + }); + console.log(`✓ Organization created: ${organization.name}`); + + // Create Entities + console.log("🏢 Creating entities..."); + const acmeSoftware = await prisma.entity.create({ + data: { + organizationId: organization.id, + name: "Acme Software Inc", + code: "ACM-US", + type: "SUBSIDIARY", + defaultCurrency: "USD", + status: "ACTIVE", + }, + }); + const acmeCloud = await prisma.entity.create({ + data: { + organizationId: organization.id, + name: "Acme Cloud Services Ltd", + code: "ACM-UK", + type: "SUBSIDIARY", + defaultCurrency: "GBP", + status: "ACTIVE", + }, + }); + const acmeEurope = await prisma.entity.create({ + data: { + organizationId: organization.id, + name: "Acme Europe GmbH", + code: "ACM-DE", + type: "SUBSIDIARY", + defaultCurrency: "EUR", + status: "ACTIVE", + }, + }); + const acmePacific = await prisma.entity.create({ + data: { + organizationId: organization.id, + name: "Acme Pacific Pty Ltd", + code: "ACM-AU", + type: "SUBSIDIARY", + defaultCurrency: "AUD", + status: "ACTIVE", + }, + }); + const entities = [acmeSoftware, acmeCloud, acmeEurope, acmePacific]; + console.log(`✓ Created ${entities.length} entities`); + + // Create Roles + console.log("👥 Creating roles..."); + const roleConfigs: { name: string; roleType: RoleType }[] = [ + { name: "CEO", roleType: "CEO" }, + { name: "CFO", roleType: "CFO" }, + { name: "Controller", roleType: "CONTROLLER" }, + { name: "Manager", roleType: "MANAGER" }, + { name: "Analyst", roleType: "ANALYST" }, + { name: "Clerk", roleType: "CLERK" }, + ]; + const roles = []; + for (const rc of roleConfigs) { + const role = await prisma.role.create({ + data: { + organizationId: organization.id, + name: rc.name, + roleType: rc.roleType, + description: `${rc.name} role`, + isSystem: true, + }, + }); + roles.push(role); + } + console.log(`✓ Created ${roles.length} roles`); + + // Create Admin User + console.log("👤 Creating admin user..."); + const hashedPassword = await bcrypt.hash("demo123", 10); + const user = await prisma.user.create({ + data: { + organizationId: organization.id, + email: "ryan@acme.com", + passwordHash: hashedPassword, + name: "Ryan Francis", + firstName: "Ryan", + lastName: "Francis", + status: "ACTIVE", + }, + }); + // Assign CEO role + await prisma.userRole.create({ + data: { + userId: user.id, + roleId: roles[0].id, + }, + }); + console.log(`✓ Admin user created: ${user.email}`); + + // Create Chart of Accounts + console.log("📈 Creating chart of accounts..."); + const accountsData: { code: string; name: string; type: AccountType; parent: string | null }[] = [ + { code: "1000", name: "Cash and Cash Equivalents", type: "ASSET", parent: null }, + { code: "1010", name: "Operating Account", type: "ASSET", parent: "1000" }, + { code: "1020", name: "Payroll Account", type: "ASSET", parent: "1000" }, + { code: "1100", name: "Accounts Receivable", type: "ASSET", parent: null }, + { code: "1200", name: "Prepaid Expenses", type: "ASSET", parent: null }, + { code: "1500", name: "Fixed Assets", type: "ASSET", parent: null }, + { code: "1550", name: "Accumulated Depreciation", type: "ASSET", parent: null }, + { code: "2000", name: "Accounts Payable", type: "LIABILITY", parent: null }, + { code: "2100", name: "Deferred Revenue", type: "LIABILITY", parent: null }, + { code: "2200", name: "Accrued Liabilities", type: "LIABILITY", parent: null }, + { code: "2500", name: "Long-Term Debt", type: "LIABILITY", parent: null }, + { code: "3000", name: "Common Stock", type: "EQUITY", parent: null }, + { code: "3100", name: "Additional Paid-In Capital", type: "EQUITY", parent: null }, + { code: "3200", name: "Retained Earnings", type: "EQUITY", parent: null }, + { code: "4000", name: "Software Revenue", type: "REVENUE", parent: null }, + { code: "4100", name: "Services Revenue", type: "REVENUE", parent: null }, + { code: "4500", name: "Interest Income", type: "REVENUE", parent: null }, + { code: "5000", name: "Cost of Goods Sold", type: "EXPENSE", parent: null }, + { code: "6000", name: "Operating Expenses", type: "EXPENSE", parent: null }, + { code: "6100", name: "Sales & Marketing", type: "EXPENSE", parent: "6000" }, + { code: "6200", name: "Engineering", type: "EXPENSE", parent: "6000" }, + { code: "6300", name: "General & Administrative", type: "EXPENSE", parent: "6000" }, + { code: "6400", name: "IT & Infrastructure", type: "EXPENSE", parent: "6000" }, + { code: "7000", name: "Interest Expense", type: "EXPENSE", parent: null }, + ]; + + // First pass: create all accounts without parents + const accounts: Record = {}; + for (const a of accountsData) { + const account = await prisma.chartOfAccount.create({ + data: { + organizationId: organization.id, + accountCode: a.code, + accountName: a.name, + accountType: a.type, + status: "ACTIVE", + level: a.parent ? 2 : 1, + hierarchy: a.parent ? `${a.parent}/${a.code}` : a.code, + }, + }); + accounts[a.code] = account; + } + + // Second pass: set parent relationships + for (const a of accountsData) { + if (a.parent && accounts[a.parent]) { + await prisma.chartOfAccount.update({ + where: { id: accounts[a.code].id }, + data: { parentAccountId: accounts[a.parent].id }, + }); + } + } + console.log(`✓ Created ${accountsData.length} accounts`); + + // ======================================== + // Create Fiscal Periods for FY2024, FY2025, FY2026 + // ======================================== + console.log("📅 Creating fiscal periods..."); + const months = [ + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December", + ]; + + const allPeriods: Record = {}; + + // FY2024 — all CLOSED + for (let i = 0; i < 12; i++) { + const startDate = new Date(2024, i, 1); + const endDate = new Date(2024, i + 1, 0); + const period = await prisma.fiscalPeriod.create({ + data: { + organizationId: organization.id, + fiscalYear: 2024, + periodNumber: i + 1, + periodName: `${months[i]} 2024`, + startDate, + endDate, + status: "CLOSED" as FiscalPeriodStatus, + }, + }); + allPeriods[`2024-${i + 1}`] = period; + } + + // FY2025 — all CLOSED (year is complete) + for (let i = 0; i < 12; i++) { + const startDate = new Date(2025, i, 1); + const endDate = new Date(2025, i + 1, 0); + const period = await prisma.fiscalPeriod.create({ + data: { + organizationId: organization.id, + fiscalYear: 2025, + periodNumber: i + 1, + periodName: `${months[i]} 2025`, + startDate, + endDate, + status: "CLOSED" as FiscalPeriodStatus, + }, + }); + allPeriods[`2025-${i + 1}`] = period; + } + + // FY2026 — Jan–Mar CLOSED, Apr–Dec OPEN (current date: April 5, 2026) + for (let i = 0; i < 12; i++) { + const startDate = new Date(2026, i, 1); + const endDate = new Date(2026, i + 1, 0); + const status: FiscalPeriodStatus = i < 3 ? "CLOSED" : "OPEN"; + const period = await prisma.fiscalPeriod.create({ + data: { + organizationId: organization.id, + fiscalYear: 2026, + periodNumber: i + 1, + periodName: `${months[i]} 2026`, + startDate, + endDate, + status, + }, + }); + allPeriods[`2026-${i + 1}`] = period; + } + console.log(`✓ Created 36 fiscal periods (FY2024-FY2026)`); + + // ======================================== + // COMPREHENSIVE JOURNAL ENTRIES + // Spanning Jan 2025 – March 2026 across all account types + // ======================================== + console.log("📝 Creating comprehensive journal entries..."); + let jeCounter = 0; + + async function createJE(opts: { + periodKey: string; + date: string; + description: string; + sourceModule: string; + status: "POSTED" | "DRAFT" | "PENDING_APPROVAL"; + entityRef: any; + lines: { accountCode: string; debit: number; credit: number; desc: string }[]; + }) { + jeCounter++; + const entryNumber = `JE-${opts.date.slice(0, 4)}-${String(jeCounter).padStart(4, "0")}`; + const totalDebits = opts.lines.reduce((s, l) => s + l.debit, 0); + const totalCredits = opts.lines.reduce((s, l) => s + l.credit, 0); + const isPosted = opts.status === "POSTED"; + const entryDate = new Date(opts.date); + + return prisma.journalEntry.create({ + data: { + organizationId: organization.id, + fiscalPeriodId: allPeriods[opts.periodKey].id, + entryNumber, + entryDate, + description: opts.description, + sourceModule: opts.sourceModule, + status: opts.status, + totalDebits, + totalCredits, + isBalanced: totalDebits === totalCredits, + postedAt: isPosted ? entryDate : null, + postedBy: isPosted ? user.id : null, + createdBy: user.name, + journalEntryLines: { + create: opts.lines.map((l, idx) => ({ + organizationId: organization.id, + entityId: opts.entityRef.id, + accountId: accounts[l.accountCode].id, + debitAmount: l.debit, + creditAmount: l.credit, + lineNumber: idx + 1, + description: l.desc, + })), + }, + }, + }); + } + + // ---- FY2025 MONTHLY JOURNAL ENTRIES ---- + // We'll create recurring monthly entries + some one-off transactions + + for (let month = 1; month <= 12; month++) { + const mm = String(month).padStart(2, "0"); + const periodKey = `2025-${month}`; + const monthName = months[month - 1]; + + // 1) Monthly Software Revenue (ACM-US) — DR AR, CR Revenue + await createJE({ + periodKey, + date: `2025-${mm}-05`, + description: `${monthName} 2025 software license revenue`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1100", debit: 185000, credit: 0, desc: `AR - software licenses ${monthName}` }, + { accountCode: "4000", debit: 0, credit: 185000, desc: `Software revenue ${monthName}` }, + ], + }); + + // 2) Monthly Services Revenue (ACM-US) — DR AR, CR Services Revenue + await createJE({ + periodKey, + date: `2025-${mm}-08`, + description: `${monthName} 2025 consulting & services revenue`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1100", debit: 92000, credit: 0, desc: `AR - consulting services ${monthName}` }, + { accountCode: "4100", debit: 0, credit: 92000, desc: `Services revenue ${monthName}` }, + ], + }); + + // 3) Monthly Cash Collection (ACM-US) — DR Cash, CR AR + await createJE({ + periodKey, + date: `2025-${mm}-20`, + description: `${monthName} 2025 customer payments received`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1010", debit: 245000, credit: 0, desc: `Cash received from customers ${monthName}` }, + { accountCode: "1100", debit: 0, credit: 245000, desc: `AR collections ${monthName}` }, + ], + }); + + // 4) Monthly COGS (ACM-US) — DR COGS, CR Cash + await createJE({ + periodKey, + date: `2025-${mm}-10`, + description: `${monthName} 2025 cost of goods sold`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "5000", debit: 55000, credit: 0, desc: `COGS - hosting & delivery ${monthName}` }, + { accountCode: "1010", debit: 0, credit: 55000, desc: `Payment for COGS ${monthName}` }, + ], + }); + + // 5) Monthly Engineering Payroll (ACM-US) — DR Engineering, CR Payroll Account + await createJE({ + periodKey, + date: `2025-${mm}-25`, + description: `${monthName} 2025 engineering payroll`, + sourceModule: "PAYROLL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6200", debit: 210000, credit: 0, desc: `Engineering salaries ${monthName}` }, + { accountCode: "1020", debit: 0, credit: 210000, desc: `Payroll disbursement ${monthName}` }, + ], + }); + + // 6) Monthly S&M Expenses — DR S&M, CR AP + await createJE({ + periodKey, + date: `2025-${mm}-12`, + description: `${monthName} 2025 sales & marketing expenses`, + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6100", debit: 45000, credit: 0, desc: `Marketing campaigns & sales ops ${monthName}` }, + { accountCode: "2000", debit: 0, credit: 45000, desc: `AP - marketing vendors ${monthName}` }, + ], + }); + + // 7) Monthly G&A Expenses — DR G&A, CR AP + await createJE({ + periodKey, + date: `2025-${mm}-15`, + description: `${monthName} 2025 general & administrative`, + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6300", debit: 38000, credit: 0, desc: `Office rent, insurance, admin ${monthName}` }, + { accountCode: "2000", debit: 0, credit: 38000, desc: `AP - G&A vendors ${monthName}` }, + ], + }); + + // 8) Monthly IT & Infrastructure — DR IT, CR AP + await createJE({ + periodKey, + date: `2025-${mm}-14`, + description: `${monthName} 2025 IT & infrastructure`, + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6400", debit: 22000, credit: 0, desc: `Cloud hosting, SaaS tools ${monthName}` }, + { accountCode: "2000", debit: 0, credit: 22000, desc: `AP - IT vendors ${monthName}` }, + ], + }); + + // 9) Monthly AP Payments — DR AP, CR Cash (pay last month's bills) + await createJE({ + periodKey, + date: `2025-${mm}-18`, + description: `${monthName} 2025 vendor payments`, + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "2000", debit: 95000, credit: 0, desc: `AP payments to vendors ${monthName}` }, + { accountCode: "1010", debit: 0, credit: 95000, desc: `Cash disbursed ${monthName}` }, + ], + }); + + // 10) Monthly Depreciation — DR Depreciation Expense (G&A), CR Accumulated Depreciation + await createJE({ + periodKey, + date: `2025-${mm}-28`, + description: `${monthName} 2025 depreciation expense`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6300", debit: 8500, credit: 0, desc: `Monthly depreciation ${monthName}` }, + { accountCode: "1550", debit: 0, credit: 8500, desc: `Accumulated depreciation ${monthName}` }, + ], + }); + + // 11) Monthly Interest on Long-Term Debt — DR Interest Expense, CR Accrued Liabilities + await createJE({ + periodKey, + date: `2025-${mm}-28`, + description: `${monthName} 2025 interest expense on long-term debt`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "7000", debit: 4200, credit: 0, desc: `Interest on term loan ${monthName}` }, + { accountCode: "2200", debit: 0, credit: 4200, desc: `Accrued interest ${monthName}` }, + ], + }); + + // 12) Monthly Interest Income — DR Cash, CR Interest Income (small) + await createJE({ + periodKey, + date: `2025-${mm}-28`, + description: `${monthName} 2025 interest income earned`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1010", debit: 1800, credit: 0, desc: `Interest earned on deposits ${monthName}` }, + { accountCode: "4500", debit: 0, credit: 1800, desc: `Interest income ${monthName}` }, + ], + }); + + // UK Entity Revenue (quarterly — Q1, Q2, Q3, Q4) + if (month % 3 === 0) { + await createJE({ + periodKey, + date: `2025-${mm}-15`, + description: `Q${month / 3} 2025 Acme Cloud UK revenue`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeCloud, + lines: [ + { accountCode: "1100", debit: 125000, credit: 0, desc: `AR - UK cloud services Q${month / 3}` }, + { accountCode: "4000", debit: 0, credit: 125000, desc: `UK cloud revenue Q${month / 3}` }, + ], + }); + } + + // Europe Entity Revenue (quarterly) + if (month % 3 === 0) { + await createJE({ + periodKey, + date: `2025-${mm}-16`, + description: `Q${month / 3} 2025 Acme Europe revenue`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeEurope, + lines: [ + { accountCode: "1100", debit: 95000, credit: 0, desc: `AR - Europe consulting Q${month / 3}` }, + { accountCode: "4100", debit: 0, credit: 95000, desc: `Europe services revenue Q${month / 3}` }, + ], + }); + } + + // Pacific Entity Revenue (quarterly) + if (month % 3 === 0) { + await createJE({ + periodKey, + date: `2025-${mm}-17`, + description: `Q${month / 3} 2025 Acme Pacific revenue`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmePacific, + lines: [ + { accountCode: "1100", debit: 68000, credit: 0, desc: `AR - Pacific software Q${month / 3}` }, + { accountCode: "4000", debit: 0, credit: 68000, desc: `Pacific software revenue Q${month / 3}` }, + ], + }); + } + } + + // ---- ONE-OFF FY2025 ENTRIES ---- + + // Fixed Asset Purchase (Q1 2025) — DR Fixed Assets, CR Cash + await createJE({ + periodKey: "2025-2", + date: "2025-02-15", + description: "Server hardware and office equipment purchase", + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1500", debit: 350000, credit: 0, desc: "Server hardware, networking gear" }, + { accountCode: "1010", debit: 0, credit: 350000, desc: "Cash payment for fixed assets" }, + ], + }); + + // Additional Fixed Asset Purchase (Q3 2025) + await createJE({ + periodKey: "2025-8", + date: "2025-08-10", + description: "Office furniture and developer workstations", + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1500", debit: 125000, credit: 0, desc: "Office furniture & workstations" }, + { accountCode: "1010", debit: 0, credit: 125000, desc: "Cash payment for equipment" }, + ], + }); + + // Prepaid Expenses — annual insurance (Jan 2025) + await createJE({ + periodKey: "2025-1", + date: "2025-01-05", + description: "Annual business insurance premium prepayment", + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1200", debit: 96000, credit: 0, desc: "Prepaid D&O and E&O insurance" }, + { accountCode: "1010", debit: 0, credit: 96000, desc: "Cash payment for insurance" }, + ], + }); + + // Deferred Revenue Recognition (Q2 2025) — large annual license prepaid + await createJE({ + periodKey: "2025-4", + date: "2025-04-01", + description: "Received annual license prepayment from Global Partners", + sourceModule: "AR", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1010", debit: 480000, credit: 0, desc: "Cash received - annual prepayment" }, + { accountCode: "2100", debit: 0, credit: 480000, desc: "Deferred revenue - Global Partners" }, + ], + }); + + // Deferred Revenue Recognition monthly (Q2-Q4, 9 months of $53,333) + for (let m = 4; m <= 12; m++) { + const mm = String(m).padStart(2, "0"); + await createJE({ + periodKey: `2025-${m}`, + date: `2025-${mm}-28`, + description: `${months[m - 1]} 2025 deferred revenue recognition`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "2100", debit: 53333, credit: 0, desc: `Deferred rev recognition ${months[m - 1]}` }, + { accountCode: "4000", debit: 0, credit: 53333, desc: `Revenue recognized ${months[m - 1]}` }, + ], + }); + } + + // Long-term Debt Drawdown (Mar 2025) — DR Cash, CR Long-Term Debt + await createJE({ + periodKey: "2025-3", + date: "2025-03-01", + description: "Term loan drawdown - growth capital", + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1010", debit: 2000000, credit: 0, desc: "Loan proceeds received" }, + { accountCode: "2500", debit: 0, credit: 2000000, desc: "Term loan - 5yr facility" }, + ], + }); + + // Equity Contribution (Jan 2025) — Series B round + await createJE({ + periodKey: "2025-1", + date: "2025-01-15", + description: "Series B equity investment received", + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1010", debit: 5000000, credit: 0, desc: "Series B investment proceeds" }, + { accountCode: "3000", debit: 0, credit: 500000, desc: "Common stock par value" }, + { accountCode: "3100", debit: 0, credit: 4500000, desc: "Additional paid-in capital" }, + ], + }); + + // Quarterly debt principal repayment + for (const q of [6, 9, 12]) { + const mm = String(q).padStart(2, "0"); + await createJE({ + periodKey: `2025-${q}`, + date: `2025-${mm}-30`, + description: `Q${q / 3} 2025 loan principal repayment`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "2500", debit: 100000, credit: 0, desc: `Term loan principal Q${q / 3}` }, + { accountCode: "1010", debit: 0, credit: 100000, desc: `Cash - loan repayment Q${q / 3}` }, + ], + }); + } + + // Payroll Account Funding (monthly — DR Payroll, CR Operating) + for (let month = 1; month <= 12; month++) { + const mm = String(month).padStart(2, "0"); + await createJE({ + periodKey: `2025-${month}`, + date: `2025-${mm}-22`, + description: `${months[month - 1]} 2025 payroll account funding`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1020", debit: 210000, credit: 0, desc: `Payroll funding ${months[month - 1]}` }, + { accountCode: "1010", debit: 0, credit: 210000, desc: `Transfer to payroll ${months[month - 1]}` }, + ], + }); + } + + // ---- FY2026 Q1 JOURNAL ENTRIES (Jan–Mar 2026) ---- + for (let month = 1; month <= 3; month++) { + const mm = String(month).padStart(2, "0"); + const periodKey = `2026-${month}`; + const monthName = months[month - 1]; + + // Revenue entries (growing 10% over FY2025) + await createJE({ + periodKey, + date: `2026-${mm}-05`, + description: `${monthName} 2026 software license revenue`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1100", debit: 203500, credit: 0, desc: `AR - software licenses ${monthName}` }, + { accountCode: "4000", debit: 0, credit: 203500, desc: `Software revenue ${monthName}` }, + ], + }); + + await createJE({ + periodKey, + date: `2026-${mm}-08`, + description: `${monthName} 2026 services revenue`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1100", debit: 101200, credit: 0, desc: `AR - consulting services ${monthName}` }, + { accountCode: "4100", debit: 0, credit: 101200, desc: `Services revenue ${monthName}` }, + ], + }); + + // Cash collections + await createJE({ + periodKey, + date: `2026-${mm}-20`, + description: `${monthName} 2026 customer payments received`, + sourceModule: "AR", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1010", debit: 270000, credit: 0, desc: `Cash received ${monthName}` }, + { accountCode: "1100", debit: 0, credit: 270000, desc: `AR collections ${monthName}` }, + ], + }); + + // COGS + await createJE({ + periodKey, + date: `2026-${mm}-10`, + description: `${monthName} 2026 cost of goods sold`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "5000", debit: 60500, credit: 0, desc: `COGS ${monthName}` }, + { accountCode: "1010", debit: 0, credit: 60500, desc: `COGS payment ${monthName}` }, + ], + }); + + // Engineering Payroll + await createJE({ + periodKey, + date: `2026-${mm}-25`, + description: `${monthName} 2026 engineering payroll`, + sourceModule: "PAYROLL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6200", debit: 225000, credit: 0, desc: `Engineering salaries ${monthName}` }, + { accountCode: "1020", debit: 0, credit: 225000, desc: `Payroll disbursement ${monthName}` }, + ], + }); + + // S&M + await createJE({ + periodKey, + date: `2026-${mm}-12`, + description: `${monthName} 2026 sales & marketing`, + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6100", debit: 49500, credit: 0, desc: `Marketing ${monthName}` }, + { accountCode: "2000", debit: 0, credit: 49500, desc: `AP - marketing ${monthName}` }, + ], + }); + + // G&A + await createJE({ + periodKey, + date: `2026-${mm}-15`, + description: `${monthName} 2026 G&A expenses`, + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6300", debit: 41800, credit: 0, desc: `G&A expenses ${monthName}` }, + { accountCode: "2000", debit: 0, credit: 41800, desc: `AP - G&A ${monthName}` }, + ], + }); + + // IT + await createJE({ + periodKey, + date: `2026-${mm}-14`, + description: `${monthName} 2026 IT & infrastructure`, + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6400", debit: 24200, credit: 0, desc: `IT costs ${monthName}` }, + { accountCode: "2000", debit: 0, credit: 24200, desc: `AP - IT ${monthName}` }, + ], + }); + + // AP Payments + await createJE({ + periodKey, + date: `2026-${mm}-18`, + description: `${monthName} 2026 vendor payments`, + sourceModule: "AP", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "2000", debit: 105000, credit: 0, desc: `AP payments ${monthName}` }, + { accountCode: "1010", debit: 0, credit: 105000, desc: `Cash disbursed ${monthName}` }, + ], + }); + + // Depreciation + await createJE({ + periodKey, + date: `2026-${mm}-28`, + description: `${monthName} 2026 depreciation`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6300", debit: 9900, credit: 0, desc: `Depreciation ${monthName}` }, + { accountCode: "1550", debit: 0, credit: 9900, desc: `Accum depreciation ${monthName}` }, + ], + }); + + // Interest Expense + await createJE({ + periodKey, + date: `2026-${mm}-28`, + description: `${monthName} 2026 interest expense`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "7000", debit: 3500, credit: 0, desc: `Interest on debt ${monthName}` }, + { accountCode: "2200", debit: 0, credit: 3500, desc: `Accrued interest ${monthName}` }, + ], + }); + + // Interest Income + await createJE({ + periodKey, + date: `2026-${mm}-28`, + description: `${monthName} 2026 interest income`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1010", debit: 2100, credit: 0, desc: `Interest earned ${monthName}` }, + { accountCode: "4500", debit: 0, credit: 2100, desc: `Interest income ${monthName}` }, + ], + }); + + // Payroll funding + await createJE({ + periodKey, + date: `2026-${mm}-22`, + description: `${monthName} 2026 payroll account funding`, + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1020", debit: 225000, credit: 0, desc: `Payroll funding ${monthName}` }, + { accountCode: "1010", debit: 0, credit: 225000, desc: `Transfer to payroll ${monthName}` }, + ], + }); + } + + // Q1 2026 subsidiary revenues + await createJE({ + periodKey: "2026-3", + date: "2026-03-15", + description: "Q1 2026 Acme Cloud UK revenue", + sourceModule: "AR", + status: "POSTED", + entityRef: acmeCloud, + lines: [ + { accountCode: "1100", debit: 142000, credit: 0, desc: "AR - UK cloud services Q1 2026" }, + { accountCode: "4000", debit: 0, credit: 142000, desc: "UK cloud revenue Q1 2026" }, + ], + }); + await createJE({ + periodKey: "2026-3", + date: "2026-03-16", + description: "Q1 2026 Acme Europe revenue", + sourceModule: "AR", + status: "POSTED", + entityRef: acmeEurope, + lines: [ + { accountCode: "1100", debit: 108000, credit: 0, desc: "AR - Europe consulting Q1 2026" }, + { accountCode: "4100", debit: 0, credit: 108000, desc: "Europe services revenue Q1 2026" }, + ], + }); + await createJE({ + periodKey: "2026-3", + date: "2026-03-17", + description: "Q1 2026 Acme Pacific revenue", + sourceModule: "AR", + status: "POSTED", + entityRef: acmePacific, + lines: [ + { accountCode: "1100", debit: 78000, credit: 0, desc: "AR - Pacific software Q1 2026" }, + { accountCode: "4000", debit: 0, credit: 78000, desc: "Pacific revenue Q1 2026" }, + ], + }); + + // FY2026 Opening retained earnings entry (close FY2025 net income) + // FY2025 Net Income calc: Revenue (185k*12+92k*12+125k*4+95k*4+68k*4+53.3k*9+1.8k*12) - Expenses + // Approx: Revenue ~$4.87M, Expenses ~$4.61M → Net income ~$260k → round to closing entry + await createJE({ + periodKey: "2026-1", + date: "2026-01-01", + description: "FY2025 year-end close - retained earnings", + sourceModule: "GL", + status: "POSTED", + entityRef: acmeSoftware, + lines: [ + { accountCode: "3200", debit: 0, credit: 258400, desc: "FY2025 net income to retained earnings" }, + { accountCode: "1010", debit: 258400, credit: 0, desc: "Opening balance adjustment" }, + ], + }); + + // A couple DRAFT entries in April 2026 (current month) + await createJE({ + periodKey: "2026-4", + date: "2026-04-03", + description: "April 2026 software revenue accrual (draft)", + sourceModule: "AR", + status: "DRAFT", + entityRef: acmeSoftware, + lines: [ + { accountCode: "1100", debit: 203500, credit: 0, desc: "AR - April software" }, + { accountCode: "4000", debit: 0, credit: 203500, desc: "April software revenue" }, + ], + }); + + await createJE({ + periodKey: "2026-4", + date: "2026-04-04", + description: "April 2026 payroll accrual (pending approval)", + sourceModule: "PAYROLL", + status: "PENDING_APPROVAL", + entityRef: acmeSoftware, + lines: [ + { accountCode: "6200", debit: 225000, credit: 0, desc: "April engineering payroll" }, + { accountCode: "2200", debit: 0, credit: 225000, desc: "Accrued payroll" }, + ], + }); + + console.log(`✓ Created ${jeCounter} journal entries`); + + // ======================================== + // VENDORS + // ======================================== + console.log("🏪 Creating vendors..."); + const vendors = []; + const vendorData = [ + { code: "V001", name: "Amazon Web Services", termDays: 30, type: "Cloud Services", email: "billing@aws.amazon.com", phone: "206-555-0100" }, + { code: "V002", name: "Salesforce Inc", termDays: 45, type: "Software", email: "invoices@salesforce.com", phone: "415-555-0200" }, + { code: "V003", name: "WeWork", termDays: 30, type: "Real Estate", email: "accounts@wework.com", phone: "212-555-0300" }, + { code: "V004", name: "ADP Inc", termDays: 15, type: "HR Services", email: "billing@adp.com", phone: "973-555-0400" }, + { code: "V005", name: "Dell Technologies", termDays: 60, type: "Hardware", email: "orders@dell.com", phone: "512-555-0500" }, + { code: "V006", name: "Google Cloud Platform", termDays: 30, type: "Cloud Services", email: "billing@google.com", phone: "650-555-0600" }, + { code: "V007", name: "Datadog Inc", termDays: 30, type: "Software", email: "billing@datadoghq.com", phone: "646-555-0700" }, + { code: "V008", name: "Marsh McLennan", termDays: 45, type: "Insurance", email: "accounts@marsh.com", phone: "212-555-0800" }, + ]; + + for (const v of vendorData) { + const vendor = await prisma.vendor.create({ + data: { + organizationId: organization.id, + vendorCode: v.code, + vendorName: v.name, + vendorType: v.type, + paymentTermDays: v.termDays, + email: v.email, + phone: v.phone, + status: "ACTIVE", + }, + }); + vendors.push(vendor); + } + console.log(`✓ Created ${vendors.length} vendors`); + + // ======================================== + // PURCHASE ORDERS + // ======================================== + console.log("📦 Creating purchase orders..."); + const purchaseOrders = []; + const poData = [ + { + poNumber: "PO-2026-001", vendor: vendors[0], orderDate: new Date("2026-01-15"), expectedDate: new Date("2026-02-01"), + status: "RECEIVED", subtotal: 22000, tax: 1980, + lines: [{ lineNumber: 1, description: "AWS Reserved Instances - Q1 2026", quantity: 1, unitPrice: 22000 }], + }, + { + poNumber: "PO-2026-002", vendor: vendors[1], orderDate: new Date("2026-01-20"), expectedDate: new Date("2026-02-15"), + status: "RECEIVED", subtotal: 48000, tax: 4320, + lines: [{ lineNumber: 1, description: "Salesforce Enterprise - Annual Renewal", quantity: 1, unitPrice: 48000 }], + }, + { + poNumber: "PO-2026-003", vendor: vendors[2], orderDate: new Date("2026-02-01"), expectedDate: new Date("2026-03-01"), + status: "APPROVED", subtotal: 30000, tax: 2700, + lines: [ + { lineNumber: 1, description: "Office lease - Q2 2026", quantity: 3, unitPrice: 8000 }, + { lineNumber: 2, description: "Common area + utilities", quantity: 1, unitPrice: 6000 }, + ], + }, + { + poNumber: "PO-2026-004", vendor: vendors[4], orderDate: new Date("2026-02-10"), expectedDate: new Date("2026-03-10"), + status: "PARTIALLY_RECEIVED", subtotal: 75000, tax: 6750, + lines: [{ lineNumber: 1, description: "Developer workstations - new hires", quantity: 15, unitPrice: 5000 }], + }, + { + poNumber: "PO-2026-005", vendor: vendors[5], orderDate: new Date("2026-03-01"), expectedDate: new Date("2026-03-15"), + status: "SENT", subtotal: 18000, tax: 1620, + lines: [{ lineNumber: 1, description: "GCP BigQuery & Vertex AI credits", quantity: 1, unitPrice: 18000 }], + }, + { + poNumber: "PO-2026-006", vendor: vendors[6], orderDate: new Date("2026-03-05"), expectedDate: new Date("2026-03-20"), + status: "APPROVED", subtotal: 9600, tax: 864, + lines: [{ lineNumber: 1, description: "Datadog Pro - Annual", quantity: 1, unitPrice: 9600 }], + }, + { + poNumber: "PO-2026-007", vendor: vendors[3], orderDate: new Date("2026-03-15"), expectedDate: new Date("2026-04-01"), + status: "SENT", subtotal: 12000, tax: 1080, + lines: [{ lineNumber: 1, description: "ADP Workforce Now - Q2 processing", quantity: 1, unitPrice: 12000 }], + }, + { + poNumber: "PO-2026-008", vendor: vendors[7], orderDate: new Date("2026-01-10"), expectedDate: new Date("2026-01-31"), + status: "RECEIVED", subtotal: 96000, tax: 8640, + lines: [{ lineNumber: 1, description: "Annual D&O and E&O insurance premium", quantity: 1, unitPrice: 96000 }], + }, + ]; + + for (const po of poData) { + const subtotal = po.lines.reduce((sum, line) => sum + (line.quantity * line.unitPrice), 0); + const totalAmount = subtotal + po.tax; + const purchaseOrder = await prisma.purchaseOrder.create({ + data: { + organizationId: organization.id, + poNumber: po.poNumber, + vendorId: po.vendor.id, + orderDate: po.orderDate, + expectedDate: po.expectedDate, + status: po.status, + subtotal: subtotal.toString(), + taxAmount: po.tax.toString(), + totalAmount: totalAmount.toString(), + notes: null, + createdBy: user.id, + lines: { + create: po.lines.map(line => ({ + lineNumber: line.lineNumber, + description: line.description, + quantity: line.quantity, + unitPrice: line.unitPrice, + lineAmount: (line.quantity * line.unitPrice).toString(), + glAccountCode: null, + })), + }, + }, + include: { vendor: true, lines: true }, + }); + purchaseOrders.push(purchaseOrder); + } + console.log(`✓ Created ${purchaseOrders.length} purchase orders`); + + // ======================================== + // CUSTOMERS + // ======================================== + console.log("👥 Creating customers..."); + const customers = []; + const customerData = [ + { code: "C001", name: "ABC Corporation", termDays: 30, type: "Enterprise", email: "ap@abccorp.com", phone: "212-555-1001" }, + { code: "C002", name: "TechVenture Inc", termDays: 30, type: "SaaS", email: "billing@techventure.io", phone: "415-555-1002" }, + { code: "C003", name: "Global Partners Ltd", termDays: 45, type: "Consulting", email: "finance@globalpartners.com", phone: "44-20-555-1003" }, + { code: "C004", name: "Premier Solutions Group", termDays: 30, type: "Enterprise", email: "accounts@premiersolutions.com", phone: "312-555-1004" }, + { code: "C005", name: "StartUp Ventures", termDays: 15, type: "Startup", email: "cfo@startupventures.co", phone: "650-555-1005" }, + { code: "C006", name: "Northern Health Systems", termDays: 45, type: "Enterprise", email: "procurement@northernhealth.org", phone: "617-555-1006" }, + { code: "C007", name: "Pacific Retail Group", termDays: 30, type: "Enterprise", email: "finance@pacificretail.com", phone: "503-555-1007" }, + { code: "C008", name: "Atlas Financial Corp", termDays: 30, type: "Financial Services", email: "vendor-mgmt@atlasfinancial.com", phone: "704-555-1008" }, + ]; + + for (const c of customerData) { + const customer = await prisma.customer.create({ + data: { + organizationId: organization.id, + customerCode: c.code, + customerName: c.name, + customerType: c.type, + paymentTermDays: c.termDays, + email: c.email, + phone: c.phone, + status: "ACTIVE", + }, + }); + customers.push(customer); + } + console.log(`✓ Created ${customers.length} customers`); + + // ======================================== + // AP INVOICES (FY2026 Q1) + // ======================================== + console.log("📄 Creating AP invoices..."); + const apInvoices = []; + const apInvoiceData = [ + { number: "INV-AP-2026-0001", vendor: vendors[0], amount: 22000, status: "PAID" as InvoiceStatus, issueDate: new Date("2026-01-10"), dueDate: new Date("2026-02-15"), paidAmount: 22000, + lines: [{ accountCode: "6400", description: "AWS Reserved Instances - Jan", amount: 22000 }] }, + { number: "INV-AP-2026-0002", vendor: vendors[1], amount: 48000, status: "PAID" as InvoiceStatus, issueDate: new Date("2026-01-20"), dueDate: new Date("2026-03-05"), paidAmount: 48000, + lines: [{ accountCode: "6100", description: "Salesforce Enterprise - Annual", amount: 48000 }] }, + { number: "INV-AP-2026-0003", vendor: vendors[2], amount: 30000, status: "APPROVED" as InvoiceStatus, issueDate: new Date("2026-02-01"), dueDate: new Date("2026-04-01"), + lines: [{ accountCode: "6300", description: "Office lease - Q2", amount: 24000 }, { accountCode: "6300", description: "Utilities Q2", amount: 6000 }] }, + { number: "INV-AP-2026-0004", vendor: vendors[3], amount: 12000, status: "PENDING_APPROVAL" as InvoiceStatus, issueDate: new Date("2026-03-15"), dueDate: new Date("2026-04-15"), + lines: [{ accountCode: "6300", description: "ADP Payroll Processing Q2", amount: 12000 }] }, + { number: "INV-AP-2026-0005", vendor: vendors[4], amount: 75000, status: "PARTIALLY_PAID" as InvoiceStatus, issueDate: new Date("2026-02-10"), dueDate: new Date("2026-04-10"), paidAmount: 37500, + lines: [{ accountCode: "6400", description: "Developer workstations", amount: 75000 }] }, + { number: "INV-AP-2026-0006", vendor: vendors[0], amount: 24200, status: "APPROVED" as InvoiceStatus, issueDate: new Date("2026-02-28"), dueDate: new Date("2026-03-30"), + lines: [{ accountCode: "6400", description: "AWS usage - February", amount: 24200 }] }, + { number: "INV-AP-2026-0007", vendor: vendors[5], amount: 18000, status: "DRAFT" as InvoiceStatus, issueDate: new Date("2026-03-25"), dueDate: new Date("2026-04-30"), + lines: [{ accountCode: "6400", description: "GCP BigQuery & AI credits", amount: 18000 }] }, + { number: "INV-AP-2026-0008", vendor: vendors[6], amount: 9600, status: "APPROVED" as InvoiceStatus, issueDate: new Date("2026-03-05"), dueDate: new Date("2026-04-05"), + lines: [{ accountCode: "6400", description: "Datadog Pro Annual", amount: 9600 }] }, + { number: "INV-AP-2026-0009", vendor: vendors[7], amount: 96000, status: "PAID" as InvoiceStatus, issueDate: new Date("2026-01-08"), dueDate: new Date("2026-02-10"), paidAmount: 96000, + lines: [{ accountCode: "1200", description: "Annual D&O + E&O insurance", amount: 96000 }] }, + { number: "INV-AP-2026-0010", vendor: vendors[2], amount: 8000, status: "OVERDUE" as InvoiceStatus, issueDate: new Date("2026-01-25"), dueDate: new Date("2026-03-01"), daysOverdue: 35, + lines: [{ accountCode: "6300", description: "Conference room rental Feb", amount: 8000 }] }, + { number: "INV-AP-2026-0011", vendor: vendors[0], amount: 24200, status: "APPROVED" as InvoiceStatus, issueDate: new Date("2026-03-28"), dueDate: new Date("2026-04-30"), + lines: [{ accountCode: "6400", description: "AWS usage - March", amount: 24200 }] }, + { number: "INV-AP-2026-0012", vendor: vendors[4], amount: 15000, status: "DRAFT" as InvoiceStatus, issueDate: new Date("2026-04-01"), dueDate: new Date("2026-05-10"), + lines: [{ accountCode: "1500", description: "Additional server hardware", amount: 15000 }] }, + ]; + + for (const apData of apInvoiceData) { + const invoiceLines = apData.lines.map((line, index) => ({ + description: line.description, quantity: 1, unitPrice: line.amount, lineAmount: line.amount, + lineNumber: index + 1, glAccountCode: line.accountCode, + })); + const totalAmount = apData.lines.reduce((sum, line) => sum + line.amount, 0); + const paidAmount = apData.paidAmount ?? (apData.status === "PAID" ? totalAmount : 0); + const invoice = await prisma.invoice.create({ + data: { + organizationId: organization.id, entityId: acmeSoftware.id, vendorId: apData.vendor.id, + invoiceNumber: apData.number, invoiceDate: apData.issueDate, dueDate: apData.dueDate, + invoiceType: "ACCOUNTS_PAYABLE", status: apData.status, + subtotalAmount: totalAmount, totalAmount, paidAmount, balanceDue: totalAmount - paidAmount, + daysOverdue: apData.daysOverdue ?? null, + invoiceLines: { create: invoiceLines }, + }, + }); + apInvoices.push(invoice); + } + console.log(`✓ Created ${apInvoices.length} AP invoices`); + + // ======================================== + // AR INVOICES (FY2026 Q1) + // ======================================== + console.log("📄 Creating AR invoices..."); + const arInvoices = []; + const arInvoiceData = [ + { number: "INV-AR-2026-0001", customer: customers[0], amount: 185000, status: "PAID" as InvoiceStatus, issueDate: new Date("2026-01-05"), dueDate: new Date("2026-02-14"), paidAmount: 185000, + lines: [{ accountCode: "4000", description: "Enterprise platform license - Jan", amount: 185000 }] }, + { number: "INV-AR-2026-0002", customer: customers[1], amount: 45000, status: "PAID" as InvoiceStatus, issueDate: new Date("2026-01-08"), dueDate: new Date("2026-02-14"), paidAmount: 45000, + lines: [{ accountCode: "4100", description: "SaaS subscription Q1", amount: 45000 }] }, + { number: "INV-AR-2026-0003", customer: customers[2], amount: 92000, status: "APPROVED" as InvoiceStatus, issueDate: new Date("2026-02-10"), dueDate: new Date("2026-03-30"), + lines: [{ accountCode: "4100", description: "Consulting engagement - Feb/Mar", amount: 92000 }] }, + { number: "INV-AR-2026-0004", customer: customers[3], amount: 203500, status: "PAID" as InvoiceStatus, issueDate: new Date("2026-02-01"), dueDate: new Date("2026-03-14"), paidAmount: 203500, + lines: [{ accountCode: "4000", description: "Enterprise license renewal", amount: 203500 }] }, + { number: "INV-AR-2026-0005", customer: customers[4], amount: 24000, status: "OVERDUE" as InvoiceStatus, issueDate: new Date("2026-01-15"), dueDate: new Date("2026-02-20"), daysOverdue: 44, + lines: [{ accountCode: "4100", description: "Startup plan - 12 months", amount: 24000 }] }, + { number: "INV-AR-2026-0006", customer: customers[0], amount: 101200, status: "PARTIALLY_PAID" as InvoiceStatus, issueDate: new Date("2026-03-01"), dueDate: new Date("2026-04-14"), paidAmount: 50000, + lines: [{ accountCode: "4000", description: "Implementation services", amount: 101200 }] }, + { number: "INV-AR-2026-0007", customer: customers[5], amount: 156000, status: "APPROVED" as InvoiceStatus, issueDate: new Date("2026-03-10"), dueDate: new Date("2026-04-30"), + lines: [{ accountCode: "4000", description: "Healthcare platform license", amount: 156000 }] }, + { number: "INV-AR-2026-0008", customer: customers[6], amount: 78000, status: "DRAFT" as InvoiceStatus, issueDate: new Date("2026-03-20"), dueDate: new Date("2026-05-15"), + lines: [{ accountCode: "4000", description: "Retail analytics module", amount: 78000 }] }, + { number: "INV-AR-2026-0009", customer: customers[7], amount: 210000, status: "APPROVED" as InvoiceStatus, issueDate: new Date("2026-03-15"), dueDate: new Date("2026-04-20"), + lines: [{ accountCode: "4000", description: "Financial compliance suite", amount: 135000 }, { accountCode: "4100", description: "Integration services", amount: 75000 }] }, + { number: "INV-AR-2026-0010", customer: customers[1], amount: 15000, status: "APPROVED" as InvoiceStatus, issueDate: new Date("2026-03-28"), dueDate: new Date("2026-04-14"), + lines: [{ accountCode: "4100", description: "SaaS subscription Q2", amount: 15000 }] }, + ]; + + for (const arData of arInvoiceData) { + const invoiceLines = arData.lines.map((line, index) => ({ + description: line.description, quantity: 1, unitPrice: line.amount, lineAmount: line.amount, + lineNumber: index + 1, glAccountCode: line.accountCode, + })); + const totalAmount = arData.lines.reduce((sum, line) => sum + line.amount, 0); + const paidAmount = arData.paidAmount ?? (arData.status === "PAID" ? totalAmount : 0); + const invoice = await prisma.invoice.create({ + data: { + organizationId: organization.id, entityId: acmeSoftware.id, customerId: arData.customer.id, + invoiceNumber: arData.number, invoiceDate: arData.issueDate, dueDate: arData.dueDate, + invoiceType: "ACCOUNTS_RECEIVABLE", status: arData.status, + subtotalAmount: totalAmount, totalAmount, paidAmount, balanceDue: totalAmount - paidAmount, + daysOverdue: arData.daysOverdue ?? null, + invoiceLines: { create: invoiceLines }, + }, + }); + arInvoices.push(invoice); + } + console.log(`✓ Created ${arInvoices.length} AR invoices`); + + // ======================================== + // PAYMENTS + // ======================================== + console.log("💳 Creating payments..."); + const payments = []; + + const paymentConfigs = [ + { vendorId: vendors[0].id, invoiceIdx: 0, number: "PAY-2026-0001", date: "2026-02-10", method: "BANK_TRANSFER" as const, amount: 22000 }, + { vendorId: vendors[1].id, invoiceIdx: 1, number: "PAY-2026-0002", date: "2026-02-28", method: "BANK_TRANSFER" as const, amount: 48000 }, + { vendorId: vendors[7].id, invoiceIdx: 8, number: "PAY-2026-0003", date: "2026-02-05", method: "WIRE" as const, amount: 96000 }, + { vendorId: vendors[4].id, invoiceIdx: 4, number: "PAY-2026-0004", date: "2026-03-20", method: "BANK_TRANSFER" as const, amount: 37500 }, + { customerId: customers[0].id, invoiceIdx: 0, isAR: true, number: "PAY-2026-0005", date: "2026-02-12", method: "BANK_TRANSFER" as const, amount: 185000 }, + { customerId: customers[1].id, invoiceIdx: 1, isAR: true, number: "PAY-2026-0006", date: "2026-02-10", method: "ACH" as const, amount: 45000 }, + { customerId: customers[3].id, invoiceIdx: 3, isAR: true, number: "PAY-2026-0007", date: "2026-03-10", method: "WIRE" as const, amount: 203500 }, + { customerId: customers[0].id, invoiceIdx: 5, isAR: true, number: "PAY-2026-0008", date: "2026-04-01", method: "CHECK" as const, amount: 50000 }, + ]; + + for (const pc of paymentConfigs) { + const invoiceRef = pc.isAR ? arInvoices[pc.invoiceIdx] : apInvoices[pc.invoiceIdx]; + const payment = await prisma.payment.create({ + data: { + organizationId: organization.id, + vendorId: pc.vendorId || null, + customerId: pc.customerId || null, + invoiceId: invoiceRef.id, + paymentNumber: pc.number, + paymentDate: new Date(pc.date), + paymentMethod: pc.method, + status: "COMPLETED", + paymentAmount: pc.amount, + totalPaymentAmount: pc.amount, + paymentAllocations: { + create: [{ organizationId: organization.id, invoiceId: invoiceRef.id, allocatedAmount: pc.amount }], + }, + }, + }); + payments.push(payment); + } + console.log(`✓ Created ${payments.length} payments`); + + // ======================================== + // BANK ACCOUNTS + // ======================================== + console.log("🏦 Creating bank accounts..."); + const bankAccounts = []; + const bankAccountsData = [ + { name: "Chase Business Checking", bank: "Chase Bank", number: "****2847", type: "Checking", balance: 2845600.75, entity: acmeSoftware }, + { name: "Bank of America Payroll", bank: "Bank of America", number: "****5923", type: "Checking", balance: 485340.50, entity: acmeSoftware }, + { name: "Silicon Valley Bank", bank: "Silicon Valley Bank", number: "****7412", type: "Checking", balance: 1524850.00, entity: acmeSoftware }, + { name: "Mercury Bank", bank: "Mercury", number: "****3156", type: "Savings", balance: 289750.25, entity: acmeSoftware }, + { name: "Wells Fargo Business Savings", bank: "Wells Fargo", number: "****9284", type: "Savings", balance: 756200.00, entity: acmeSoftware }, + { name: "Barclays UK Account", bank: "Barclays", number: "****6201", type: "Checking", balance: 342000.00, entity: acmeCloud }, + { name: "Deutsche Bank EUR", bank: "Deutsche Bank", number: "****8834", type: "Checking", balance: 215000.00, entity: acmeEurope }, + { name: "ANZ Business", bank: "ANZ", number: "****4477", type: "Checking", balance: 178500.00, entity: acmePacific }, + ]; + + for (const accData of bankAccountsData) { + const account = await prisma.bankAccount.create({ + data: { + organizationId: organization.id, + entityId: accData.entity.id, + accountName: accData.name, + bankName: accData.bank, + accountNumber: accData.number, + accountNumberMasked: accData.number, + accountType: accData.type, + currencyCode: accData.entity === acmeCloud ? "GBP" : accData.entity === acmeEurope ? "EUR" : accData.entity === acmePacific ? "AUD" : "USD", + currentBalance: accData.balance, + availableBalance: accData.balance, + lastBalanceUpdate: new Date("2026-04-03"), + status: "ACTIVE", + }, + }); + bankAccounts.push(account); + } + console.log(`✓ Created ${bankAccounts.length} bank accounts`); + + // ======================================== + // BANK TRANSACTIONS (recent 30 days) + // ======================================== + console.log("📊 Creating bank transactions..."); + const bankTransactions = []; + const transactionData = [ + { account: bankAccounts[0], date: "2026-03-05", type: "CREDIT", amount: 185000, description: "Customer payment - ABC Corp", reconciled: true }, + { account: bankAccounts[0], date: "2026-03-10", type: "CREDIT", amount: 203500, description: "Customer payment - Premier Solutions", reconciled: true }, + { account: bankAccounts[0], date: "2026-03-12", type: "DEBIT", amount: 48000, description: "Salesforce annual renewal", reconciled: true }, + { account: bankAccounts[0], date: "2026-03-15", type: "DEBIT", amount: 22000, description: "AWS cloud hosting", reconciled: true }, + { account: bankAccounts[0], date: "2026-03-20", type: "DEBIT", amount: 37500, description: "Dell workstations partial", reconciled: true }, + { account: bankAccounts[0], date: "2026-03-25", type: "CREDIT", amount: 45000, description: "Customer payment - TechVenture", reconciled: true }, + { account: bankAccounts[0], date: "2026-04-01", type: "CREDIT", amount: 50000, description: "Customer payment - ABC Corp partial", reconciled: false }, + { account: bankAccounts[0], date: "2026-04-03", type: "DEBIT", amount: 24200, description: "AWS usage - March billing", reconciled: false }, + { account: bankAccounts[1], date: "2026-03-25", type: "DEBIT", amount: 225000, description: "March payroll - engineering", reconciled: true }, + { account: bankAccounts[1], date: "2026-03-25", type: "DEBIT", amount: 49500, description: "March payroll - S&M team", reconciled: true }, + { account: bankAccounts[1], date: "2026-03-25", type: "DEBIT", amount: 41800, description: "March payroll - G&A staff", reconciled: true }, + { account: bankAccounts[1], date: "2026-03-22", type: "CREDIT", amount: 225000, description: "Payroll account funding - Mar", reconciled: true }, + { account: bankAccounts[2], date: "2026-03-01", type: "DEBIT", amount: 96000, description: "Insurance premium - annual", reconciled: true }, + { account: bankAccounts[2], date: "2026-03-15", type: "CREDIT", amount: 92000, description: "Customer payment - Global Partners", reconciled: true }, + { account: bankAccounts[2], date: "2026-04-02", type: "DEBIT", amount: 105000, description: "Vendor payments batch", reconciled: false }, + { account: bankAccounts[3], date: "2026-03-31", type: "CREDIT", amount: 2100, description: "Interest earned Q1", reconciled: true }, + { account: bankAccounts[3], date: "2026-04-01", type: "DEBIT", amount: 150, description: "Monthly maintenance fee", reconciled: true }, + { account: bankAccounts[4], date: "2026-03-30", type: "DEBIT", amount: 100000, description: "Loan principal payment Q1", reconciled: true }, + { account: bankAccounts[4], date: "2026-03-30", type: "DEBIT", amount: 3500, description: "Interest payment Q1", reconciled: true }, + { account: bankAccounts[5], date: "2026-03-15", type: "CREDIT", amount: 142000, description: "UK customer payments Q1", reconciled: true }, + { account: bankAccounts[5], date: "2026-03-28", type: "DEBIT", amount: 45000, description: "UK operating expenses", reconciled: false }, + { account: bankAccounts[6], date: "2026-03-16", type: "CREDIT", amount: 108000, description: "Europe customer payments Q1", reconciled: true }, + { account: bankAccounts[6], date: "2026-03-30", type: "DEBIT", amount: 38000, description: "Europe operating expenses", reconciled: false }, + { account: bankAccounts[7], date: "2026-03-17", type: "CREDIT", amount: 78000, description: "Pacific customer payments Q1", reconciled: true }, + { account: bankAccounts[7], date: "2026-03-30", type: "DEBIT", amount: 28000, description: "Pacific operating expenses", reconciled: false }, + ]; + + for (const txData of transactionData) { + const txDate = new Date(txData.date); + const transaction = await prisma.bankTransaction.create({ + data: { + organizationId: organization.id, + bankAccountId: txData.account.id, + transactionDate: txDate, + postDate: txDate, + transactionType: txData.type as "DEBIT" | "CREDIT" | "REVERSAL" | "ADJUSTMENT", + amount: txData.amount, + description: txData.description, + reconciled: txData.reconciled, + reconciledAt: txData.reconciled ? txDate : null, + status: "PENDING", + }, + }); + bankTransactions.push(transaction); + } + console.log(`✓ Created ${bankTransactions.length} bank transactions`); + + // ======================================== + // CASH POSITION SNAPSHOTS + // ======================================== + console.log("💰 Creating cash position snapshots..."); + const cashSnapshots = [ + { date: "2025-12-31", total: 5250000, byEntity: { "Acme Software Inc": 4450000, "Acme Cloud Services Ltd": 380000, "Acme Europe GmbH": 240000, "Acme Pacific Pty Ltd": 180000 } }, + { date: "2026-01-31", total: 5680000, byEntity: { "Acme Software Inc": 4820000, "Acme Cloud Services Ltd": 395000, "Acme Europe GmbH": 268000, "Acme Pacific Pty Ltd": 197000 } }, + { date: "2026-02-28", total: 5920000, byEntity: { "Acme Software Inc": 5010000, "Acme Cloud Services Ltd": 415000, "Acme Europe GmbH": 285000, "Acme Pacific Pty Ltd": 210000 } }, + { date: "2026-03-31", total: 6137241.50, byEntity: { "Acme Software Inc": 5201741.50, "Acme Cloud Services Ltd": 439000, "Acme Europe GmbH": 310000, "Acme Pacific Pty Ltd": 186500 } }, + { date: "2026-04-03", total: 6037241.50, byEntity: { "Acme Software Inc": 5101741.50, "Acme Cloud Services Ltd": 439000, "Acme Europe GmbH": 310000, "Acme Pacific Pty Ltd": 186500 } }, + ]; + + for (const snap of cashSnapshots) { + await prisma.cashPosition.create({ + data: { + organizationId: organization.id, + snapshotDate: new Date(snap.date), + totalCash: snap.total, + totalAvailable: snap.total, + cashByEntity: snap.byEntity, + cashByCurrency: { USD: snap.byEntity["Acme Software Inc"], GBP: snap.byEntity["Acme Cloud Services Ltd"], EUR: snap.byEntity["Acme Europe GmbH"], AUD: snap.byEntity["Acme Pacific Pty Ltd"] }, + }, + }); + } + console.log(`✓ Created ${cashSnapshots.length} cash position snapshots`); + + // ======================================== + // BUDGET LINES (FY2026) + // ======================================== + console.log("📊 Creating budget lines..."); + const budgetData = [ + { accountCode: "4000", annual: 2640000, monthly: [200000, 210000, 215000, 220000, 225000, 225000, 220000, 215000, 220000, 230000, 230000, 230000] }, + { accountCode: "4100", annual: 1200000, monthly: [95000, 98000, 100000, 102000, 100000, 100000, 100000, 102000, 103000, 100000, 100000, 100000] }, + { accountCode: "4500", annual: 25200, monthly: [2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100, 2100] }, + { accountCode: "5000", annual: 726000, monthly: [60500, 60500, 60500, 60500, 60500, 60500, 60500, 60500, 60500, 60500, 60500, 60500] }, + { accountCode: "6100", annual: 594000, monthly: [49500, 49500, 49500, 49500, 49500, 49500, 49500, 49500, 49500, 49500, 49500, 49500] }, + { accountCode: "6200", annual: 2700000, monthly: [225000, 225000, 225000, 225000, 225000, 225000, 225000, 225000, 225000, 225000, 225000, 225000] }, + { accountCode: "6300", annual: 620400, monthly: [51700, 51700, 51700, 51700, 51700, 51700, 51700, 51700, 51700, 51700, 51700, 51700] }, + { accountCode: "6400", annual: 290400, monthly: [24200, 24200, 24200, 24200, 24200, 24200, 24200, 24200, 24200, 24200, 24200, 24200] }, + { accountCode: "7000", annual: 42000, monthly: [3500, 3500, 3500, 3500, 3500, 3500, 3500, 3500, 3500, 3500, 3500, 3500] }, + ]; + + for (const bd of budgetData) { + await prisma.budgetLine.create({ + data: { + organizationId: organization.id, + accountId: accounts[bd.accountCode].id, + fiscalYear: 2026, + monthlyAmounts: bd.monthly, + annualBudget: bd.annual, + notes: `FY2026 budget for ${accounts[bd.accountCode].accountName}`, + }, + }); + } + console.log(`✓ Created ${budgetData.length} budget lines`); + + // Also create FY2025 budgets (for YoY comparison) + const fy2025BudgetData = [ + { accountCode: "4000", annual: 2400000, monthly: [185000, 190000, 195000, 200000, 205000, 205000, 200000, 200000, 205000, 210000, 200000, 205000] }, + { accountCode: "4100", annual: 1104000, monthly: [92000, 92000, 92000, 92000, 92000, 92000, 92000, 92000, 92000, 92000, 92000, 92000] }, + { accountCode: "5000", annual: 660000, monthly: [55000, 55000, 55000, 55000, 55000, 55000, 55000, 55000, 55000, 55000, 55000, 55000] }, + { accountCode: "6200", annual: 2520000, monthly: [210000, 210000, 210000, 210000, 210000, 210000, 210000, 210000, 210000, 210000, 210000, 210000] }, + { accountCode: "6100", annual: 540000, monthly: [45000, 45000, 45000, 45000, 45000, 45000, 45000, 45000, 45000, 45000, 45000, 45000] }, + { accountCode: "6300", annual: 558000, monthly: [46500, 46500, 46500, 46500, 46500, 46500, 46500, 46500, 46500, 46500, 46500, 46500] }, + { accountCode: "6400", annual: 264000, monthly: [22000, 22000, 22000, 22000, 22000, 22000, 22000, 22000, 22000, 22000, 22000, 22000] }, + ]; + + for (const bd of fy2025BudgetData) { + await prisma.budgetLine.create({ + data: { + organizationId: organization.id, + accountId: accounts[bd.accountCode].id, + fiscalYear: 2025, + monthlyAmounts: bd.monthly, + annualBudget: bd.annual, + notes: `FY2025 budget for ${accounts[bd.accountCode].accountName}`, + }, + }); + } + console.log(`✓ Created ${fy2025BudgetData.length} FY2025 budget lines`); + + // ======================================== + // LEASES (ASC 842) + // ======================================== + console.log("🏢 Creating leases..."); + const leases = [ + { + description: "NYC Office Space - 5th Avenue", + type: "Operating", + startDate: new Date("2024-01-01"), + endDate: new Date("2028-12-31"), + monthlyPayment: 24000, + totalCommitment: 1440000, + discountRate: 4.5, + rouAsset: 1296000, + leaseLiability: 1310400, + currentPortion: 276480, + nonCurrentPortion: 1033920, + status: "Active", + }, + { + description: "London Office - Canary Wharf", + type: "Operating", + startDate: new Date("2024-06-01"), + endDate: new Date("2027-05-31"), + monthlyPayment: 15000, + totalCommitment: 540000, + discountRate: 5.0, + rouAsset: 486000, + leaseLiability: 495000, + currentPortion: 175500, + nonCurrentPortion: 319500, + status: "Active", + }, + { + description: "Server Co-location - Equinix NY5", + type: "Finance", + startDate: new Date("2025-03-01"), + endDate: new Date("2030-02-28"), + monthlyPayment: 35000, + totalCommitment: 2100000, + discountRate: 3.8, + rouAsset: 1890000, + leaseLiability: 1932000, + currentPortion: 396000, + nonCurrentPortion: 1536000, + status: "Active", + }, + { + description: "Company Vehicles Fleet (12 units)", + type: "Operating", + startDate: new Date("2025-01-01"), + endDate: new Date("2027-12-31"), + monthlyPayment: 6000, + totalCommitment: 216000, + discountRate: 4.0, + rouAsset: 194400, + leaseLiability: 198000, + currentPortion: 70200, + nonCurrentPortion: 127800, + status: "Active", + }, + { + description: "Berlin Office - Alexanderplatz", + type: "Operating", + startDate: new Date("2025-06-01"), + endDate: new Date("2028-05-31"), + monthlyPayment: 8500, + totalCommitment: 306000, + discountRate: 4.2, + rouAsset: 275400, + leaseLiability: 280800, + currentPortion: 99000, + nonCurrentPortion: 181800, + status: "Active", + }, + { + description: "Old SF Office (terminated early)", + type: "Operating", + startDate: new Date("2022-01-01"), + endDate: new Date("2025-06-30"), + monthlyPayment: 18000, + totalCommitment: 756000, + discountRate: 3.5, + rouAsset: 0, + leaseLiability: 0, + currentPortion: 0, + nonCurrentPortion: 0, + status: "Expired", + }, + ]; + + for (const l of leases) { + await prisma.lease.create({ + data: { + organizationId: organization.id, + description: l.description, + type: l.type, + startDate: l.startDate, + endDate: l.endDate, + monthlyPayment: l.monthlyPayment, + totalCommitment: l.totalCommitment, + discountRate: l.discountRate, + rouAsset: l.rouAsset, + leaseLiability: l.leaseLiability, + currentPortion: l.currentPortion, + nonCurrentPortion: l.nonCurrentPortion, + status: l.status, + }, + }); + } + console.log(`✓ Created ${leases.length} leases`); + + // ======================================== + // SHAREHOLDERS / CAP TABLE + // ======================================== + console.log("📋 Creating shareholders..."); + const shareholders = [ + { name: "Ryan Francis", type: "founder", sharesOwned: 4000000, shareClass: "Common", vestingCliffMonths: 12, vestingTotalMonths: 48, vestedPercent: 87.50, grantDate: new Date("2020-01-01"), exercisePrice: 0.01, status: "ACTIVE" }, + { name: "Sarah Chen", type: "founder", sharesOwned: 3000000, shareClass: "Common", vestingCliffMonths: 12, vestingTotalMonths: 48, vestedPercent: 87.50, grantDate: new Date("2020-01-01"), exercisePrice: 0.01, status: "ACTIVE" }, + { name: "Velocity Partners Fund III", type: "investor", sharesOwned: 2500000, shareClass: "Series A", vestingCliffMonths: 0, vestingTotalMonths: 0, vestedPercent: 100.00, grantDate: new Date("2022-06-15"), exercisePrice: 1.20, status: "ACTIVE" }, + { name: "Summit Capital Growth", type: "investor", sharesOwned: 3500000, shareClass: "Series B", vestingCliffMonths: 0, vestingTotalMonths: 0, vestedPercent: 100.00, grantDate: new Date("2025-01-15"), exercisePrice: 2.85, status: "ACTIVE" }, + { name: "Emily Rodriguez", type: "employee", sharesOwned: 500000, shareClass: "Options", vestingCliffMonths: 12, vestingTotalMonths: 48, vestedPercent: 62.50, grantDate: new Date("2021-06-01"), exercisePrice: 0.50, status: "ACTIVE" }, + { name: "James Park", type: "employee", sharesOwned: 400000, shareClass: "Options", vestingCliffMonths: 12, vestingTotalMonths: 48, vestedPercent: 50.00, grantDate: new Date("2022-01-15"), exercisePrice: 0.80, status: "ACTIVE" }, + { name: "Aisha Patel", type: "employee", sharesOwned: 350000, shareClass: "Options", vestingCliffMonths: 12, vestingTotalMonths: 48, vestedPercent: 37.50, grantDate: new Date("2023-01-01"), exercisePrice: 1.50, status: "ACTIVE" }, + { name: "David Kim", type: "advisor", sharesOwned: 150000, shareClass: "Options", vestingCliffMonths: 6, vestingTotalMonths: 24, vestedPercent: 100.00, grantDate: new Date("2022-01-01"), exercisePrice: 0.80, status: "ACTIVE" }, + { name: "Maria Santos", type: "employee", sharesOwned: 250000, shareClass: "Options", vestingCliffMonths: 12, vestingTotalMonths: 48, vestedPercent: 18.75, grantDate: new Date("2024-04-01"), exercisePrice: 2.00, status: "ACTIVE" }, + { name: "Alex Thompson (departed)", type: "employee", sharesOwned: 200000, shareClass: "Options", vestingCliffMonths: 12, vestingTotalMonths: 48, vestedPercent: 25.00, grantDate: new Date("2023-01-01"), exercisePrice: 1.50, status: "TERMINATED" }, + ]; + + for (const sh of shareholders) { + await prisma.shareholder.create({ + data: { + organizationId: organization.id, + name: sh.name, + type: sh.type, + sharesOwned: sh.sharesOwned, + shareClass: sh.shareClass, + vestingCliffMonths: sh.vestingCliffMonths, + vestingTotalMonths: sh.vestingTotalMonths, + vestedPercent: sh.vestedPercent, + grantDate: sh.grantDate, + exercisePrice: sh.exercisePrice, + status: sh.status, + }, + }); + } + console.log(`✓ Created ${shareholders.length} shareholders`); + + // ======================================== + // SUBSCRIPTIONS (customer recurring revenue) + // ======================================== + console.log("🔄 Creating subscriptions..."); + const subscriptions = [ + { customer: customers[0], plan: "Enterprise Platform", cycle: "ANNUAL", amount: 2220000, start: "2025-01-01", next: "2026-01-01", status: "ACTIVE" }, + { customer: customers[1], plan: "SaaS Professional", cycle: "MONTHLY", amount: 15000, start: "2025-03-01", next: "2026-05-01", status: "ACTIVE" }, + { customer: customers[2], plan: "Consulting Retainer", cycle: "QUARTERLY", amount: 92000, start: "2025-01-01", next: "2026-07-01", status: "ACTIVE" }, + { customer: customers[3], plan: "Enterprise License", cycle: "ANNUAL", amount: 2442000, start: "2026-01-01", next: "2027-01-01", status: "ACTIVE" }, + { customer: customers[4], plan: "Startup Plan", cycle: "ANNUAL", amount: 24000, start: "2025-06-01", next: "2026-06-01", status: "ACTIVE" }, + { customer: customers[5], plan: "Healthcare Suite", cycle: "ANNUAL", amount: 1872000, start: "2026-01-01", next: "2027-01-01", status: "ACTIVE" }, + { customer: customers[6], plan: "Retail Analytics", cycle: "MONTHLY", amount: 6500, start: "2025-09-01", next: "2026-05-01", status: "ACTIVE" }, + { customer: customers[7], plan: "Financial Compliance", cycle: "ANNUAL", amount: 2520000, start: "2026-02-01", next: "2027-02-01", status: "ACTIVE" }, + { customer: customers[1], plan: "SaaS Basic (old)", cycle: "MONTHLY", amount: 8000, start: "2024-01-01", end: "2025-02-28", status: "CANCELLED" }, + ]; + + for (const sub of subscriptions) { + await prisma.subscription.create({ + data: { + organizationId: organization.id, + customerId: sub.customer.id, + planName: sub.plan, + billingCycle: sub.cycle, + amount: sub.amount, + startDate: new Date(sub.start), + endDate: sub.end ? new Date(sub.end) : null, + nextBillingDate: sub.next ? new Date(sub.next) : null, + cancelledAt: sub.status === "CANCELLED" ? new Date(sub.end!) : null, + status: sub.status, + }, + }); + } + console.log(`✓ Created ${subscriptions.length} subscriptions`); + + // ======================================== + // FORECASTS + // ======================================== + console.log("🔮 Creating forecasts..."); + const forecasts = [ + { + name: "FY2026 Base Case Forecast", + description: "Conservative growth scenario based on current pipeline and retention rates", + scenarioType: "BASE", + startDate: new Date("2026-01-01"), + endDate: new Date("2026-12-31"), + status: "ACTIVE", + assumptions: { revenueGrowth: 0.10, expenseGrowth: 0.08, churnRate: 0.05, newCustomers: 12 }, + projections: { + months: months.map((m, i) => ({ + month: `${m} 2026`, + revenue: 304700 + (i * 3000), + expenses: 350400 + (i * 1500), + netIncome: -45700 + (i * 1500), + cashBalance: 6037241 + (i * 45000), + })), + }, + }, + { + name: "FY2026 Optimistic Scenario", + description: "Aggressive growth with accelerated enterprise sales and expansion revenue", + scenarioType: "OPTIMISTIC", + startDate: new Date("2026-01-01"), + endDate: new Date("2026-12-31"), + status: "ACTIVE", + assumptions: { revenueGrowth: 0.25, expenseGrowth: 0.15, churnRate: 0.03, newCustomers: 24 }, + projections: { + months: months.map((m, i) => ({ + month: `${m} 2026`, + revenue: 345000 + (i * 8000), + expenses: 365000 + (i * 3000), + netIncome: -20000 + (i * 5000), + cashBalance: 6037241 + (i * 85000), + })), + }, + }, + { + name: "FY2026 Pessimistic Scenario", + description: "Downturn scenario with reduced pipeline and higher churn", + scenarioType: "PESSIMISTIC", + startDate: new Date("2026-01-01"), + endDate: new Date("2026-12-31"), + status: "ACTIVE", + assumptions: { revenueGrowth: -0.05, expenseGrowth: 0.03, churnRate: 0.12, newCustomers: 4 }, + projections: { + months: months.map((m, i) => ({ + month: `${m} 2026`, + revenue: 270000 - (i * 2000), + expenses: 345000 + (i * 500), + netIncome: -75000 - (i * 2500), + cashBalance: 6037241 - (i * 35000), + })), + }, + }, + ]; + + for (const f of forecasts) { + await prisma.forecast.create({ + data: { + organizationId: organization.id, + name: f.name, + description: f.description, + scenarioType: f.scenarioType, + startDate: f.startDate, + endDate: f.endDate, + status: f.status, + assumptions: f.assumptions, + projections: f.projections, + createdBy: user.name, + }, + }); + } + console.log(`✓ Created ${forecasts.length} forecasts`); + + // ======================================== + // DOCUMENTS + // ======================================== + console.log("📁 Creating documents..."); + const documents = [ + { name: "FY2025 Annual Report.pdf", category: "report", mimeType: "application/pdf", fileSize: 2450000, storagePath: "/documents/reports/fy2025-annual.pdf", tags: ["annual", "FY2025", "financial"] }, + { name: "Series B Term Sheet.pdf", category: "legal", mimeType: "application/pdf", fileSize: 185000, storagePath: "/documents/legal/series-b-term-sheet.pdf", tags: ["legal", "fundraising", "Series B"] }, + { name: "AWS MSA.pdf", category: "contract", mimeType: "application/pdf", fileSize: 420000, storagePath: "/documents/contracts/aws-msa.pdf", tags: ["contract", "vendor", "AWS"] }, + { name: "Q1 2026 Board Deck.pptx", category: "report", mimeType: "application/vnd.openxmlformats-officedocument.presentationml.presentation", fileSize: 5200000, storagePath: "/documents/reports/q1-2026-board-deck.pptx", tags: ["board", "Q1", "2026"] }, + { name: "Office Lease Agreement - NYC.pdf", category: "contract", mimeType: "application/pdf", fileSize: 890000, storagePath: "/documents/contracts/nyc-office-lease.pdf", tags: ["lease", "real estate", "NYC"] }, + { name: "D&O Insurance Policy.pdf", category: "legal", mimeType: "application/pdf", fileSize: 340000, storagePath: "/documents/legal/do-insurance-2026.pdf", tags: ["insurance", "D&O", "2026"] }, + { name: "Employee Stock Option Plan.pdf", category: "legal", mimeType: "application/pdf", fileSize: 275000, storagePath: "/documents/legal/esop-plan.pdf", tags: ["ESOP", "equity", "options"] }, + { name: "SOC 2 Type II Report.pdf", category: "report", mimeType: "application/pdf", fileSize: 1800000, storagePath: "/documents/compliance/soc2-type2-2025.pdf", tags: ["compliance", "SOC2", "audit"] }, + { name: "Revenue Recognition Policy.docx", category: "report", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileSize: 125000, storagePath: "/documents/policies/rev-rec-policy.docx", tags: ["policy", "ASC 606", "revenue"] }, + { name: "ABC Corp Master Agreement.pdf", category: "contract", mimeType: "application/pdf", fileSize: 560000, storagePath: "/documents/contracts/abc-corp-msa.pdf", tags: ["contract", "customer", "ABC Corp"] }, + ]; + + for (const doc of documents) { + await prisma.document.create({ + data: { + organizationId: organization.id, + name: doc.name, + category: doc.category, + mimeType: doc.mimeType, + fileSize: doc.fileSize, + storagePath: doc.storagePath, + status: "ACTIVE", + tags: doc.tags, + uploadedBy: user.name, + }, + }); + } + console.log(`✓ Created ${documents.length} documents`); + + // ======================================== + // AUDIT LOG + // ======================================== + console.log("📜 Creating audit log entries..."); + const auditEntries = [ + { action: "LOGIN", module: "auth", entityType: "User", description: "User logged in", date: "2026-04-05T08:30:00Z" }, + { action: "CREATE", module: "general-ledger", entityType: "JournalEntry", description: "Created JE-2026-0001 - January software revenue", date: "2026-01-06T09:15:00Z" }, + { action: "POST", module: "general-ledger", entityType: "JournalEntry", description: "Posted JE-2026-0001", date: "2026-01-06T09:20:00Z" }, + { action: "APPROVE", module: "ap", entityType: "Invoice", description: "Approved INV-AP-2026-0003 - WeWork office lease", date: "2026-02-15T14:00:00Z" }, + { action: "CREATE", module: "ap", entityType: "Payment", description: "Created payment PAY-2026-0001 for AWS", date: "2026-02-10T10:30:00Z" }, + { action: "APPROVE", module: "ar", entityType: "Invoice", description: "Approved INV-AR-2026-0007 - Northern Health Systems", date: "2026-03-20T11:00:00Z" }, + { action: "EXPORT", module: "reports", entityType: "Report", description: "Exported Q1 2026 Trial Balance to CSV", date: "2026-04-02T16:45:00Z" }, + { action: "UPDATE", module: "treasury", entityType: "BankAccount", description: "Updated Chase Business Checking balance", date: "2026-04-03T09:00:00Z" }, + { action: "CREATE", module: "general-ledger", entityType: "JournalEntry", description: "Created April 2026 revenue accrual (draft)", date: "2026-04-03T10:00:00Z" }, + { action: "CREATE", module: "ar", entityType: "Invoice", description: "Created INV-AR-2026-0008 - Pacific Retail Group", date: "2026-04-01T13:30:00Z" }, + { action: "LOGIN", module: "auth", entityType: "User", description: "User logged in from new device", date: "2026-04-04T07:45:00Z" }, + { action: "UPDATE", module: "planning", entityType: "BudgetLine", description: "Updated FY2026 engineering budget", date: "2026-03-15T15:20:00Z" }, + ]; + + for (const entry of auditEntries) { + await prisma.auditLog.create({ + data: { + organizationId: organization.id, + userId: user.id, + userName: user.name, + action: entry.action, + module: entry.module, + entityType: entry.entityType, + description: entry.description, + createdAt: new Date(entry.date), + }, + }); + } + console.log(`✓ Created ${auditEntries.length} audit log entries`); + + // ======================================== + // SUMMARY + // ======================================== + console.log("\n✅ Database seed completed successfully!"); + console.log(` + Organization: ${organization.name} + Entities: ${entities.length} + Users: 1 (${user.email}) + Accounts: ${accountsData.length} + Fiscal Periods: 36 (FY2024-FY2026) + Journal Entries: ${jeCounter} (spanning Jan 2025 - Apr 2026) + Vendors: ${vendors.length} + Purchase Orders: ${purchaseOrders.length} + Customers: ${customers.length} + AP Invoices: ${apInvoices.length} + AR Invoices: ${arInvoices.length} + Payments: ${payments.length} + Bank Accounts: ${bankAccounts.length} + Bank Transactions: ${bankTransactions.length} + Cash Position Snapshots: ${cashSnapshots.length} + Budget Lines: ${budgetData.length + fy2025BudgetData.length} (FY2025 + FY2026) + Leases: ${leases.length} + Shareholders: ${shareholders.length} + Subscriptions: ${subscriptions.length} + Forecasts: ${forecasts.length} + Documents: ${documents.length} + Audit Log Entries: ${auditEntries.length} + `); +} + +main() + .then(async () => { + await prisma.$disconnect(); + }) + .catch(async (e) => { + console.error("❌ Seed error:", e); + await prisma.$disconnect(); + process.exit(1); + }); diff --git a/replace_colors.sh b/replace_colors.sh new file mode 100644 index 0000000..2c517e8 --- /dev/null +++ b/replace_colors.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +# Array of files to update +files=( + "src/app/(dashboard)/admin/users/page.tsx" + "src/app/(dashboard)/admin/integrations/page.tsx" + "src/app/(dashboard)/admin/settings/page.tsx" + "src/app/(dashboard)/admin/activity-log/page.tsx" + "src/app/(dashboard)/planning/budgets/page.tsx" + "src/app/(dashboard)/planning/forecasting/page.tsx" + "src/app/(dashboard)/planning/cash-forecast/page.tsx" + "src/app/(dashboard)/planning/fpa/page.tsx" + "src/app/(dashboard)/planning/projects/page.tsx" + "src/app/(dashboard)/compliance/tax/page.tsx" + "src/app/(dashboard)/compliance/tax-reporting/page.tsx" + "src/app/(dashboard)/compliance/reporting/page.tsx" + "src/app/(dashboard)/compliance/leases/page.tsx" + "src/app/(dashboard)/compliance/report-builder/page.tsx" + "src/app/(dashboard)/equity/cap-table/page.tsx" +) + +# Color mappings +declare -a replacements=( + 's/text-slate-900/text-[#F0F0F3]/g' + 's/text-slate-800/text-[#F0F0F3]/g' + 's/text-slate-700/text-[#8B8B9E]/g' + 's/text-slate-600/text-[#8B8B9E]/g' + 's/text-slate-500/text-[#5A5A6E]/g' + 's/text-slate-400/text-[#5A5A6E]/g' + 's/text-gray-900/text-[#F0F0F3]/g' + 's/text-gray-800/text-[#F0F0F3]/g' + 's/text-gray-700/text-[#8B8B9E]/g' + 's/text-gray-600/text-[#8B8B9E]/g' + 's/text-gray-500/text-[#5A5A6E]/g' + 's/text-gray-400/text-[#5A5A6E]/g' + 's/bg-white/bg-[#1A1A1F]/g' + 's/bg-slate-50/bg-[#111114]/g' + 's/bg-slate-100/bg-[#1A1A1F]/g' + 's/bg-slate-200/bg-[#222228]/g' + 's/bg-gray-50/bg-[#111114]/g' + 's/bg-gray-100/bg-[#1A1A1F]/g' + 's/border-slate-200/border-[#2A2A32]/g' + 's/border-slate-100/border-[#2A2A32]/g' + 's/border-slate-300/border-[#3A3A45]/g' + 's/border-gray-200/border-[#2A2A32]/g' + 's/border-gray-300/border-[#3A3A45]/g' + 's/divide-slate-200/divide-[#2A2A32]/g' + 's/divide-slate-100/divide-[#2A2A32]/g' + 's/divide-gray-200/divide-[#2A2A32]/g' + 's/hover:bg-slate-50/hover:bg-[#222228]/g' + 's/hover:bg-slate-100/hover:bg-[#222228]/g' + 's/hover:bg-slate-200/hover:bg-[#2A2A32]/g' + 's/hover:bg-gray-50/hover:bg-[#222228]/g' + 's/hover:bg-gray-100/hover:bg-[#222228]/g' + 's/placeholder-slate-400/placeholder-[#5A5A6E]/g' + 's/placeholder-gray-400/placeholder-[#5A5A6E]/g' +) + +for file in "${files[@]}"; do + if [ -f "$file" ]; then + echo "Processing $file..." + for replacement in "${replacements[@]}"; do + sed -i "$replacement" "$file" + done + else + echo "File not found: $file" + fi +done + +echo "Done!" diff --git a/scripts/dev-https.js b/scripts/dev-https.js new file mode 100644 index 0000000..2145c2f --- /dev/null +++ b/scripts/dev-https.js @@ -0,0 +1,63 @@ +/** + * Local HTTPS development server. + * + * Creates an HTTPS proxy in front of Next.js dev server so that + * the EVE SSO callback URL (https://localhost:3000/...) works locally. + * + * Usage: node scripts/dev-https.js + * (or: npm run dev:https) + * + * Prerequisites: + * 1. Run ./scripts/generate-cert.sh to create certs/ + * 2. Trust the self-signed cert in your OS/browser + */ + +const { createServer } = require("https"); +const { parse } = require("url"); +const next = require("next"); +const fs = require("fs"); +const path = require("path"); + +const dev = process.env.NODE_ENV !== "production"; +const hostname = "localhost"; +const port = parseInt(process.env.PORT || "3000", 10); + +const certDir = path.join(__dirname, "..", "certs"); +const keyPath = path.join(certDir, "localhost-key.pem"); +const certPath = path.join(certDir, "localhost.pem"); + +if (!fs.existsSync(keyPath) || !fs.existsSync(certPath)) { + console.error( + "Self-signed certificates not found.\n" + + "Run: ./scripts/generate-cert.sh\n" + + "Then try again." + ); + process.exit(1); +} + +const httpsOptions = { + key: fs.readFileSync(keyPath), + cert: fs.readFileSync(certPath), +}; + +const app = next({ dev, hostname, port }); +const handle = app.getRequestHandler(); + +app.prepare().then(() => { + createServer(httpsOptions, async (req, res) => { + try { + const parsedUrl = parse(req.url, true); + await handle(req, res, parsedUrl); + } catch (err) { + console.error("Error handling request:", err); + res.statusCode = 500; + res.end("Internal Server Error"); + } + }).listen(port, () => { + console.log(`\n ▶ HTTPS server running at https://${hostname}:${port}\n`); + console.log(` EVE SSO Login: https://${hostname}:${port}/api/auth/eve-sso`); + console.log(` EVE SSO Callback: https://${hostname}:${port}/api/auth/callback/eve-sso`); + console.log(` Sync trigger: POST https://${hostname}:${port}/api/eve/sync`); + console.log(` Sync status: GET https://${hostname}:${port}/api/eve/sync\n`); + }); +}); diff --git a/scripts/generate-cert.sh b/scripts/generate-cert.sh new file mode 100644 index 0000000..ed8dee1 --- /dev/null +++ b/scripts/generate-cert.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Generate a self-signed certificate for local HTTPS development. +# EVE SSO requires HTTPS for the callback URL. +# +# Usage: ./scripts/generate-cert.sh +# +# This creates: +# certs/localhost-key.pem — Private key +# certs/localhost.pem — Self-signed certificate +# +# The cert is valid for 365 days and covers localhost + 127.0.0.1. + +set -euo pipefail + +CERT_DIR="certs" +mkdir -p "$CERT_DIR" + +echo "Generating self-signed certificate for localhost..." + +openssl req -x509 \ + -newkey rsa:2048 \ + -keyout "$CERT_DIR/localhost-key.pem" \ + -out "$CERT_DIR/localhost.pem" \ + -days 365 \ + -nodes \ + -subj "/CN=localhost" \ + -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" + +echo "" +echo "Certificate generated:" +echo " Key: $CERT_DIR/localhost-key.pem" +echo " Cert: $CERT_DIR/localhost.pem" +echo "" +echo "To trust this certificate on macOS:" +echo " sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain $CERT_DIR/localhost.pem" +echo "" +echo "To trust on Windows (PowerShell as Admin):" +echo ' Import-Certificate -FilePath "certs\localhost.pem" -CertStoreLocation Cert:\LocalMachine\Root' +echo "" +echo "Then run: npm run dev:https" diff --git a/scripts/migrate-new-modules.js b/scripts/migrate-new-modules.js new file mode 100644 index 0000000..0cd43d4 --- /dev/null +++ b/scripts/migrate-new-modules.js @@ -0,0 +1,58 @@ +#!/usr/bin/env node +/** + * Migration runner for new module tables. + * Run from project root: node scripts/migrate-new-modules.js + * + * Alternative: npx prisma db push (which reads from schema.prisma) + */ + +const { PrismaClient } = require('@prisma/client'); +const fs = require('fs'); +const path = require('path'); + +async function main() { + const prisma = new PrismaClient(); + + try { + console.log('Connecting to database...'); + await prisma.$connect(); + console.log('Connected.'); + + const sqlPath = path.join(__dirname, '..', 'prisma', 'migrations', 'add_new_modules', 'migration.sql'); + const sql = fs.readFileSync(sqlPath, 'utf-8'); + + // Split by semicolons and execute each statement + const statements = sql + .split(';') + .map(s => s.trim()) + .filter(s => s.length > 0 && !s.startsWith('--')); + + console.log(`Executing ${statements.length} SQL statements...`); + + for (let i = 0; i < statements.length; i++) { + const stmt = statements[i]; + try { + await prisma.$executeRawUnsafe(stmt); + console.log(` [${i + 1}/${statements.length}] OK`); + } catch (err) { + // Ignore "already exists" errors + if (err.message.includes('already exists')) { + console.log(` [${i + 1}/${statements.length}] Already exists (skipped)`); + } else { + console.error(` [${i + 1}/${statements.length}] ERROR: ${err.message}`); + } + } + } + + console.log('\nMigration complete!'); + console.log('Next step: run "npx prisma generate" to update the Prisma client types.'); + + } catch (err) { + console.error('Migration failed:', err.message); + process.exit(1); + } finally { + await prisma.$disconnect(); + } +} + +main(); diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx new file mode 100644 index 0000000..b408537 --- /dev/null +++ b/src/app/(auth)/login/page.tsx @@ -0,0 +1,174 @@ +'use client'; + +import { useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { Loader2 } from 'lucide-react'; + +export default function LoginPage() { + const router = useRouter(); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [error, setError] = useState(''); + const [successMsg, setSuccessMsg] = useState(''); + const [isLoading, setIsLoading] = useState(false); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(''); + setIsLoading(true); + + try { + const response = await fetch('/api/auth/login', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password }), + }); + + const data = await response.json(); + + if (!response.ok) { + setError(data.error || 'Invalid email or password'); + setIsLoading(false); + return; + } + + // Cookie is set by the API, redirect to dashboard + const params = new URLSearchParams(window.location.search); + const redirect = params.get('redirect') || '/dashboard'; + router.push(redirect); + } catch (err) { + setError('An error occurred. Please try again.'); + setIsLoading(false); + } + }; + + return ( +
+ {/* Subtle gradient overlay */} +
+ +
+ {/* Login Card */} +
+ {/* Logo */} +
+
+ F +
+
+ + {/* Title */} +

+ Francis +

+

+ AI-Native Universal ERP +

+ + {/* Error Message */} + {error && ( +
+

{error}

+
+ )} + + {/* Success Message */} + {successMsg && ( +
+

{successMsg}

+
+ )} + + {/* Form */} +
+ {/* Email Input */} +
+ + setEmail(e.target.value)} + placeholder="Enter your email" + className="w-full px-4 py-2.5 bg-[#0B0B0D] border border-[#2A2A32] rounded-lg text-[#F0F0F3] placeholder:text-[#5A5A6E] focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500/30 transition" + disabled={isLoading} + required + /> +
+ + {/* Password Input */} +
+ + setPassword(e.target.value)} + placeholder="Enter your password" + className="w-full px-4 py-2.5 bg-[#0B0B0D] border border-[#2A2A32] rounded-lg text-[#F0F0F3] placeholder:text-[#5A5A6E] focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500/30 transition" + disabled={isLoading} + required + /> +
+ + {/* Forgot Password Link */} +
+ +
+ + {/* Sign In Button */} + +
+ + {/* Register Link */} +
+

+ Don't have an account?{' '} + + Create one + +

+
+ + {/* Demo Credentials */} +
+

+ Demo credentials:
+ ryan@acme.com / demo123 +

+
+
+
+
+ ); +} diff --git a/src/app/(auth)/register/page.tsx b/src/app/(auth)/register/page.tsx new file mode 100644 index 0000000..e8830a2 --- /dev/null +++ b/src/app/(auth)/register/page.tsx @@ -0,0 +1,255 @@ +'use client'; + +import React, { useState } from 'react'; +import Link from 'next/link'; +import { useRouter } from 'next/navigation'; +import { Button } from '@/components/ui/Button'; +import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/Card'; +import { AlertCircle, CheckCircle, Loader2 } from 'lucide-react'; + +export default function RegisterPage() { + const router = useRouter(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [success, setSuccess] = useState(false); + + const [formData, setFormData] = useState({ + organizationName: '', + name: '', + email: '', + password: '', + confirmPassword: '', + }); + + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setFormData((prev) => ({ + ...prev, + [name]: value, + })); + setError(null); + }; + + const validateForm = (): boolean => { + if (!formData.organizationName.trim()) { + setError('Organization name is required'); + return false; + } + if (!formData.name.trim()) { + setError('Full name is required'); + return false; + } + if (!formData.email.trim()) { + setError('Email is required'); + return false; + } + if (!formData.password) { + setError('Password is required'); + return false; + } + if (formData.password.length < 8) { + setError('Password must be at least 8 characters'); + return false; + } + if (formData.password !== formData.confirmPassword) { + setError('Passwords do not match'); + return false; + } + return true; + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); + + if (!validateForm()) { + return; + } + + setLoading(true); + + try { + const response = await fetch('/api/auth/register', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + organizationName: formData.organizationName, + name: formData.name, + email: formData.email, + password: formData.password, + }), + }); + + if (!response.ok) { + const data = await response.json(); + setError(data.error || 'Registration failed'); + return; + } + + setSuccess(true); + + // Redirect to dashboard after a short delay + setTimeout(() => { + router.push('/dashboard'); + }, 1500); + } catch (err) { + setError(err instanceof Error ? err.message : 'An error occurred'); + } finally { + setLoading(false); + } + }; + + if (success) { + return ( +
+ + + +

+ Welcome! +

+

+ Your account has been created successfully. +

+

+ Redirecting to dashboard... +

+
+
+
+ ); + } + + return ( +
+ + + + Create Your Account + +

+ Set up your organization and get started +

+
+ +
+ {error && ( +
+ +

{error}

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

+ Minimum 8 characters +

+
+ +
+ + +
+ + +
+ +
+

+ Already have an account?{' '} + + Login here + +

+
+
+
+
+ ); +} diff --git a/src/app/(dashboard)/admin/activity-log/page.tsx b/src/app/(dashboard)/admin/activity-log/page.tsx new file mode 100644 index 0000000..00482b2 --- /dev/null +++ b/src/app/(dashboard)/admin/activity-log/page.tsx @@ -0,0 +1,504 @@ +'use client'; + +import React, { useState, useEffect, useMemo } from 'react'; +import { formatTimeAgo } from '@/lib/utils'; +import { + Activity, + Search, + ChevronRight, + FileText, + Plus, + Pencil, + Trash2, + CheckCircle, + XCircle, + Send, + Ban, + LogIn, + Download, + Loader2, + AlertCircle, + Shield, + Lock, + ArrowRight, + Globe, + RefreshCw, + AlertTriangle, + Eye, + Calendar, + Copy, + Share2, + Filter, + User, + Zap, +} from 'lucide-react'; + +interface AuditChange { + field: string; + oldValue: string; + newValue: string; +} + +interface AuditEntry { + id: string; + timestamp: string; + user: string; + action: string; + module: string; + entityType: string; + entityId: string; + entityRef: string; + description: string; + changes: AuditChange[] | null; + ipAddress: string; + severity: 'info' | 'warning' | 'critical'; +} + +interface AuditSummary { + total: number; + critical: number; + warnings: number; + uniqueUsers: number; + todayCount: number; +} + +const ACTION_ICONS: Record = { + CREATE: , + UPDATE: , + DELETE: , + APPROVE: , + REJECT: , + POST: , + VOID: , + STATUS_CHANGE: , + LOGIN: , + EXPORT: , + EXECUTE: , + RECONCILE: , + REVERSE: , + PERMISSION_CHANGE: , + PERIOD_LOCK: , +}; + +const ACTION_COLORS: Record = { + CREATE: 'bg-emerald-100 text-emerald-700', + UPDATE: 'bg-blue-100 text-blue-700', + DELETE: 'bg-red-100 text-red-700', + APPROVE: 'bg-emerald-100 text-emerald-700', + REJECT: 'bg-red-100 text-red-700', + POST: 'bg-blue-100 text-blue-700', + VOID: 'bg-red-100 text-red-700', + STATUS_CHANGE: 'bg-purple-100 text-purple-700', + LOGIN: 'bg-indigo-100 text-indigo-700', + EXPORT: 'bg-[#1A1A1F] text-[#8B8B9E]', + EXECUTE: 'bg-cyan-100 text-cyan-700', + RECONCILE: 'bg-teal-100 text-teal-700', + REVERSE: 'bg-amber-100 text-amber-700', + PERMISSION_CHANGE: 'bg-red-100 text-red-700', + PERIOD_LOCK: 'bg-amber-100 text-amber-700', +}; + +const SEVERITY_STYLES = { + info: '', + warning: 'border-l-4 border-l-amber-400', + critical: 'border-l-4 border-l-red-500 bg-red-50/30', +}; + +export default function ActivityLogPage() { + const [entries, setEntries] = useState([]); + const [modules, setModules] = useState([]); + const [actions, setActions] = useState([]); + const [summary, setSummary] = useState(null); + const [loading, setLoading] = useState(true); + const [searchQuery, setSearchQuery] = useState(''); + const [moduleFilter, setModuleFilter] = useState('all'); + const [actionFilter, setActionFilter] = useState('all'); + const [severityFilter, setSeverityFilter] = useState('all'); + const [_userFilter, _setUserFilter] = useState('all'); + const [dateRange, setDateRange] = useState({ start: '', end: '' }); + const [expandedId, setExpandedId] = useState(null); + const [bookmarkedEntries, setBookmarkedEntries] = useState>(new Set()); + const [_exportFormat, _setExportFormat] = useState<'csv' | 'json' | null>(null); + + const fetchData = () => { + setLoading(true); + const params = new URLSearchParams(); + if (moduleFilter !== 'all') params.set('module', moduleFilter); + if (actionFilter !== 'all') params.set('action', actionFilter); + + fetch(`/api/audit-trail?${params}`) + .then((r) => r.json()) + .then((d) => { + setEntries(d.entries || []); + setModules(d.modules || []); + setActions(d.actions || []); + setSummary(d.summary || null); + }) + .catch(console.error) + .finally(() => setLoading(false)); + }; + + useEffect(() => { fetchData(); }, [moduleFilter, actionFilter]); + + const filtered = useMemo(() => { + let result = entries; + if (searchQuery.trim()) { + const q = searchQuery.toLowerCase(); + result = result.filter( + (e) => + e.description.toLowerCase().includes(q) || + e.user.toLowerCase().includes(q) || + e.entityRef.toLowerCase().includes(q) || + e.module.toLowerCase().includes(q) + ); + } + if (severityFilter !== 'all') { + result = result.filter((e) => e.severity === severityFilter); + } + return result; + }, [entries, searchQuery, severityFilter]); + + + const formatFullTime = (dateStr: string) => + new Date(dateStr).toLocaleString('en-US', { + month: 'short', day: 'numeric', year: 'numeric', + hour: '2-digit', minute: '2-digit', second: '2-digit', + }); + + const handleBulkExport = (format: 'csv' | 'json') => { + const dataToExport = filtered.map(entry => ({ + timestamp: entry.timestamp, + user: entry.user, + action: entry.action, + module: entry.module, + description: entry.description, + severity: entry.severity, + })); + + const content = format === 'csv' + ? ['timestamp,user,action,module,description,severity', ...dataToExport.map(d => `"${d.timestamp}","${d.user}","${d.action}","${d.module}","${d.description}","${d.severity}"`)].join('\n') + : JSON.stringify(dataToExport, null, 2); + + const blob = new Blob([content], { type: format === 'csv' ? 'text/csv' : 'application/json' }); + const url = window.URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `audit-log-${new Date().toISOString().split('T')[0]}.${format}`; + document.body.appendChild(a); + a.click(); + window.URL.revokeObjectURL(url); + document.body.removeChild(a); + }; + + const toggleBookmark = (entryId: string) => { + const newBookmarks = new Set(bookmarkedEntries); + if (newBookmarks.has(entryId)) { + newBookmarks.delete(entryId); + } else { + newBookmarks.add(entryId); + } + setBookmarkedEntries(newBookmarks); + }; + + return ( +
+ {/* Header */} +
+
+

+ + Audit Trail +

+

+ Complete audit trail with field-level change tracking and advanced analytics +

+
+
+ +
+ +
+ + +
+
+
+
+ + {/* Summary Dashboard */} + {summary && ( +
+
+
+

Total Events

+

{summary.total}

+
+
+

Today

+

{summary.todayCount}

+
+
+
+ +

Active Users

+
+

{summary.uniqueUsers}

+
+
+
+ +

Warnings

+
+

{summary.warnings}

+
+
+
+ +

Critical

+
+

{summary.critical}

+
+
+
+

Data retention: 90 days • Last export: {new Date().toLocaleDateString()}

+
+
+ )} + + {/* Advanced Filters */} +
+
+

+ + Advanced Filters +

+ +
+
+
+ + setSearchQuery(e.target.value)} + className="bg-transparent text-sm outline-none w-full placeholder-[#5A5A6E]" + /> +
+ + + + + + + +
+ setDateRange({ ...dateRange, start: e.target.value })} className="flex-1 text-xs border border-[#2A2A32] rounded-lg px-3 py-2 outline-none" /> + setDateRange({ ...dateRange, end: e.target.value })} className="flex-1 text-xs border border-[#2A2A32] rounded-lg px-3 py-2 outline-none" /> +
+
+
+ + {filtered.length} event{filtered.length !== 1 ? 's' : ''} found + +
+
+ + {/* Audit Entries */} +
+ {loading && entries.length === 0 ? ( +
+ +
+ ) : filtered.length === 0 ? ( +
+ +

No events match your filters

+
+ ) : ( +
+ {filtered.map((entry) => { + const isExpanded = expandedId === entry.id; + return ( +
+ + {entry.changes ? ( + + ) : ( + + )} +
+ + + {/* Expanded Detail */} + {isExpanded && ( +
+
+ {/* Changes diff */} + {entry.changes && entry.changes.length > 0 && ( +
+

+ Field Changes +

+
+ {entry.changes.map((change, i) => ( +
0 ? 'border-t border-[#2A2A32]' : '' + }`} + > + + {change.field} + +
+ + {change.oldValue} + + + + {change.newValue} + +
+
+ ))} +
+
+ )} + + {/* Metadata */} +
+ + + {formatFullTime(entry.timestamp)} + + + + {entry.ipAddress} + + {entry.entityType}: {entry.entityId.slice(0, 8)}... + + +
+
+
+ )} +
+ ); + })} +
+ )} +
+ + {/* Bookmarked Entries Section */} + {bookmarkedEntries.size > 0 && ( +
+

+ + Bookmarked Entries ({bookmarkedEntries.size}) +

+

You can access your bookmarked entries here for quick reference and sharing.

+
+ )} +
+ ); +} diff --git a/src/app/(dashboard)/admin/approvals/page.tsx b/src/app/(dashboard)/admin/approvals/page.tsx new file mode 100644 index 0000000..8224a31 --- /dev/null +++ b/src/app/(dashboard)/admin/approvals/page.tsx @@ -0,0 +1,649 @@ +'use client'; + +import React, { useState, useEffect, useMemo } from 'react'; +import { formatCurrency, formatCompactCurrency } from '@/lib/utils'; +import { ToastNotification } from '@/components/ui/ToastNotification'; +import { useToast } from '@/hooks/useListPage'; +import { apiFetch, apiJson, ApiError, usePermissions } from '@/lib/api-client'; +import { + ShieldCheck, + Loader2, + Clock, + CheckCircle2, + FileText, + BookOpen, + CreditCard, + Search, + AlertTriangle, + ChevronDown, + Send, + Zap, + MoreVertical, +} from 'lucide-react'; + +interface ApprovalItem { + id: string; + type: 'invoice' | 'journal_entry' | 'payment'; + module: string; + reference: string; + description: string; + amount: number; + status: string; + party: string | null; + date: string; + dueDate: string | null; + href: string; +} + +interface RecentApproval { + id: string; + reference: string; + amount: number; + approvedAt: string; + approvedBy: string | null; + party: string | null; +} + +interface Summary { + totalPending: number; + pendingInvoices: number; + pendingJournalEntries: number; + pendingPayments: number; + totalPendingAmount: number; +} + +export default function ApprovalsPage() { + const [pending, setPending] = useState([]); + const [recentlyApproved, setRecentlyApproved] = useState([]); + const [summary, setSummary] = useState(null); + const [loading, setLoading] = useState(true); + const [search, setSearch] = useState(''); + const [typeFilter, setTypeFilter] = useState<'all' | 'invoice' | 'journal_entry' | 'payment'>('all'); + const [activeTab, setActiveTab] = useState<'pending' | 'recent'>('pending'); + const [approvingId, setApprovingId] = useState(null); + const [rejectingId, setRejectingId] = useState(null); + const [selectedForBulk, setSelectedForBulk] = useState>(new Set()); + const [expandedDetail, setExpandedDetail] = useState(null); + const [delegateModal, setDelegateModal] = useState<{ show: boolean; itemId?: string }>({ show: false }); + const [autoApprovalRules, _setAutoApprovalRules] = useState>([ + { type: 'invoice', threshold: 500 }, + { type: 'payment', threshold: 1000 }, + ]); + const [showAutoRuleModal, setShowAutoRuleModal] = useState(false); + const { toast, showToast, clearToast } = useToast(); + const { can, user: currentUser } = usePermissions(); + // The server-side guard enforces per-type APPROVE permission. We mirror + // that here so buttons don't render when they'd just bounce off a 403. + const canApproveType = (type: ApprovalItem['type']): boolean => { + if (type === 'invoice') return can('INVOICES', 'APPROVE'); + if (type === 'payment') return can('PAYMENTS', 'APPROVE'); + if (type === 'journal_entry') return can('JOURNAL_ENTRIES', 'APPROVE'); + return false; + }; + + useEffect(() => { + fetchApprovals(); + }, []); + + const fetchApprovals = async () => { + setLoading(true); + try { + const data = await apiJson<{ + pending?: ApprovalItem[]; + recentlyApproved?: RecentApproval[]; + summary?: Summary; + }>('/api/approvals', { silent: true }); + setPending(data.pending || []); + setRecentlyApproved(data.recentlyApproved || []); + setSummary(data.summary || null); + } catch (err) { + console.error('Failed to fetch approvals:', err); + } finally { + setLoading(false); + } + }; + + const formatTime = (dateString: string): string => { + const date = new Date(dateString); + return date.toLocaleDateString() + ' ' + date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + }; + + const handleApprove = async (item: ApprovalItem) => { + setApprovingId(item.id); + try { + // silent: true — we use the in-page toast helper for consistent UX. + await apiFetch('/api/approvals', { + method: 'POST', + body: JSON.stringify({ + id: item.id, + type: item.type, + action: 'approve', + }), + silent: true, + }); + + setPending(pending.filter((p) => p.id !== item.id)); + const newApproval: RecentApproval = { + id: item.id, + reference: item.reference, + amount: item.amount, + approvedAt: new Date().toISOString(), + approvedBy: currentUser?.name || 'You', + party: item.party, + }; + setRecentlyApproved([newApproval, ...recentlyApproved]); + setSummary( + summary ? { + ...summary, + totalPending: Math.max(0, summary.totalPending - 1), + pendingInvoices: item.type === 'invoice' ? Math.max(0, summary.pendingInvoices - 1) : summary.pendingInvoices, + pendingJournalEntries: item.type === 'journal_entry' ? Math.max(0, summary.pendingJournalEntries - 1) : summary.pendingJournalEntries, + pendingPayments: item.type === 'payment' ? Math.max(0, summary.pendingPayments - 1) : summary.pendingPayments, + totalPendingAmount: summary.totalPendingAmount - item.amount, + } : null + ); + showToast(`${item.reference} approved`, 'success'); + } catch (error) { + const msg = error instanceof ApiError ? error.message : 'An error occurred while approving the item'; + showToast(msg, 'error'); + console.error(error); + } finally { + setApprovingId(null); + } + }; + + const handleReject = async (item: ApprovalItem) => { + setRejectingId(item.id); + try { + await apiFetch('/api/approvals', { + method: 'POST', + body: JSON.stringify({ + id: item.id, + type: item.type, + action: 'reject', + }), + silent: true, + }); + + setPending(pending.filter((p) => p.id !== item.id)); + setSummary( + summary ? { + ...summary, + totalPending: Math.max(0, summary.totalPending - 1), + pendingInvoices: item.type === 'invoice' ? Math.max(0, summary.pendingInvoices - 1) : summary.pendingInvoices, + pendingJournalEntries: item.type === 'journal_entry' ? Math.max(0, summary.pendingJournalEntries - 1) : summary.pendingJournalEntries, + pendingPayments: item.type === 'payment' ? Math.max(0, summary.pendingPayments - 1) : summary.pendingPayments, + totalPendingAmount: summary.totalPendingAmount - item.amount, + } : null + ); + showToast(`${item.reference} rejected`, 'success'); + } catch (error) { + const msg = error instanceof ApiError ? error.message : 'An error occurred while rejecting the item'; + showToast(msg, 'error'); + console.error(error); + } finally { + setRejectingId(null); + } + }; + + + const typeIcons: Record = { + invoice: , + journal_entry: , + payment: , + }; + + const filtered = useMemo(() => { + return pending.filter((item) => { + if (typeFilter !== 'all' && item.type !== typeFilter) return false; + if (search.trim()) { + const q = search.toLowerCase(); + return ( + item.reference.toLowerCase().includes(q) || + item.description.toLowerCase().includes(q) || + item.party?.toLowerCase().includes(q) || + item.module.toLowerCase().includes(q) + ); + } + return true; + }); + }, [pending, typeFilter, search]); + + if (loading) { + return ( +
+ +
+ ); + } + + return ( +
+ + {/* Header */} +
+

+ + Approval Center +

+

+ Review and approve pending items across all modules +

+
+ + {/* Summary Cards */} + {summary && ( +
+
+
+ +

Total Pending

+
+

{summary.totalPending}

+
+
+
+ +

Invoices

+
+

{summary.pendingInvoices}

+
+
+
+ +

Journal Entries

+
+

{summary.pendingJournalEntries}

+
+
+
+ +

Payments

+
+

{summary.pendingPayments}

+
+
+

Pending Value

+

{formatCompactCurrency(summary.totalPendingAmount)}

+
+
+ )} + + {/* Tabs */} +
+
+
+ + +
+ + {activeTab === 'pending' && ( +
+
+ + setSearch(e.target.value)} + className="bg-transparent text-sm outline-none w-36" + /> +
+ +
+ )} +
+ + {/* Pending Items */} + {activeTab === 'pending' && ( +
+ {/* Bulk Actions */} + {selectedForBulk.size > 0 && ( +
+

{selectedForBulk.size} items selected

+
+ + + +
+
+ )} + + {filtered.length === 0 ? ( +
+ +

All caught up!

+

No items pending approval

+
+ ) : ( +
+ {filtered.map((item) => { + const isOverdue = item.dueDate && new Date(item.dueDate) < new Date(); + const isProcessing = approvingId === item.id || rejectingId === item.id; + const isExpanded = expandedDetail === item.id; + const timeSinceSubmit = Math.floor((new Date().getTime() - new Date(item.date).getTime()) / 1000 / 60); + const slaBreach = timeSinceSubmit > 120; // 2 hours SLA + return ( +
+ + + {/* Expanded Detail */} + {isExpanded && ( +
+ {/* Document Preview */} +
+

Document Details

+
+
Reference:{item.reference}
+
Amount:{formatCurrency(item.amount)}
+
Party:{item.party || 'N/A'}
+
Date:{new Date(item.date).toLocaleDateString()}
+
+
+ + {/* Comments */} +
+ +