diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..17d94cd --- /dev/null +++ b/README.MD @@ -0,0 +1,697 @@ +# Nodebase + +A visual workflow automation platform — similar to n8n — built with **Next.js 15** on the frontend and a custom **Node.js + Express** API server on the backend. Design, save, and execute multi-step workflows that chain together AI models, HTTP requests, messaging platforms, and external trigger sources like Google Forms and Stripe, all with real-time execution status visualised directly in the editor. + +--- + +## Table of Contents + +1. [Architecture Overview](#architecture-overview) +2. [Tech Stack](#tech-stack) +3. [Repository Structure](#repository-structure) +4. [Backend — Setup & Configuration](#backend--setup--configuration) + - [Environment Variables](#backend-environment-variables) + - [Dependencies](#backend-dependencies) + - [Database Migrations](#database-migrations) + - [Running the Backend](#running-the-backend) +5. [Frontend — Setup & Configuration](#frontend--setup--configuration) + - [Environment Variables](#frontend-environment-variables) + - [Dependencies](#frontend-dependencies) + - [Running the Frontend](#running-the-frontend) +6. [Inngest Dev Server](#inngest-dev-server) +7. [Webhooks (Local Development)](#webhooks-local-development) +8. [API Reference](#api-reference) +9. [Workflow Engine](#workflow-engine) +10. [Node Types & Executors](#node-types--executors) +11. [Real-Time Execution Status (SSE)](#real-time-execution-status-sse) +12. [Authentication](#authentication) +13. [Credential Encryption](#credential-encryption) +14. [Key Architectural Decisions](#key-architectural-decisions) +15. [What Was Removed](#what-was-removed) + +--- + +## Architecture Overview + +``` +┌──────────────────────────────────────────────┐ +│ Next.js Frontend (port 3000) │ +│ │ +│ React 19 · Jotai · ky · @xyflow/react │ +│ shadcn/ui · react-hook-form · zod │ +│ │ +│ API Layer: src/api/{client,auth,workflows, │ +│ credentials}.ts │ +│ │ +│ SSE streams ──────────────────────────────► │ +└──────────────────┬───────────────────────────┘ + │ HTTP + SSE (cookie auth) + ▼ +┌──────────────────────────────────────────────┐ +│ Express Backend (port 4000) │ +│ │ +│ 7 REST modules: auth, users, workflows, │ +│ nodes, connections, credentials, executions │ +│ + webhooks (no auth) │ +│ │ +│ Middleware: JWT cookies, Helmet, CORS, │ +│ rate-limit, Zod validation, request logger │ +└──────────────┬───────────────────────────────┘ + │ + ┌───────┴────────┐ + ▼ ▼ +┌─────────────┐ ┌─────────────────────────────┐ +│ PostgreSQL │ │ Inngest │ +│ (NeonDB) │ │ │ +│ │ │ Durable background jobs │ +│ 12 SQL │ │ execute-workflow function │ +│ migrations │ │ 9 node executors │ +│ RLS + AES │ │ SSE events pushed back │ +│ encryption │ │ to Express → browser │ +└─────────────┘ └─────────────────────────────┘ +``` + +--- + +## Tech Stack + +### Frontend + +| Layer | Technology | +| ------------------ | --------------------------------------------- | +| Framework | Next.js 15.5.4 (App Router, Turbopack) | +| UI Library | React 19 | +| State Management | Jotai 2 | +| HTTP Client | ky 1 | +| Flow Editor | @xyflow/react 12 | +| Forms | react-hook-form 7 + zod 4 | +| UI Components | shadcn/ui (Radix primitives + Tailwind CSS 4) | +| Icons | lucide-react | +| Notifications | sonner | +| Linting/Formatting | Biome 2 | + +### Backend + +| Layer | Technology | +| ---------------- | ----------------------------------------------------------------------------- | +| Runtime | Node.js (ESM, `"type": "module"`) | +| Framework | Express 5 | +| Database | PostgreSQL via `pg` Pool (NeonDB, always-on SSL) | +| Auth | JWT (jsonwebtoken) stored in httpOnly cookies | +| Password Hashing | bcryptjs | +| Encryption | AES-256-GCM via Node.js `node:crypto` | +| Workflow Engine | Inngest (durable steps, local dev server) | +| AI SDK | Vercel AI SDK (`ai`, `@ai-sdk/openai`, `@ai-sdk/google`, `@ai-sdk/anthropic`) | +| Templating | Handlebars (with custom `json`, `encodeURI`, `eq` helpers) | +| Graph Ordering | toposort | +| ID Generation | uuid v4 | +| Validation | zod 4 | +| Security | helmet, cors, express-rate-limit | +| Logging | Custom structured JSON logger | + +--- + +## Repository Structure + +``` +nodebase/ +├── package.json # Frontend dependencies +├── next.config.ts +├── tsconfig.json +├── biome.json +├── README.MD +├── Server_Side_Integrations.MD +│ +├── nodebase_backend/ # Express API server (separate project) +│ ├── package.json +│ ├── .env # Backend env vars (not committed) +│ └── src/ +│ ├── server.js # Entry point — starts on PORT (default 4000) +│ ├── app.js # Express app, middleware, routes +│ ├── config/ +│ │ ├── env.js # Validates + exports all env vars +│ │ ├── db.js # pg Pool (SSL always-on for NeonDB) +│ │ └── constants.js # NodeType + ExecutionStatus enums +│ ├── middleware/ +│ │ ├── auth.js # verifyToken — JWT cookie middleware +│ │ ├── validate.js # Zod schema request validation +│ │ ├── error-handler.js # Global error handler +│ │ ├── not-found.js # 404 handler +│ │ └── request-logger.js # HTTP request/response logger +│ ├── modules/ +│ │ ├── auth/ # register, login, logout, me +│ │ ├── users/ # user profile CRUD +│ │ ├── workflows/ # workflow CRUD + execute + SSE stream +│ │ ├── nodes/ # node CRUD per workflow +│ │ ├── connections/ # connection (edge) CRUD per workflow +│ │ ├── credentials/ # encrypted credential CRUD +│ │ ├── executions/ # execution history + SSE stream +│ │ │ └── sse.js # SSEManager (execution + workflow level) +│ │ └── webhooks/ # Google Form + Stripe inbound webhooks +│ ├── engine/ +│ │ ├── runner.js # Workflow orchestrator +│ │ ├── toposort.js # DAG topological sort +│ │ └── template.js # Handlebars template resolution +│ ├── inngest/ +│ │ ├── client.js # Inngest client (isDev in development) +│ │ ├── serve.js # inngest/express serve middleware +│ │ ├── functions/ +│ │ │ └── execute-workflow.js +│ │ └── executors/ # 9 node executors (one per node type) +│ ├── scripts/ +│ │ ├── migrate.js # Migration runner +│ │ ├── 000_create_extensions.sql +│ │ ├── 001_create_enums.sql +│ │ ├── 002_create_users.sql +│ │ ├── 003_create_sessions.sql +│ │ ├── 004_create_accounts.sql +│ │ ├── 005_create_verifications.sql +│ │ ├── 006_create_credentials.sql +│ │ ├── 007_create_workflows.sql +│ │ ├── 008_create_nodes.sql +│ │ ├── 009_create_connections.sql +│ │ ├── 010_create_executions.sql +│ │ └── 011_create_node_executions.sql +│ └── utils/ +│ ├── api-response.js # Standardised JSON response helper +│ ├── api-error.js # AppError class with status code +│ ├── catch-async.js # Wraps async controllers +│ ├── encryption.js # AES-256-GCM encrypt/decrypt +│ ├── logger.js # Structured JSON logger (stdout) +│ └── transaction.js # withTransaction() + RLS SET LOCAL +│ +└── src/ + ├── api/ # Frontend HTTP client layer + │ ├── client.ts # ky instance (NEXT_PUBLIC_API_URL, cookies) + │ ├── auth.ts # login, register, logout, getMe + │ ├── workflows.ts # workflow CRUD + execute + save + │ └── credentials.ts # credential CRUD + getByType + ├── app/ + │ ├── layout.tsx # AuthProvider wrapper + │ ├── (auth)/ # login + signup pages + │ └── (dashboard)/ + │ ├── (editor)/workflows/[workflowId]/page.tsx + │ └── (rest)/ # workflows, credentials, executions pages + ├── components/ + │ ├── react-flow/ + │ │ ├── base-node.tsx # status icons (checkmark/X/spinner) + │ │ ├── base-handle.tsx + │ │ ├── node-status-indicator.tsx # border colors + loading spinner + │ │ └── placeholder-node.tsx + │ └── ui/ # shadcn/ui components + ├── config/ + │ ├── constants.ts # NodeType + ExecutionStatus enums (frontend) + │ └── node-components.ts # nodeComponents map for React Flow + ├── features/ + │ ├── auth/ + │ │ ├── components/ # login-form, register-form (eye toggle) + │ │ ├── store/auth-atoms.ts # currentUserAtom, isAuthenticatedAtom + │ │ └── components/auth-provider.tsx + │ ├── credentials/ + │ │ ├── store/credential-atoms.ts + │ │ ├── hooks/use-credentials.ts + │ │ └── components/ # credential + credentials UI + │ ├── editor/ + │ │ ├── components/ + │ │ │ ├── editor.tsx # React Flow + workflow SSE subscription + │ │ │ ├── editor-header.tsx + │ │ │ └── execute-workflow-button.tsx + │ │ ├── hooks/ + │ │ │ ├── use-execution-stream.ts # SSE connect + subscribeToWorkflow + │ │ │ └── use-node-status.ts # per-node status from atom + │ │ └── store/ + │ │ ├── atoms.ts # editorAtom (ReactFlowInstance) + │ │ └── execution-atoms.ts # nodeStatusMapAtom, activeExecutionIdAtom + │ ├── executions/ + │ │ ├── hooks/use-executions.ts + │ │ └── components/ # execution + executions UI + all 6 execution nodes + │ ├── triggers/ + │ │ └── components/ # 3 trigger nodes (manual, google-form, stripe) + │ ├── subscriptions/ + │ └── workflows/ + │ ├── store/workflow-atoms.ts + │ ├── hooks/use-workflows.ts + │ └── components/ + └── hooks/ + ├── use-entity-search.tsx + ├── use-mobile.ts + └── use-upgrade-modal.tsx +``` + +--- + +## Backend — Setup & Configuration + +### Backend Environment Variables + +Create `nodebase_backend/.env`: + +```env +# Server +PORT=4000 +NODE_ENV=development + +# PostgreSQL (NeonDB or any Postgres — SSL is always enabled) +DATABASE_URL=postgresql://USER:PASSWORD@HOST/DATABASE?sslmode=require + +# JWT — used for httpOnly cookie auth +JWT_SECRET=your-long-random-secret-here +JWT_EXPIRES_IN=7d + +# Credential Encryption — must be exactly 32 bytes (64 hex chars) +# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" +ENCRYPTION_KEY=a1b2c3d4e5f6...64hexchars... + +# CORS — frontend origin +CLIENT_URL=http://localhost:3000 + +# Inngest — only required in production; in development isDev:true is used automatically +INNGEST_EVENT_KEY=your-inngest-event-key +``` + +> **Important:** `ENCRYPTION_KEY` must be a 64-character hex string (32 bytes). Changing it after credentials have been stored will make those credentials unreadable. + +--- + +### Backend Dependencies + +**Production:** + +| Package | Version | Purpose | +| -------------------- | -------- | ------------------------------------------------ | +| `express` | ^5.2.1 | HTTP framework | +| `pg` | ^8.19.0 | PostgreSQL client (connection pool) | +| `jsonwebtoken` | ^9.0.3 | JWT signing/verification | +| `bcryptjs` | ^3.0.3 | Password hashing (10 rounds) | +| `cookie-parser` | ^1.4.7 | Parse httpOnly JWT cookie | +| `cors` | ^2.8.6 | Cross-origin resource sharing | +| `helmet` | ^8.1.0 | Security HTTP headers | +| `express-rate-limit` | ^8.2.1 | Rate limiting per IP | +| `dotenv` | ^17.3.1 | Load `.env` file | +| `zod` | ^4.3.6 | Request body/params validation | +| `uuid` | ^13.0.0 | UUID v4 primary key generation | +| `inngest` | ^3.52.4 | Durable workflow execution engine | +| `ai` | ^6.0.105 | Vercel AI SDK core | +| `@ai-sdk/openai` | ^3.0.37 | OpenAI provider (gpt-4o-mini) | +| `@ai-sdk/google` | ^3.0.34 | Google provider (gemini-2.5-flash) | +| `@ai-sdk/anthropic` | ^3.0.50 | Anthropic provider (claude-sonnet-4) | +| `handlebars` | ^4.7.8 | Template resolution (`{{nodes.id.output.text}}`) | +| `html-entities` | ^2.6.0 | Decode HTML entities after Handlebars rendering | +| `toposort` | ^2.0.2 | Topological sort for DAG execution order | + +**Development:** + +| Package | Version | Purpose | +| --------- | ------- | ---------------------------- | +| `nodemon` | ^3.1.14 | Auto-restart on file changes | + +--- + +### Database Migrations + +All migrations are plain SQL files run in numeric order. The migration runner tracks which have been applied in a `_migrations` table. + +```bash +cd nodebase_backend +npm run db:migrate +``` + +| Migration | Creates | +| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `000_create_extensions` | `pgcrypto`, `uuid-ossp` extensions | +| `001_create_enums` | `node_type` enum (INITIAL, MANUAL_TRIGGER, HTTP_REQUEST, GOOGLE_FORM_TRIGGER, STRIPE_TRIGGER, ANTHROPIC, GEMINI, OPENAI, DISCORD, SLACK), `execution_status` enum (PENDING, RUNNING, SUCCESS, FAILED, CANCELLED) | +| `002_create_users` | `user` table (id TEXT PK, email, name, password_hash, timestamps) with RLS | +| `003_create_sessions` | `session` table for session tracking | +| `004_create_accounts` | `account` table for OAuth accounts | +| `005_create_verifications` | `verification` table | +| `006_create_credentials` | `credential` table (id TEXT PK, user_id FK, name, type, encrypted_value, iv, auth_tag) with RLS | +| `007_create_workflows` | `workflow` table (id TEXT PK, user_id FK, name, timestamps) with RLS | +| `008_create_nodes` | `node` table (id TEXT PK, workflow_id FK, type node_type, data JSONB, position_x, position_y) with RLS | +| `009_create_connections` | `connection` table (id TEXT PK, workflow_id FK, source_node_id, target_node_id, source_handle, target_handle) with RLS | +| `010_create_executions` | `execution` table (id TEXT PK, user_id FK, workflow_id FK, status execution_status, result JSONB, error TEXT, timestamps) with RLS | +| `011_create_node_executions` | `node_execution` table (id TEXT PK, execution_id FK → TEXT, node_id FK → TEXT, status, output JSONB, error TEXT, timestamps) with RLS using `::text` casts | + +> **Note on RLS:** All tables use PostgreSQL Row-Level Security. Every request runs `SET LOCAL app.current_user_id = '...'` via `client.escapeLiteral()` (parameterized queries are not supported by Postgres `SET LOCAL`) inside a transaction, ensuring users can only access their own data. + +--- + +### Running the Backend + +```bash +cd nodebase_backend +npm install +cp .env.example .env # fill in your values +npm run db:migrate # run all 12 migrations +npm run dev # starts nodemon on PORT (default 4000) +``` + +--- + +## Frontend — Setup & Configuration + +### Frontend Environment Variables + +Create `.env.local` in the root `nodebase/` directory: + +```env +# Backend API base URL +NEXT_PUBLIC_API_URL=http://localhost:4000 + +# Webhook URL for trigger nodes (use ngrok tunnel in local dev) +# This is displayed inside the Google Form / Stripe trigger dialogs +# so users know where to point their external service. +NEXT_PUBLIC_WEBHOOK_URL=https://your-ngrok-subdomain.ngrok-free.app +``` + +--- + +### Frontend Dependencies + +**Key additions and their roles:** + +| Package | Version | Purpose | +| ----------------------- | -------- | ------------------------------------------------------------------------------------------------ | +| `ky` | ^1.12.0 | Lightweight HTTP client replacing tRPC. Configured with `credentials: "include"` for cookie auth | +| `jotai` | ^2.15.0 | Atomic state management for auth, workflows, credentials, and real-time execution status | +| `@xyflow/react` | ^12.8.6 | React Flow — visual node graph editor | +| `react-hook-form` | ^7.64.0 | Form state management for all dialogs | +| `zod` | ^4.1.11 | Frontend schema validation (mirrors backend) | +| `sonner` | ^2.0.7 | Toast notifications | +| `next` | 15.5.4 | App Router with Turbopack | +| `react` / `react-dom` | 19.1.0 | React 19 | +| `lucide-react` | ^0.544.0 | All icons including Eye/EyeOff for password toggles | +| `@tanstack/react-query` | ^5.90.2 | Server state management (retained from original) | + +--- + +### Running the Frontend + +```bash +cd nodebase # root of the repo +npm install +cp .env.local.example .env.local # fill in values +npm run dev # starts Next.js on port 3000 (Turbopack) +``` + +--- + +## Inngest Dev Server + +Inngest is used as the durable workflow execution engine. In development, you need the Inngest Dev Server running alongside the backend so it can receive and dispatch workflow events. + +```bash +cd nodebase_backend +npm run inngest:dev +# runs: npx inngest-cli@latest dev -u http://localhost:4000/api/inngest +``` + +The `-u` flag tells Inngest exactly where your serve endpoint is, preventing it from probing random paths on your frontend (which causes 404 noise in the browser console). + +The Inngest dashboard is available at **http://localhost:8288** — you can inspect events, replay failed functions, and see step-by-step execution traces there. + +**How Inngest is used:** + +1. `POST /api/workflows/:id/execute` (or a webhook) creates an execution row and fires `workflow/execute` event +2. The Inngest function picks it up, loads the workflow graph + credentials, and runs the engine +3. Each node execution is a durable step — if the process crashes, Inngest resumes from the last completed step +4. The function emits SSE events back to Express via `sseManager` as each node runs + +--- + +## Webhooks (Local Development) + +Google Form and Stripe triggers require an externally reachable URL. Use [ngrok](https://ngrok.com) to tunnel your local backend: + +```bash +ngrok http 4000 +# e.g. output: https://ideographic-arie-hastily.ngrok-free.app +``` + +Then set in `.env.local`: + +```env +NEXT_PUBLIC_WEBHOOK_URL=https://ideographic-arie-hastily.ngrok-free.app +``` + +This URL is shown inside the Google Form Trigger and Stripe Trigger node configuration dialogs so you can copy it directly into the external service. + +**Webhook endpoints (no authentication required):** + +| Trigger | Method | URL | +| ----------- | ------ | ---------------------------------------------------------------- | +| Google Form | POST | `http://localhost:4000/api/webhooks/google-form?workflowId=` | +| Stripe | POST | `http://localhost:4000/api/webhooks/stripe?workflowId=` | + +Both endpoints: + +1. Look up the workflow and its owner +2. Create an `execution` row with status `RUNNING` +3. Fire the `workflow/execute` Inngest event with the trigger payload +4. Return `202 Accepted` immediately + +--- + +## API Reference + +All routes are prefixed with `/api`. All routes except `/api/auth/*` and `/api/webhooks/*` require a valid JWT cookie (`Authorization` via httpOnly cookie set at login). + +### Auth — `/api/auth` + +| Method | Path | Description | +| ------ | ----------- | ------------------------------------------------------------------ | +| POST | `/register` | Create account. Body: `{ name, email, password }` | +| POST | `/login` | Sign in. Sets `token` httpOnly cookie. Body: `{ email, password }` | +| POST | `/logout` | Clear auth cookie | +| GET | `/me` | Return current authenticated user | + +### Workflows — `/api/workflows` + +| Method | Path | Description | +| ------ | -------------- | ---------------------------------------------------------------------------------------- | +| GET | `/` | List workflows with pagination (`?page=1&pageSize=10`) | +| POST | `/` | Create workflow. Body: `{ name }` | +| GET | `/:id` | Get workflow with nodes and connections | +| PATCH | `/:id/name` | Rename workflow. Body: `{ name }` | +| PUT | `/:id` | Save full workflow (delete-and-reinsert nodes/connections). Body: `{ nodes[], edges[] }` | +| DELETE | `/:id` | Delete workflow | +| POST | `/:id/execute` | Start execution (creates execution row + fires Inngest event) | +| GET | `/:id/stream` | SSE stream — notifies open editors when any execution starts on this workflow | + +### Credentials — `/api/credentials` + +| Method | Path | Description | +| ------ | ------------- | -------------------------------------------------------------- | +| GET | `/` | List credentials (encrypted values never returned) | +| POST | `/` | Create credential. Body: `{ name, type, value }` | +| GET | `/:id` | Get credential metadata | +| PATCH | `/:id` | Update credential. Body: `{ name?, value? }` | +| DELETE | `/:id` | Delete credential | +| GET | `/type/:type` | Get credentials by type (e.g. `OPENAI`, `GEMINI`, `ANTHROPIC`) | + +### Executions — `/api/executions` + +| Method | Path | Description | +| ------ | ------------- | ----------------------------------------------------------- | +| GET | `/` | List executions with pagination | +| GET | `/:id` | Get execution details | +| GET | `/:id/nodes` | Get per-node execution results | +| GET | `/:id/stream` | SSE stream — real-time node status events for one execution | + +### Webhooks — `/api/webhooks` (no auth) + +| Method | Path | Description | +| ------ | -------------------------- | ------------------------------------------------------ | +| POST | `/google-form?workflowId=` | Trigger workflow execution from Google Form submission | +| POST | `/stripe?workflowId=` | Trigger workflow execution from Stripe event | + +### Nodes & Connections — `/api/nodes`, `/api/connections` + +Full CRUD used internally by the workflow save/load flow. + +--- + +## Workflow Engine + +The engine (`src/engine/`) runs workflows as a directed acyclic graph (DAG). + +### Execution Order — `toposort.js` + +Nodes are sorted into a linear execution order respecting all edge dependencies. If node B depends on output from node A, A always runs first. Circular dependencies throw an error before execution begins. + +### Template Resolution — `template.js` + +Before a node runs, all string fields in its `data` object are processed through Handlebars. This lets node configuration reference outputs from previously executed nodes: + +``` +"userPrompt": "Summarise this form response: {{json nodes.abc123.output}}" +``` + +**Custom Handlebars helpers registered:** + +- `{{json value}}` — serialises any value to a pretty-printed JSON string +- `{{encodeURI value}}` — URI-encodes a string +- `{{#eq a b}}...{{/eq}}` — equality block helper + +### Runner — `runner.js` + +The `runWorkflow()` function: + +1. Calls `toposort` to get ordered node IDs +2. Skips `INITIAL` placeholder nodes +3. For each node: resolves templates → calls the executor → stores output in `context.nodes[nodeId]` +4. At each step calls `onNodeStart`, `onNodeComplete`, or `onNodeError` callbacks +5. The Inngest function wires these callbacks to both database updates and SSE events + +--- + +## Node Types & Executors + +### Trigger Nodes (start the workflow) + +| Node | Executor | Behaviour | +| ----------------------- | ------------------------ | ----------------------------------------------------- | +| **Manual Trigger** | `manual-trigger.js` | Pass-through. Used for the "Execute workflow" button. | +| **Google Form Trigger** | `google-form-trigger.js` | Receives `triggerPayload.formData` from the webhook. | +| **Stripe Trigger** | `stripe-trigger.js` | Receives `triggerPayload.event` from the webhook. | + +### Execution Nodes (do the work) + +| Node | Executor | Model / Service | Credential Type | +| ---------------- | ----------------- | ---------------------------------- | ----------------------- | +| **HTTP Request** | `http-request.js` | Configurable method, URL, body | None | +| **OpenAI** | `openai.js` | `gpt-4o-mini` (Vercel AI SDK) | `OPENAI` | +| **Anthropic** | `anthropic.js` | `claude-sonnet-4` (Vercel AI SDK) | `ANTHROPIC` | +| **Gemini** | `gemini.js` | `gemini-2.5-flash` (Vercel AI SDK) | `GEMINI` | +| **Discord** | `discord.js` | Webhook message | `DISCORD` (webhook URL) | +| **Slack** | `slack.js` | Webhook message | `SLACK` (webhook URL) | + +**AI node configuration (shared by OpenAI, Anthropic, Gemini):** + +- `credentialId` — references a saved credential for the API key +- `systemPrompt` _(optional)_ — sets the AI's role/behaviour +- `userPrompt` _(required)_ — the actual prompt, supports `{{template}}` expressions +- `variableName` — the key under which this node's output is accessible to downstream nodes as `{{nodes..output.text}}` + +--- + +## Real-Time Execution Status (SSE) + +Nodes in the editor show live execution status with no polling: + +| Status | Visual | +| ------- | ---------------------------------------------- | +| Running | Blue animated border + spinner overlay | +| Success | Green border + ✓ checkmark icon (bottom-right) | +| Error | Red border + ✗ icon (bottom-right) | + +### How it works + +**Two-level SSE architecture:** + +1. **Execution-level stream** (`GET /api/executions/:id/stream`) + - Opened once an execution ID is known + - Events: `node:start`, `node:complete`, `node:error`, `execution:complete`, `execution:error` + - Updates `nodeStatusMapAtom` in Jotai → each node component re-renders with new status + +2. **Workflow-level stream** (`GET /api/workflows/:id/stream`) + - Opened automatically when the editor mounts, stays alive the whole session + - Event: `execution:started` — fires when _any_ execution begins on this workflow + - Auto-triggers the execution-level subscription with the new `executionId` + +**Why two levels?** The "Execute workflow" button knows the `executionId` immediately (it gets it from the API response). But webhook triggers (Google Form, Stripe) run externally — the browser never learns the `executionId` without the workflow-level channel. The workflow stream bridges this gap. + +### SSEManager (`src/modules/executions/sse.js`) + +A singleton class that maintains two `Map`s: + +- `connections`: `executionId → Response[]` +- `workflowConnections`: `workflowId → Response[]` + +The Inngest function holds a direct reference to `sseManager` and calls `send()` / `sendWorkflow()` / `close()` as execution progresses. + +--- + +## Authentication + +Authentication uses **JWT stored in httpOnly cookies**, not `Authorization` headers. + +**Login flow:** + +1. `POST /api/auth/login` → verifies password with `bcryptjs.compare` → signs JWT with `JWT_SECRET` → sets `token` cookie (`httpOnly: true, sameSite: "lax"`) +2. All subsequent requests include the cookie automatically (browser-native) +3. `verifyToken` middleware extracts and verifies the JWT, attaches `req.user` + +**Why cookies over Bearer tokens:** + +- httpOnly cookies are not accessible from JavaScript — XSS cannot steal them +- Automatic inclusion by the browser — no token management in frontend code +- Works naturally with SSE (`EventSource` always sends cookies on same-origin requests) + +**Frontend:** + +- `ky` is configured with `credentials: "include"` so all API requests send the cookie +- `EventSource` is created with `{ withCredentials: true }` for the same reason +- `AuthProvider` calls `getMe()` on mount to hydrate `currentUserAtom`; on 401 the atom is set to `null` and the user is redirected to login + +--- + +## Credential Encryption + +API keys and webhook secrets stored in credentials are encrypted at rest using **AES-256-GCM**. + +**Encryption details (`src/utils/encryption.js`):** + +- Algorithm: `aes-256-gcm` +- Key: 32-byte buffer derived from `ENCRYPTION_KEY` hex string +- IV: 16 random bytes generated per encryption, stored alongside ciphertext +- Auth tag: 16 bytes, stored alongside ciphertext +- Storage: `encrypted_value` (hex), `iv` (hex), `auth_tag` (hex) columns in `credential` table + +**Decryption at execution time:** +The `getCredentialsForWorkflow()` service decrypts all credentials needed by a workflow's nodes during the Inngest `load-workflow` step, passing plain-text values to executors in memory only — decrypted values are never persisted. + +--- + +## Key Architectural Decisions + +### Why a separate Express backend instead of Next.js API routes? + +- **Server-Sent Events (SSE)**: Next.js API routes run in Vercel's edge/serverless environment which does not support persistent TCP connections. SSE requires a long-lived connection that only a traditional server can provide. +- **Inngest integration**: The Inngest background function holds a live reference to `sseManager` (in-process singleton). This only works in a persistent Node.js process. +- **Database transactions with RLS**: Using `SET LOCAL` for row-level security requires a real connection pool that can hold clients across transaction boundaries. +- **Full control**: No edge runtime restrictions, no 10-second function timeouts, no cold starts. + +### Why Jotai instead of keeping TanStack Query for everything? + +- Execution status (SSE events) is push-based, not request-based. TanStack Query polls or refetches; it is not designed for live SSE streams. +- Jotai atoms are the ideal store for `nodeStatusMap` — they are fine-grained (each node subscribes to only its own status), synchronous, and update-friendly. +- TanStack Query is still used where appropriate (list views, detail pages). + +### Why Inngest instead of running executors directly? + +- Durability: if the server restarts mid-execution, Inngest resumes from the last completed step. +- Retryability: individual steps can be retried without re-running the whole workflow. +- Observability: the Inngest Dev Server UI shows every event, step, and output. +- Decoupling: the HTTP request that starts a workflow returns in `<50ms`; execution happens in the background. + +### Handlebars for templating + +Node configuration fields support `{{nodes..output.text}}` expressions. This lets users chain outputs between nodes — e.g. feed a Google Form response directly into a Gemini prompt — without any code. Handlebars was chosen for its well-understood syntax, safety (no arbitrary code execution), and ease of extending with custom helpers. + +--- + +## What Was Removed + +The following were completely removed as part of this migration: + +| Removed | Replaced with | +| --------------------------------------------------------------- | ---------------------------------------------------------- | +| **tRPC** (client, server, routers, init, query-client) | Direct REST calls via `ky` | +| **Prisma** (schema, client, 12 migration files) | Raw SQL via `pg` Pool + custom migration runner | +| **BetterAuth** (auth.ts, auth-client.ts, API route) | Custom JWT + bcryptjs authentication | +| **Sentry** (instrumentation, configs, example page, API route) | Custom structured JSON logger | +| **Polar** (subscriptions Polar client) | Subscription hook stubbed | +| **Inngest client-side** (channels, functions, utils, API route) | Inngest moved entirely to backend | +| **Next.js API routes for webhooks** | Express webhook module (required for SSE singleton access) | +| **Server-side `prefetch` / `params-loader` files** | Hook-based data fetching via `ky` API layer | +| **mprocs** (process manager config) | Separate terminal tabs or `concurrently` | diff --git a/README.md b/README.md deleted file mode 100644 index e215bc4..0000000 --- a/README.md +++ /dev/null @@ -1,36 +0,0 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). - -## Getting Started - -First, run the development server: - -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` - -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/Server_Side_Integrations.MD b/Server_Side_Integrations.MD new file mode 100644 index 0000000..4bbd36b --- /dev/null +++ b/Server_Side_Integrations.MD @@ -0,0 +1,181 @@ +# Server-Side Integrations — Removed & Documented + +This document records all server-side integrations that were removed from Nodebase to transform it into a client-only UI/UX application. Each section notes the original purpose and what to connect when building the custom backend. + +--- + +## 1. Database — Prisma + PostgreSQL (Neon) + +### What was removed +- Package: `prisma`, `@prisma/client` +- Files: `prisma/` schema directory, `src/generated/` (Prisma client), `src/lib/db.ts` +- All `@/generated/prisma` imports replaced with local enums in `src/config/node-components.ts` + +### Custom backend integration points +- Expose a REST/GraphQL API for all CRUD operations +- `NodeType` and `ExecutionStatus` enums must match the database schema values +- Re-add `src/generated/` (or use a custom type package) when Prisma is re-introduced + +--- + +## 2. Authentication — Better Auth + +### What was removed +- Package: `better-auth` +- Files: `src/lib/auth.ts`, `src/lib/auth-client.ts`, `src/app/api/auth/` +- All `authClient.*` calls replaced with `toast.info("…requires custom backend")` stubs +- `requireAuth()` calls commented out in all dashboard pages + +### Custom backend integration points +All auth flows need corresponding endpoints: + +| Action | Stub location | Backend route | +|---|---|---| +| Email register | `register-form.tsx` | `POST /api/auth/register` | +| Email login | `login-form.tsx` | `POST /api/auth/login` | +| GitHub OAuth | `login-form.tsx`, `register-form.tsx` | `GET /api/auth/github` | +| Google OAuth | `login-form.tsx`, `register-form.tsx` | `GET /api/auth/google` | +| Sign out | `app-sidebar.tsx` | `POST /api/auth/logout` | +| Billing/checkout | `app-sidebar.tsx`, `upgrade-modal.tsx` | `POST /api/billing/checkout` | +| Billing portal | `app-sidebar.tsx` | `GET /api/billing/portal` | + +**Re-enable auth guards** by uncommenting `// await requireAuth()` in all dashboard page files once the backend exposes a session-check endpoint. + +--- + +## 3. Background Jobs — Inngest + +### What was removed +- Packages: `inngest`, `@inngest/realtime` +- Files: `src/inngest/` (client, functions, channels), `src/app/api/inngest/` +- All `actions.ts` files (per node type) — replaced with no-op stubs +- All `executor.ts` files — replaced with passthrough stubs +- `src/features/executions/hooks/use-node-status.ts` — removed (realtime status hook) +- Scripts removed from `package.json`: `inngest:dev`, `ngrok:dev`, `dev:all` + +### Custom backend integration points +Each node executor needs a corresponding backend handler: + +| Node | Executor stub file | +|---|---| +| Manual Trigger | `src/features/triggers/components/manual-trigger/executor.ts` | +| Google Form Trigger | `src/features/triggers/components/google-form-trigger/executor.ts` | +| Stripe Trigger | `src/features/triggers/components/stripe-trigger/executor.ts` | +| HTTP Request | `src/features/executions/components/http-request/executor.ts` | +| Gemini | `src/features/executions/components/gemini/executor.ts` | +| OpenAI | `src/features/executions/components/openai/executor.ts` | +| Anthropic | `src/features/executions/components/anthropic/executor.ts` | +| Discord | `src/features/executions/components/discord/executor.ts` | +| Slack | `src/features/executions/components/slack/executor.ts` | + +Each `actions.ts` file (per node) is the place to add real-time token fetching once a backend SSE/WebSocket is available. + +--- + +## 4. tRPC — API Layer + +### What was removed +- Packages: `@trpc/server`, `@trpc/client`, `@trpc/react-query`, `@trpc/next`, `superjson` +- Files: `src/trpc/` (entire directory — routers, server, client) +- Files: `src/features/*/server/routers.ts` +- `TRPCReactProvider` removed from `src/app/layout.tsx` +- All `useTRPC`, `useSuspenseQuery`, `useMutation`, `HydrateClient`, server prefetch calls removed + +### Custom backend integration points +All tRPC procedure calls replaced with stub hooks in: + +| Hook file | Stubs provided | +|---|---| +| `src/features/workflows/hooks/use-workflows.ts` | `useSuspenseWorkflows`, `useCreateWorkflow`, `useRemoveWorkflow`, `useSuspenseWorkflow`, `useUpdateWorkflowName`, `useUpdateWorkflow`, `useExecuteWorkflow` | +| `src/features/credentials/hooks/use-credentials.ts` | `useSuspenseCredentials`, `useCreateCredential`, `useRemoveCredential`, `useSuspenseCredential`, `useUpdateCredential`, `useCredentialsByType` | +| `src/features/executions/hooks/use-executions.ts` | `useSuspenseExecutions`, `useSuspenseExecution` | + +To integrate with a custom backend, replace `toast.info(…)` stubs inside these hooks with `fetch`/`ky` calls to the corresponding REST endpoints. + +--- + +## 5. Billing — Polar + +### What was removed +- Packages: `@polar-sh/nextjs`, `@polar-sh/sdk` +- Files: `src/lib/polar.ts`, `src/app/api/polar/` +- `authClient.checkout({ slug: "pro" })` → toast stub in `upgrade-modal.tsx` and `app-sidebar.tsx` +- `authClient.customer.portal()` → toast stub in `app-sidebar.tsx` + +### Custom backend integration points +| Feature | Stub location | +|---|---| +| Subscription status | `src/features/subscriptions/hooks/use-subscription.ts` — returns `hasActiveSubscription: false` | +| Checkout | `upgrade-modal.tsx`, `app-sidebar.tsx` → connect to `POST /api/billing/checkout` | +| Portal | `app-sidebar.tsx` → connect to `GET /api/billing/portal` | + +--- + +## 6. Monitoring — Sentry + +### What was removed +- Package: `@sentry/nextjs` +- Files: `sentry.client.config.ts`, `sentry.server.config.ts`, `sentry.edge.config.ts`, `src/app/sentry-example-page/`, `src/instrumentation.ts` +- `withSentryConfig` wrapper removed from `next.config.ts` +- `src/app/global-error.tsx` simplified to plain React error boundary + +### Custom backend integration points +Re-add Sentry or a similar monitoring solution (LogRocket, Datadog) when the backend is ready. Configure in `next.config.ts` and `src/instrumentation.ts`. + +--- + +## 7. Encryption — Cryptr + +### What was removed +- Package: `cryptr` +- File: `src/lib/encryption.ts` + +### Custom backend integration point +Credential values must be encrypted at rest on the backend. Use AES-256-GCM or equivalent. Pass only encrypted values over the wire; decrypt only on the backend. + +--- + +## 8. AI SDK — Vercel AI + +### What was removed +- Packages: `ai`, `@ai-sdk/anthropic`, `@ai-sdk/google`, `@ai-sdk/openai` + +### Custom backend integration points +- The executor stubs in each AI node (`gemini/`, `openai/`, `anthropic/`) are the integration points +- AI calls should be made from the backend (keeps API keys server-side) +- The backend returns results to the client via the execution status websocket/SSE + +--- + +## 9. Email Rendering — Handlebars + html-entities + toposort + +### What was removed +- Packages: `handlebars`, `html-entities`, `toposort` + +### Custom backend integration points +- These were used in the workflow runner to template node data +- The custom backend workflow engine should implement the same `{{variable}}` templating +- `toposort` was used to determine node execution order — re-implement in the backend DAG runner + +--- + +## 10. Environment Variables Removed + +All previously configured env vars have been cleared from `.env`. When reconnecting: + +| Variable | Purpose | +|---|---| +| `DATABASE_URL` | Prisma PostgreSQL connection | +| `BETTER_AUTH_SECRET` | Auth token signing secret | +| `BETTER_AUTH_URL` | Auth redirect base URL | +| `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` | GitHub OAuth | +| `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` | Google OAuth | +| `POLAR_ACCESS_TOKEN` | Polar billing API | +| `POLAR_SUCCESS_URL` | Checkout redirect | +| `INNGEST_EVENT_KEY` / `INNGEST_SIGNING_KEY` | Inngest webhook verification | +| `NGROK_URL` | Tunnel URL for local webhook testing | +| `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `GEMINI_API_KEY` | AI provider keys | + +--- + +_Last updated: 2026-03-01_ diff --git a/mprocs.log b/mprocs.log deleted file mode 100644 index 3cc7f7b..0000000 --- a/mprocs.log +++ /dev/null @@ -1 +0,0 @@ -ERROR [mprocs::error] Error: channel closed diff --git a/mprocs.yaml b/mprocs.yaml deleted file mode 100644 index 93561e1..0000000 --- a/mprocs.yaml +++ /dev/null @@ -1,9 +0,0 @@ -procs: - ngrok: - cmd: ["npm", "run", "ngrok:dev"] - - inngest: - cmd: ["npm", "run", "inngest:dev"] - - next: - cmd: ["npm", "run", "dev"] diff --git a/next.config.ts b/next.config.ts index fbef8f5..503ec1e 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,4 +1,3 @@ -import {withSentryConfig} from "@sentry/nextjs"; import type { NextConfig } from "next"; const nextConfig: NextConfig = { @@ -9,40 +8,9 @@ const nextConfig: NextConfig = { source: "/", destination: "/workflows", permanent: false, - } + }, ]; }, }; -export default withSentryConfig(nextConfig, { - // For all available options, see: - // https://www.npmjs.com/package/@sentry/webpack-plugin#options - - org: "enra-doo", - - project: "nodebase", - - // Only print logs for uploading source maps in CI - silent: !process.env.CI, - - // For all available options, see: - // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/ - - // Upload a larger set of source maps for prettier stack traces (increases build time) - widenClientFileUpload: true, - - // Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers. - // This can increase your server load as well as your hosting bill. - // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client- - // side errors will fail. - tunnelRoute: "/monitoring", - - // Automatically tree-shake Sentry logger statements to reduce bundle size - disableLogger: true, - - // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.) - // See the following for more information: - // https://docs.sentry.io/product/crons/ - // https://vercel.com/docs/cron-jobs - automaticVercelMonitors: true -}); \ No newline at end of file +export default nextConfig; \ No newline at end of file diff --git a/nodebase_backend/.gitignore b/nodebase_backend/.gitignore new file mode 100644 index 0000000..7c3aca7 --- /dev/null +++ b/nodebase_backend/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +.env* +dist/ +logs/ +coverage/ + diff --git a/nodebase_backend/package-lock.json b/nodebase_backend/package-lock.json new file mode 100644 index 0000000..e9fbf68 --- /dev/null +++ b/nodebase_backend/package-lock.json @@ -0,0 +1,4867 @@ +{ + "name": "nodebase_backend", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "nodebase_backend", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@ai-sdk/anthropic": "^3.0.50", + "@ai-sdk/google": "^3.0.34", + "@ai-sdk/openai": "^3.0.37", + "ai": "^6.0.105", + "bcryptjs": "^3.0.3", + "cookie-parser": "^1.4.7", + "cors": "^2.8.6", + "dotenv": "^17.3.1", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "handlebars": "^4.7.8", + "helmet": "^8.1.0", + "html-entities": "^2.6.0", + "inngest": "^3.52.4", + "jsonwebtoken": "^9.0.3", + "pg": "^8.19.0", + "toposort": "^2.0.2", + "uuid": "^13.0.0", + "zod": "^4.3.6" + }, + "devDependencies": { + "nodemon": "^3.1.14" + } + }, + "node_modules/@ai-sdk/anthropic": { + "version": "3.0.50", + "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-3.0.50.tgz", + "integrity": "sha512-BkCUgGTp/iZJuuFBF1wv7GGnrEJg7X7hqbaa+/t4HTBt9dZn3e6NFn5NhPUvo2p5SreUeHEl0As0r2uaVn3K9Q==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.16" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/gateway": { + "version": "3.0.59", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-3.0.59.tgz", + "integrity": "sha512-MbtheWHgEFV/8HL1Z6E3hOAsmP73zZlNFg0F0nJAD0Adnjp4J/plqNK00Y896d+dWTw+r0OXzyov9/2wCFjH0Q==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.16", + "@vercel/oidc": "3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/google": { + "version": "3.0.34", + "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-3.0.34.tgz", + "integrity": "sha512-1tXUr1W5YACXPgtHYWIU3raqMsayp6cMI8NUT4EEzzZSpvHzkkiNWHEr+bGxEGurSUukfo+pE1RKpLwBFOZtJg==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.16" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/openai": { + "version": "3.0.37", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-3.0.37.tgz", + "integrity": "sha512-bcYjT3/58i/C0DN3AnrjiGsAb0kYivZLWWUtgTjsBurHSht/LTEy+w3dw5XQe3FmZwX7Z/mUQCiA3wB/5Kf7ow==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.16" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/provider": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.8.tgz", + "integrity": "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-4.0.16.tgz", + "integrity": "sha512-kBvDqNkt5EwlzF9FujmNhhtl8FYg3e8FO8P5uneKliqfRThWemzBj+wfYr7ZCymAQhTRnwSSz1/SOqhOAwmx9g==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@standard-schema/spec": "^1.1.0", + "eventsource-parser": "^3.0.6" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.11.0.tgz", + "integrity": "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@grpc/grpc-js": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.3.tgz", + "integrity": "sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.8.0", + "@js-sdsl/ordered-map": "^4.4.2" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", + "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.5.3", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@inngest/ai": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@inngest/ai/-/ai-0.1.7.tgz", + "integrity": "sha512-5xWatW441jacGf9czKEZdgAmkvoy7GS2tp7X8GSbdGeRXzjisHR6vM+q8DQbv6rqRsmQoCQ5iShh34MguELvUQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "^22.10.5", + "typescript": "^5.7.3" + } + }, + "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==", + "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==", + "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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jpwilliams/waitgroup": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@jpwilliams/waitgroup/-/waitgroup-2.1.1.tgz", + "integrity": "sha512-0CxRhNfkvFCTLZBKGvKxY2FYtYW1yWhO2McLqBL0X5UWvYjIf9suH8anKW/DNutl369A75Ewyoh2iJMwBZ2tRg==", + "license": "MIT" + }, + "node_modules/@js-sdsl/ordered-map": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", + "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.212.0.tgz", + "integrity": "sha512-TEEVrLbNROUkYY51sBJGk7lO/OLjuepch8+hmpM6ffMJQ2z/KVCjdHuCFX6fJj8OkJP2zckPjrJzQtXU3IAsFg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/auto-instrumentations-node": { + "version": "0.70.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.70.1.tgz", + "integrity": "sha512-r8BKs0rHtBAzZViPIuzSD2eh65fOPau0NqVsca2sACuZ6LFGu6a+QMhqq7skXz+/OqKwFr/7/b6VsaNMS+zZpQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/instrumentation-amqplib": "^0.59.0", + "@opentelemetry/instrumentation-aws-lambda": "^0.64.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.67.0", + "@opentelemetry/instrumentation-bunyan": "^0.57.0", + "@opentelemetry/instrumentation-cassandra-driver": "^0.57.0", + "@opentelemetry/instrumentation-connect": "^0.55.0", + "@opentelemetry/instrumentation-cucumber": "^0.28.0", + "@opentelemetry/instrumentation-dataloader": "^0.29.0", + "@opentelemetry/instrumentation-dns": "^0.55.0", + "@opentelemetry/instrumentation-express": "^0.60.0", + "@opentelemetry/instrumentation-fastify": "^0.56.0", + "@opentelemetry/instrumentation-fs": "^0.31.0", + "@opentelemetry/instrumentation-generic-pool": "^0.55.0", + "@opentelemetry/instrumentation-graphql": "^0.60.0", + "@opentelemetry/instrumentation-grpc": "^0.212.0", + "@opentelemetry/instrumentation-hapi": "^0.58.0", + "@opentelemetry/instrumentation-http": "^0.212.0", + "@opentelemetry/instrumentation-ioredis": "^0.60.0", + "@opentelemetry/instrumentation-kafkajs": "^0.21.0", + "@opentelemetry/instrumentation-knex": "^0.56.0", + "@opentelemetry/instrumentation-koa": "^0.60.0", + "@opentelemetry/instrumentation-lru-memoizer": "^0.56.0", + "@opentelemetry/instrumentation-memcached": "^0.55.0", + "@opentelemetry/instrumentation-mongodb": "^0.65.0", + "@opentelemetry/instrumentation-mongoose": "^0.58.0", + "@opentelemetry/instrumentation-mysql": "^0.58.0", + "@opentelemetry/instrumentation-mysql2": "^0.58.0", + "@opentelemetry/instrumentation-nestjs-core": "^0.58.0", + "@opentelemetry/instrumentation-net": "^0.56.0", + "@opentelemetry/instrumentation-openai": "^0.10.0", + "@opentelemetry/instrumentation-oracledb": "^0.37.0", + "@opentelemetry/instrumentation-pg": "^0.64.0", + "@opentelemetry/instrumentation-pino": "^0.58.0", + "@opentelemetry/instrumentation-redis": "^0.60.0", + "@opentelemetry/instrumentation-restify": "^0.57.0", + "@opentelemetry/instrumentation-router": "^0.56.0", + "@opentelemetry/instrumentation-runtime-node": "^0.25.0", + "@opentelemetry/instrumentation-socket.io": "^0.59.0", + "@opentelemetry/instrumentation-tedious": "^0.31.0", + "@opentelemetry/instrumentation-undici": "^0.22.0", + "@opentelemetry/instrumentation-winston": "^0.56.0", + "@opentelemetry/resource-detector-alibaba-cloud": "^0.33.2", + "@opentelemetry/resource-detector-aws": "^2.12.0", + "@opentelemetry/resource-detector-azure": "^0.20.0", + "@opentelemetry/resource-detector-container": "^0.8.3", + "@opentelemetry/resource-detector-gcp": "^0.47.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/sdk-node": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.4.1", + "@opentelemetry/core": "^2.0.0" + } + }, + "node_modules/@opentelemetry/configuration": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/configuration/-/configuration-0.212.0.tgz", + "integrity": "sha512-D8sAY6RbqMa1W8lCeiaSL2eMCW2MF87QI3y+I6DQE1j+5GrDMwiKPLdzpa/2/+Zl9v1//74LmooCTCJBvWR8Iw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "yaml": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.5.1.tgz", + "integrity": "sha512-MHbu8XxCHcBn6RwvCt2Vpn1WnLMNECfNKYB14LI5XypcgH4IE0/DiVifVR9tAkwPMyLXN8dOoPJfya3IryLQVw==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.5.1.tgz", + "integrity": "sha512-Dwlc+3HAZqpgTYq0MUyZABjFkcrKTePwuiFVLjahGD8cx3enqihmpAmdgNFO1R4m/sIe5afjJrA25Prqy4NXlA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.212.0.tgz", + "integrity": "sha512-/0bk6fQG+eSFZ4L6NlckGTgUous/ib5+OVdg0x4OdwYeHzV3lTEo3it1HgnPY6UKpmX7ki+hJvxjsOql8rCeZA==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/sdk-logs": "0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-http": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.212.0.tgz", + "integrity": "sha512-JidJasLwG/7M9RTxV/64xotDKmFAUSBc9SNlxI32QYuUMK5rVKhHNWMPDzC7E0pCAL3cu+FyiKvsTwLi2KqPYw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.212.0", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/sdk-logs": "0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-logs-otlp-proto": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.212.0.tgz", + "integrity": "sha512-RpKB5UVfxc7c6Ta1UaCrxXDTQ0OD7BCGT66a97Q5zR1x3+9fw4dSaiqMXT/6FAWj2HyFbem6Rcu1UzPZikGTWQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.212.0", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-logs": "0.212.0", + "@opentelemetry/sdk-trace-base": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.212.0.tgz", + "integrity": "sha512-/6Gqf9wpBq22XsomR1i0iPGnbQtCq2Vwnrq5oiDPjYSqveBdK1jtQbhGfmpK2mLLxk4cPDtD1ZEYdIou5K8EaA==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.212.0", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-metrics": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.212.0.tgz", + "integrity": "sha512-8hgBw3aTTRpSTkU4b9MLf/2YVLnfWp+hfnLq/1Fa2cky+vx6HqTodo+Zv1GTIrAKMOOwgysOjufy0gTxngqeBg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-metrics": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.212.0.tgz", + "integrity": "sha512-C7I4WN+ghn3g7SnxXm2RK3/sRD0k/BYcXaK6lGU3yPjiM7a1M25MLuM6zY3PeVPPzzTZPfuS7+wgn/tHk768Xw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/exporter-metrics-otlp-http": "0.212.0", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-metrics": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-prometheus": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.212.0.tgz", + "integrity": "sha512-hJFLhCJba5MW5QHexZMHZdMhBfNqNItxOsN0AZojwD1W2kU9xM+BEICowFGJFo/vNV+I2BJvTtmuKafeDSAo7Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-metrics": "2.5.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-grpc": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.212.0.tgz", + "integrity": "sha512-9xTuYWp8ClBhljDGAoa0NSsJcsxJsC9zCFKMSZJp1Osb9pjXCMRdA6fwXtlubyqe7w8FH16EWtQNKx/FWi+Ghw==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-trace-base": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-http": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.212.0.tgz", + "integrity": "sha512-v/0wMozNoiEPRolzC4YoPo4rAT0q8r7aqdnRw3Nu7IDN0CGFzNQazkfAlBJ6N5y0FYJkban7Aw5WnN73//6YlA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-trace-base": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.212.0.tgz", + "integrity": "sha512-d1ivqPT0V+i0IVOOdzGaLqonjtlk5jYrW7ItutWzXL/Mk+PiYb59dymy/i2reot9dDnBFWfrsvxyqdutGF5Vig==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-trace-base": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-zipkin": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-2.5.1.tgz", + "integrity": "sha512-Me6JVO7WqXGXsgr4+7o+B7qwKJQbt0c8WamFnxpkR43avgG9k/niTntwCaXiXUTjonWy0+61ZuX6CGzj9nn8CQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-trace-base": "2.5.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.212.0.tgz", + "integrity": "sha512-IyXmpNnifNouMOe0I/gX7ENfv2ZCNdYTF0FpCsoBcpbIHzk81Ww9rQTYTnvghszCg7qGrIhNvWC8dhEifgX9Jg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.212.0", + "import-in-the-middle": "^2.0.6", + "require-in-the-middle": "^8.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.59.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.59.0.tgz", + "integrity": "sha512-xscSgOJA+GHphESDZxBHNk/zjNaEgoeufMwmiqYdL+qM27Xw3BbR9vN6Ucbq9dW6Y+oYUPgTTj17qf+Za4+uzg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-lambda": { + "version": "0.64.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.64.0.tgz", + "integrity": "sha512-vYhM/a8fG34/Dl/Q9gfv5Ih3OFPgqeyn79S8FN+Xs/QZw6h6L8a1lDa3CyigyicOXLCmVIM7Fc9vFD4BGqgGLA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/aws-lambda": "^8.10.155" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-aws-sdk": { + "version": "0.67.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.67.0.tgz", + "integrity": "sha512-btpwJnZ2RBXDh/pTpfVpInpBu9Pedi+lbLKbt3naB344SggbbYnIdT7u8EzmGIApWi9EV91vw7hm896I7nESQA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.34.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-bunyan": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.57.0.tgz", + "integrity": "sha512-W4zLz1Y9ptCsdL+QMXR7xQaBHkJivLBmVlLCjUe23rX4V8E65fGAtlIJSKTKAfz4aEgtWgQAGMdkeqACwG0Caw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.212.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@types/bunyan": "1.8.11" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-cassandra-driver": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.57.0.tgz", + "integrity": "sha512-xLwrK+XnN32IB5i6t/a2j+SVdjlq/BIgjpVRkke4HAsKjoSMy1GeSI+ZOiJffRLFb4MojcvH4RG2+nEg1uC6Zg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.37.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.55.0.tgz", + "integrity": "sha512-UfGw7ubKKZBoTRjxi5KlfeECEaXZinS20RdRNlZE5tVF+O17hJOnrcGwAoQAHp6eYmxI2jW9IQ4t6450gnNF9g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.38" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-cucumber": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.28.0.tgz", + "integrity": "sha512-kim+bRxu4LZqKEyF2SgO01tgG88W+/iYltyP1XjT31FIXzlBjzQpwtSLLM8byayO85mcZIBha54WSNFDLM/7qQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.29.0.tgz", + "integrity": "sha512-220WjRb1G1UiAKbVblSMxwxxFdpyB4wj1XYIO9BJs5r62Azj2dL5fyZiXK3/WO6wB3uLul9R946iKI1bpPxktQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dns": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.55.0.tgz", + "integrity": "sha512-cfWLaFi22V+sQrKY7t6QroYzT3kO9m3PpkN1OXYmuCyfwxQaXOVlF8NSAHtua/RQYw0aQl+2fe6JOWyJdEZiwA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.60.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.60.0.tgz", + "integrity": "sha512-KghHCDqKq0D7iuPIVCuPSXut5WVAI6uwKcPrhwTUJL5VE2LC18id2vKoiAm1V8XvVlgIGAiECtEvbrFwkTCj3g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fastify": { + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.56.0.tgz", + "integrity": "sha512-zotOPoZsWtMF47BjottK23XaaBSmVuwG5D/R3FlGfAAwMNFoDR3IY1OGO9v9KfOU/1/xDVkxsQ22NFfu9lE8aA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.31.0.tgz", + "integrity": "sha512-C7tdXGDnkMgLVlE79VSekB+Y+P345zKUigvFMs5M7U0GIYA8ERx3FS0aAcY/ICIq9YwRmH2uuMb++Br5M2vNUg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.55.0.tgz", + "integrity": "sha512-7hWiyLbEX/dIS4LZy/h8VaAQPs8oBeEqsrysDWbos0b9PF414L6Rsbi2um/omtxIs+GTvsbuqDscWigeaxyWdA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.60.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.60.0.tgz", + "integrity": "sha512-XPATrmxAd2tFCsYbJ3eVIXt+gyvMKjc36QQuQxjtssMnAbw006Le9b5lKs7WXik7ItOpM1exATi1aDdOcCjRRg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-grpc": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.212.0.tgz", + "integrity": "sha512-r1t7LNKWVhSQMUrBdDJtooFmmLZ93kGuFixqeXPoUP8W+chJCxhey9l0c0+L3xriNdyB7TzvkKHhPXUDevgVEA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "0.212.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.58.0.tgz", + "integrity": "sha512-reuRApR2KHm2VsfyDgsrLhNE+IOy4uIU6n3oMjUleReHacEEZmf4vXxdt4/qcmJ6GoUXnRN2AOu3s5N3pMrgYA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.212.0.tgz", + "integrity": "sha512-t2nt16Uyv9irgR+tqnX96YeToOStc3X5js7Ljn3EKlI2b4Fe76VhMkTXtsTQ0aId6AsYgefrCRnXSCo/Fn/vww==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/instrumentation": "0.212.0", + "@opentelemetry/semantic-conventions": "^1.29.0", + "forwarded-parse": "2.1.2" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.60.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.60.0.tgz", + "integrity": "sha512-R+nnbPD9l2ruzu248qM3YDWzpdmWVaFFFv08lQqsc0EP4pT/B1GGUg06/tHOSo3L5njB2eejwyzpkvJkjaQEMA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/redis-common": "^0.38.2", + "@opentelemetry/semantic-conventions": "^1.33.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.21.0.tgz", + "integrity": "sha512-lkLrILnKGO7SHw1xPJnuGx2S4XwbKmQiJyzUGuEImRoU/6Gj0Nka0lkbeRd4ANN20dxr/mLdXIsUsk6DzTrX6A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.30.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.56.0.tgz", + "integrity": "sha512-pKqtY5lbAQ70MC5K/BJeAA1t2gAUlRBZBAJ5ergRUNs5jw8zbdOXEZOLztiuNvQqD2z4a9N0Tkde9JMFm2pKMQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.60.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.60.0.tgz", + "integrity": "sha512-UOmu2y2LHgPzKsm9xd0sCQJimr11YP4MKFc190Do1ufd8qds7Zd5BI3f6TudqYhH9dUIhojsQyUaS6K4nv5FsQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.36.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.56.0.tgz", + "integrity": "sha512-vXtOValhKRgWA9tLAiTU3P37Q31OveRuM2N5iLSVHl4GzkMBQ5p50A9kSKvt5gReL6BzFDXPCM9ItJiAhSS2KQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-memcached": { + "version": "0.55.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.55.0.tgz", + "integrity": "sha512-kdhW/j5X+vNCAvHVc50PZfvE7diUScg1ZkBaNFRygY3Z6IUjgPLR0luWQMDPSFun6AVo1HaMDPxbUqJrot6qrA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.0", + "@types/memcached": "^2.2.6" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.65.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.65.0.tgz", + "integrity": "sha512-hOAJRs5vrY7fZolSYUXmf29Y+HFDHWrek0DeLq82uwMPjPSda7h6oumQnqEX5olzw357q/QG39/uJdkclJ/JUg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.58.0.tgz", + "integrity": "sha512-3L0Fqo1y2oreISFPWaqdt/bg3NhLgrkn5U/E/9RNG1QaM81drTMBCHseMY1q8SlejjE43ZWOy+0KbmRBlUPJ+g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.58.0.tgz", + "integrity": "sha512-wZDrBCL3WfJclV6KywWVV3/B2ZiUYmDQdgyu3pq4jK/5qSfoDmezHzT/Nayln5MVVWMAGXIMLrCj8BKa6jaKQQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.0", + "@types/mysql": "2.15.27" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.58.0.tgz", + "integrity": "sha512-EubjV1XZb7XHrENqF7TW2lnah+KN0LddMneKNAB8PjGVKL5lJkVV/vhJ6EIcUNn9nCWmAwZ3GRcFVEDKCnyXfQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.0", + "@opentelemetry/sql-common": "^0.41.2" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-nestjs-core": { + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.58.0.tgz", + "integrity": "sha512-0lE9oW8j6nmvBHJoOxIQgKzMQQYNfX1nhiWZdXD0sNAMFsWBtvECWS7NAPSroKrEP53I04TcHCyyhcK4I9voXg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.30.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-net": { + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.56.0.tgz", + "integrity": "sha512-h69x7U6f86mP3gGWWTaMkQZk0K3tBvpVMIU7E0q2kkVw6eZ5TqFm9rkaEy38moQmixiDFQ9j/2/cwxG9P7ZEeA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-openai": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-openai/-/instrumentation-openai-0.10.0.tgz", + "integrity": "sha512-0lV2zxge2mMaruVCw/bmypWVu+aJ76rc0HBvAVFCPUI3zzJdgBZJZafGIHZ1IB2F6VvrDFL+JstEnle6V8brvA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.212.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.36.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-oracledb": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-oracledb/-/instrumentation-oracledb-0.37.0.tgz", + "integrity": "sha512-OzMghtAEAEkXlkUrZI4QcXSZq0MILeU6WC0/N5+1MSkuIkruIeaRw99/RtyS2of8vlPDa8XbbXl32Q1RM3wSyg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.34.0", + "@types/oracledb": "6.5.2" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.64.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.64.0.tgz", + "integrity": "sha512-NbfB/rlfsRI3zpTjnbvJv3qwuoGLsN8FxR/XoI+ZTn1Rs62x1IenO+TSSvk4NO+7FlXpd2MiOe8LT/oNbydHGA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.34.0", + "@opentelemetry/sql-common": "^0.41.2", + "@types/pg": "8.15.6", + "@types/pg-pool": "2.0.7" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pino": { + "version": "0.58.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.58.0.tgz", + "integrity": "sha512-rgy+tA7cDjuSq6dXAO40OiYP25azIDHMBtxG3RzSmCBVEYdjggl6btyuLVasX6VkOOhP2gf6PBuLMNxVwaIqAw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.212.0", + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis": { + "version": "0.60.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.60.0.tgz", + "integrity": "sha512-Ea/GffmmzIVHc9geaMjT94IR7poVZzIv4Kk/Lw0tbxGD3cBYcMUsLFVajKxpZsE1NRCECFpidAWeifCIKD0inw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/redis-common": "^0.38.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-restify": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.57.0.tgz", + "integrity": "sha512-kO6MsZFU+RdXOKhsKw8SOSBYGYCdFSlza+mpBQRl1DQmveZcnidchv4V5JQPtNgHxCGH+1n3hDpLdxdGUbJPNA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-router": { + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.56.0.tgz", + "integrity": "sha512-PHECDGQElLazI/QbHU16C5m9fDC7DGJk+jLIwO5ca6bcp7bXhUPPUTT78l7da2pDsrz4mhv5ytYNZmBbW/Q3rA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-runtime-node": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-runtime-node/-/instrumentation-runtime-node-0.25.0.tgz", + "integrity": "sha512-XaCmwBSui5KeTn8M6OzaEn1rEsNWtUkjuc1ylg0tqQTLHibNQ0n7f8v4zdF6x/nBV1OnsiYlN8RLHauGemv/TA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-socket.io": { + "version": "0.59.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.59.0.tgz", + "integrity": "sha512-71DnM/FEqH0PjvU2uZvzWJeaGyVIy3rJKk8rZrxg/aS2QT3qLGb+UPL/B+1vOw4pzDPn4papLTSMpLVF9G8uvw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.31.0.tgz", + "integrity": "sha512-HoF2EtcyP3JR4R3jLPHohZ9lFcj1QLJyGmFfLKDTvUUjPiFuK4XZ6L1OV9HhaqvN0xY+tWKfNdCPS3r33rd0Xw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.33.0", + "@types/tedious": "^4.0.14" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.22.0.tgz", + "integrity": "sha512-yb6vEWUPOrD5i7yR1XceEEqiVHbMgr5YnUPnom5eQVCjvrTkEVswyrf9i+vvJR+28wrNqILIIphWgOOx6BjnTQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.212.0", + "@opentelemetry/semantic-conventions": "^1.24.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/instrumentation-winston": { + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.56.0.tgz", + "integrity": "sha512-ITIA0Qe61CQ6FQU/bN23pNBvJ+5U0ofoASMOOYrODtXyV9wI267AigNTTwDmv2Myt8dPEFvvVFJZKhiZLIpehA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "^0.212.0", + "@opentelemetry/instrumentation": "^0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.212.0.tgz", + "integrity": "sha512-HoMv5pQlzbuxiMS0hN7oiUtg8RsJR5T7EhZccumIWxYfNo/f4wFc7LPDfFK6oHdG2JF/+qTocfqIHoom+7kLpw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-transformer": "0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.212.0.tgz", + "integrity": "sha512-YidOSlzpsun9uw0iyIWrQp6HxpMtBlECE3tiHGAsnpEqJWbAUWcMnIffvIuvTtTQ1OyRtwwaE79dWSQ8+eiB7g==", + "license": "Apache-2.0", + "dependencies": { + "@grpc/grpc-js": "^1.14.3", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/otlp-exporter-base": "0.212.0", + "@opentelemetry/otlp-transformer": "0.212.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.212.0.tgz", + "integrity": "sha512-bj7zYFOg6Db7NUwsRZQ/WoVXpAf41WY2gsd3kShSfdpZQDRKHWJiRZIg7A8HvWsf97wb05rMFzPbmSHyjEl9tw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.212.0", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-logs": "0.212.0", + "@opentelemetry/sdk-metrics": "2.5.1", + "@opentelemetry/sdk-trace-base": "2.5.1", + "protobufjs": "8.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/propagator-b3": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-2.5.1.tgz", + "integrity": "sha512-AU6sZgunZrZv/LTeHP+9IQsSSH5p3PtOfDPe8VTdwYH69nZCfvvvXehhzu+9fMW2mgJMh5RVpiH8M9xuYOu5Dg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-jaeger": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-2.5.1.tgz", + "integrity": "sha512-8+SB94/aSIOVGDUPRFSBRHVUm2A8ye1vC6/qcf/D+TF4qat7PC6rbJhRxiUGDXZtMtKEPM/glgv5cBGSJQymSg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.38.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz", + "integrity": "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + } + }, + "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { + "version": "0.33.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.33.2.tgz", + "integrity": "sha512-EaS54zwYmOg9Ttc79juaktpCBYqyh2IquXl534sLls+c1/pc8LZfWPMqytFt+iBvSPQ6ajraUnvi6cun4AhSjQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-aws": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-2.12.0.tgz", + "integrity": "sha512-VelueKblsnQEiBVqEYcvM9VEb+B8zN6nftltdO9HAD7qi/OlicP4z/UGJ9EeW2m++WabdMoj0G3QVL8YV0P9tw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-azure": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.20.0.tgz", + "integrity": "sha512-iRy+O2cB6DOlQ/OONaK+L8Cp8nLS89dZVRp6KgnFAfzykXuq9Ws/ygJKcU3CCmjkgY5j2Vk3uVTre/E35bWhYg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/semantic-conventions": "^1.37.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-container": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.8.3.tgz", + "integrity": "sha512-5J0JP2cy655rBKM9Doz26ffO3rG+Xqm7OXeNXkckzmc3JmL6Bj3dPBKugPYsfemhEIqtf7INH9UmPQqTMuWoHg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resource-detector-gcp": { + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.47.0.tgz", + "integrity": "sha512-57T/kRVdU0ch1P4KPEkmU2b5mWNlUs8hHgqrBYVF+fNZMc1jMdL1mANZhEzoLtWKIeoCEy+57Itt7RkXAYNJiQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/resources": "^2.0.0", + "gcp-metadata": "^8.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.5.1.tgz", + "integrity": "sha512-BViBCdE/GuXRlp9k7nS1w6wJvY5fnFX5XvuEtWsTAOQFIO89Eru7lGW3WbfbxtCuZ/GbrJfAziXG0w0dpxL7eQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.212.0.tgz", + "integrity": "sha512-qglb5cqTf0mOC1sDdZ7nfrPjgmAqs2OxkzOPIf2+Rqx8yKBK0pS7wRtB1xH30rqahBIut9QJDbDePyvtyqvH/Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.212.0", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/resources": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-2.5.1.tgz", + "integrity": "sha512-RKMn3QKi8nE71ULUo0g/MBvq1N4icEBo7cQSKnL3URZT16/YH3nSVgWegOjwx7FRBTrjOIkMJkCUn/ZFIEfn4A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/resources": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.9.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-node": { + "version": "0.212.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.212.0.tgz", + "integrity": "sha512-tJzVDk4Lo44MdgJLlP+gdYdMnjxSNsjC/IiTxj5CFSnsjzpHXwifgl3BpUX67Ty3KcdubNVfedeBc/TlqHXwwg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.212.0", + "@opentelemetry/configuration": "0.212.0", + "@opentelemetry/context-async-hooks": "2.5.1", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/exporter-logs-otlp-grpc": "0.212.0", + "@opentelemetry/exporter-logs-otlp-http": "0.212.0", + "@opentelemetry/exporter-logs-otlp-proto": "0.212.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "0.212.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.212.0", + "@opentelemetry/exporter-metrics-otlp-proto": "0.212.0", + "@opentelemetry/exporter-prometheus": "0.212.0", + "@opentelemetry/exporter-trace-otlp-grpc": "0.212.0", + "@opentelemetry/exporter-trace-otlp-http": "0.212.0", + "@opentelemetry/exporter-trace-otlp-proto": "0.212.0", + "@opentelemetry/exporter-zipkin": "2.5.1", + "@opentelemetry/instrumentation": "0.212.0", + "@opentelemetry/propagator-b3": "2.5.1", + "@opentelemetry/propagator-jaeger": "2.5.1", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/sdk-logs": "0.212.0", + "@opentelemetry/sdk-metrics": "2.5.1", + "@opentelemetry/sdk-trace-base": "2.5.1", + "@opentelemetry/sdk-trace-node": "2.5.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.5.1.tgz", + "integrity": "sha512-iZH3Gw8cxQn0gjpOjJMmKLd9GIaNh/E3v3ST67vyzLSxHBs14HsG4dy7jMYyC5WXGdBVEcM7U/XTF5hCQxjDMw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.1", + "@opentelemetry/resources": "2.5.1", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-2.5.1.tgz", + "integrity": "sha512-9lopQ6ZoElETOEN0csgmtEV5/9C7BMfA7VtF4Jape3i954b6sTY2k3Xw3CxUTKreDck/vpAuJM+EDo4zheUw+A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "2.5.1", + "@opentelemetry/core": "2.5.1", + "@opentelemetry/sdk-trace-base": "2.5.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.40.0.tgz", + "integrity": "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.41.2.tgz", + "integrity": "sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.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==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@traceloop/ai-semantic-conventions": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@traceloop/ai-semantic-conventions/-/ai-semantic-conventions-0.20.0.tgz", + "integrity": "sha512-bvivhZU6U8TW4TKktYnjdTi+7GE4WxI8epaGjawalSKDunmxaA+4UVFQ+4tSCBvp2Scby+gnYNaTZSrtABfOlQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.9.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@traceloop/instrumentation-anthropic": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@traceloop/instrumentation-anthropic/-/instrumentation-anthropic-0.20.0.tgz", + "integrity": "sha512-xQcPxVrKr3yT9+ZEM3skYXikJc/ocZlGDIcsBQ3mMwL3Weq1QL7jx/uGLXvrSO2Yh0DWUjWI6Q/oiRCEUM6P8w==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/core": "^2.0.1", + "@opentelemetry/instrumentation": "^0.203.0", + "@opentelemetry/semantic-conventions": "^1.36.0", + "@traceloop/ai-semantic-conventions": "0.20.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@traceloop/instrumentation-anthropic/node_modules/@opentelemetry/api-logs": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz", + "integrity": "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@traceloop/instrumentation-anthropic/node_modules/@opentelemetry/instrumentation": { + "version": "0.203.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz", + "integrity": "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.203.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@traceloop/instrumentation-anthropic/node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT" + }, + "node_modules/@traceloop/instrumentation-anthropic/node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/@traceloop/instrumentation-anthropic/node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@types/aws-lambda": { + "version": "8.10.161", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.161.tgz", + "integrity": "sha512-rUYdp+MQwSFocxIOcSsYSF3YYYC/uUpMbCY/mbO21vGqfrEYvNSoPyKYDj6RhXXpPfS0KstW9RwG3qXh9sL7FQ==", + "license": "MIT" + }, + "node_modules/@types/bunyan": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.11.tgz", + "integrity": "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/memcached": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", + "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", + "license": "MIT", + "dependencies": { + "@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/mysql": { + "version": "2.15.27", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.27.tgz", + "integrity": "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.19.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.13.tgz", + "integrity": "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/oracledb": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@types/oracledb/-/oracledb-6.5.2.tgz", + "integrity": "sha512-kK1eBS/Adeyis+3OlBDMeQQuasIDLUYXsi2T15ccNJ0iyUpQ4xDF7svFu3+bGVrI0CMBUclPciz+lsQR3JX3TQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/pg": { + "version": "8.15.6", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.6.tgz", + "integrity": "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/pg-pool": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.7.tgz", + "integrity": "sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==", + "license": "MIT", + "dependencies": { + "@types/pg": "*" + } + }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@vercel/oidc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.1.0.tgz", + "integrity": "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ai": { + "version": "6.0.105", + "resolved": "https://registry.npmjs.org/ai/-/ai-6.0.105.tgz", + "integrity": "sha512-rp+exWtZS3J0DDvZIfetpKCIg7D3cCsvBPoFN3I67IDTs9aoBZDbpecoIkmNLT+U9RBkoEial3OGHRvme23HCw==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/gateway": "3.0.59", + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.16", + "@opentelemetry/api": "1.9.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/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/bcryptjs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.3.tgz", + "integrity": "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g==", + "license": "BSD-3-Clause", + "bin": { + "bcrypt": "bin/bcrypt" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/canonicalize": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz", + "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", + "license": "Apache-2.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==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz", + "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "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/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dotenv": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", + "integrity": "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/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-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz", + "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==", + "license": "MIT", + "dependencies": { + "ip-address": "10.0.1" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/express/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "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/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.3.tgz", + "integrity": "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2", + "rimraf": "^5.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "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==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/helmet": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz", + "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/import-in-the-middle": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-2.0.6.tgz", + "integrity": "sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.15.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^2.2.0", + "module-details-from-path": "^1.0.4" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/inngest": { + "version": "3.52.4", + "resolved": "https://registry.npmjs.org/inngest/-/inngest-3.52.4.tgz", + "integrity": "sha512-wqDWtzbu5+SiUcUJ2qTiJOMg7dL14i8CE5NfKQIW6Izp7vOWC/SE83azwuzUznjnW9DnKBMIpoldj+VhTeDE5Q==", + "license": "Apache-2.0", + "dependencies": { + "@bufbuild/protobuf": "^2.2.3", + "@inngest/ai": "^0.1.3", + "@jpwilliams/waitgroup": "^2.1.1", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/auto-instrumentations-node": ">=0.66.0 <1.0.0", + "@opentelemetry/context-async-hooks": ">=2.0.0 <3.0.0", + "@opentelemetry/exporter-trace-otlp-http": ">=0.200.0 <0.300.0", + "@opentelemetry/instrumentation": ">=0.200.0 <0.300.0", + "@opentelemetry/resources": ">=2.0.0 <3.0.0", + "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0", + "@standard-schema/spec": "^1.0.0", + "@traceloop/instrumentation-anthropic": "^0.20.0", + "@types/debug": "^4.1.12", + "@types/ms": "~2.1.0", + "canonicalize": "^1.0.8", + "chalk": "^4.1.2", + "cross-fetch": "^4.0.0", + "debug": "^4.3.4", + "hash.js": "^1.1.7", + "json-stringify-safe": "^5.0.1", + "ms": "^2.1.3", + "serialize-error-cjs": "^0.1.3", + "strip-ansi": "^5.2.0", + "temporal-polyfill": "^0.2.5", + "ulid": "^2.3.0", + "zod": "^3.25.0" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@sveltejs/kit": ">=1.27.3", + "@vercel/node": ">=2.15.9", + "aws-lambda": ">=1.0.7", + "express": ">=4.19.2", + "fastify": ">=4.21.0", + "h3": ">=1.8.1", + "hono": ">=4.2.7", + "koa": ">=2.14.2", + "next": ">=12.0.0", + "typescript": ">=5.8.0", + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "@sveltejs/kit": { + "optional": true + }, + "@vercel/node": { + "optional": true + }, + "aws-lambda": { + "optional": true + }, + "express": { + "optional": true + }, + "fastify": { + "optional": true + }, + "h3": { + "optional": true + }, + "hono": { + "optional": true + }, + "koa": { + "optional": true + }, + "next": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/inngest/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/ip-address": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-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-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC" + }, + "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/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/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "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.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/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "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==", + "license": "ISC" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "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==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nodemon": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz", + "integrity": "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^10.2.1", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "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==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/pg": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.19.0.tgz", + "integrity": "sha512-QIcLGi508BAHkQ3pJNptsFz5WQMlpGbuBGBaIaXsWK8mel2kQ/rThYI+DbgjUvZrIr7MiuEuc9LcChJoEZK1xQ==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.11.0", + "pg-pool": "^3.12.0", + "pg-protocol": "^1.12.0", + "pg-types": "2.2.0", + "pgpass": "1.0.5" + }, + "engines": { + "node": ">= 16.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.3.0" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz", + "integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==", + "license": "MIT", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.11.0.tgz", + "integrity": "sha512-kecgoJwhOpxYU21rZjULrmrBJ698U2RxXofKVzOn5UDj61BPj/qMb7diYUR1nLScCDbrztQFl1TaQZT0t1EtzQ==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.12.0.tgz", + "integrity": "sha512-eIJ0DES8BLaziFHW7VgJEBPi5hg3Nyng5iKpYtj3wbcAUV9A1wLgWiY7ajf/f/oO1wfxt83phXPY8Emztg7ITg==", + "license": "MIT", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.12.0.tgz", + "integrity": "sha512-uOANXNRACNdElMXJ0tPz6RBM0XQ61nONGAwlt8da5zs/iUOOCLBQOHSXnrC6fMsvtjxbOJrZZl5IScGv+7mpbg==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", + "dependencies": { + "split2": "^4.1.0" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz", + "integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/protobufjs": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-8.0.0.tgz", + "integrity": "sha512-jx6+sE9h/UryaCZhsJWbJtTEy47yXoGNYI4z8ZaRncM0zBKeRqjO2JEcOUYwrYGb1WLhXM1FfMzW3annvFv0rw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-8.0.1.tgz", + "integrity": "sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3" + }, + "engines": { + "node": ">=9.3.0 || >=8.10.0 <9.0.0" + } + }, + "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/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "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/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "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/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serialize-error-cjs": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/serialize-error-cjs/-/serialize-error-cjs-0.1.4.tgz", + "integrity": "sha512-6a6dNqipzbCPlTFgztfNP2oG+IGcflMe/01zSzGrQcxGMKbIjOemBBD85pH92klWaJavAUWxAh9Z0aU28zxW6A==", + "deprecated": "Rolling release, please update to 0.2.0", + "license": "MIT-0", + "funding": { + "url": "https://github.com/sponsors/finwo" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/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==", + "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==", + "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==", + "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==", + "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==", + "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==", + "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==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "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==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/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/temporal-polyfill": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.2.5.tgz", + "integrity": "sha512-ye47xp8Cb0nDguAhrrDS1JT1SzwEV9e26sSsrWzVu+yPZ7LzceEcH0i2gci9jWfOfSCCgM3Qv5nOYShVUUFUXA==", + "license": "MIT", + "dependencies": { + "temporal-spec": "^0.2.4" + } + }, + "node_modules/temporal-spec": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.2.4.tgz", + "integrity": "sha512-lDMFv4nKQrSjlkHKAlHVqKrBG4DyFfa9F74cmBZ3Iy3ed8yvWnlWSIdi4IKfSqwmazAohBNwiN64qGx4y5Q3IQ==", + "license": "ISC" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", + "license": "MIT" + }, + "node_modules/touch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, + "license": "ISC", + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/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/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ulid": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.4.0.tgz", + "integrity": "sha512-fIRiVTJNcSRmXKPZtGzFQv9WRrZ3M9eoptl/teFJvjOzmpU+/K/JH6HZ8deBfb5vMEpicJcLn7JmvdknlMq7Zg==", + "license": "MIT", + "bin": { + "ulid": "bin/cli.js" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, + "license": "MIT" + }, + "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/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, + "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==", + "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==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "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==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.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==", + "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==", + "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==", + "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==", + "license": "ISC" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/nodebase_backend/package.json b/nodebase_backend/package.json new file mode 100644 index 0000000..c345d7c --- /dev/null +++ b/nodebase_backend/package.json @@ -0,0 +1,40 @@ +{ + "name": "nodebase_backend", + "version": "1.0.0", + "description": "Nodebase backend API server", + "main": "src/server.js", + "type": "module", + "scripts": { + "dev": "nodemon src/server.js", + "start": "node src/server.js", + "db:migrate": "node src/scripts/migrate.js", + "inngest:dev": "npx inngest-cli@latest dev -u http://localhost:4000/api/inngest" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@ai-sdk/anthropic": "^3.0.50", + "@ai-sdk/google": "^3.0.34", + "@ai-sdk/openai": "^3.0.37", + "ai": "^6.0.105", + "bcryptjs": "^3.0.3", + "cookie-parser": "^1.4.7", + "cors": "^2.8.6", + "dotenv": "^17.3.1", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "handlebars": "^4.7.8", + "helmet": "^8.1.0", + "html-entities": "^2.6.0", + "inngest": "^3.52.4", + "jsonwebtoken": "^9.0.3", + "pg": "^8.19.0", + "toposort": "^2.0.2", + "uuid": "^13.0.0", + "zod": "^4.3.6" + }, + "devDependencies": { + "nodemon": "^3.1.14" + } +} diff --git a/prisma/schema.prisma b/nodebase_backend/schema.prisma similarity index 100% rename from prisma/schema.prisma rename to nodebase_backend/schema.prisma diff --git a/nodebase_backend/src/app.js b/nodebase_backend/src/app.js new file mode 100644 index 0000000..0aa7413 --- /dev/null +++ b/nodebase_backend/src/app.js @@ -0,0 +1,111 @@ +import express from "express"; +import cors from "cors"; +import helmet from "helmet"; +import cookieParser from "cookie-parser"; +import rateLimit from "express-rate-limit"; +import env from "./config/env.js"; + +// Middleware +import requestLogger from "./middleware/request-logger.js"; +import notFound from "./middleware/not-found.js"; +import errorHandler from "./middleware/error-handler.js"; + +// Module routers +import authRoutes from "./modules/auth/auth.routes.js"; +import usersRoutes from "./modules/users/users.routes.js"; +import workflowsRoutes from "./modules/workflows/workflows.routes.js"; +import nodesRoutes from "./modules/nodes/nodes.routes.js"; +import connectionsRoutes from "./modules/connections/connections.routes.js"; +import credentialsRoutes from "./modules/credentials/credentials.routes.js"; +import executionsRoutes from "./modules/executions/executions.routes.js"; +import webhooksRoutes from "./modules/webhooks/webhooks.routes.js"; +import { inngestServe } from "./inngest/serve.js"; + +const app = express(); + +// ─── Global middleware + +// Security headers +app.use(helmet()); + +// CORS +app.use( + cors({ + origin: env.CLIENT_URL, + credentials: true, + }), +); + +// Body parsing +app.use(express.json({ limit: "1mb" })); +app.use(express.urlencoded({ extended: true })); + +// Cookie parsing +app.use(cookieParser()); + +// HTTP request & response logging (replaces morgan) +app.use(requestLogger); + +// ─── Rate limiting + +// Global rate limiter +const globalLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100, + standardHeaders: true, + legacyHeaders: false, + message: { + success: false, + message: "Too many requests, please try again later.", + }, +}); +app.use(globalLimiter); + +// Stricter limiter for auth routes +const authLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, + max: 20, + standardHeaders: true, + legacyHeaders: false, + message: { + success: false, + message: "Too many authentication attempts, please try again later.", + }, +}); + +// ─── Routes ─────── + +// Health & root +app.get("/", (_req, res) => { + res.json({ message: "Nodebase API", version: "1.0.0" }); +}); + +app.get("/health", (_req, res) => { + res.json({ + status: "ok", + uptime: process.uptime(), + timestamp: new Date().toISOString(), + }); +}); + +// Webhook routes (no auth — called by external services like Google Forms, Stripe) +app.use("/api/webhooks", webhooksRoutes); + +// Module routes +app.use("/api/auth", authLimiter, authRoutes); +app.use("/api/users", usersRoutes); +app.use("/api/workflows", workflowsRoutes); +app.use("/api/nodes", nodesRoutes); +app.use("/api/connections", connectionsRoutes); +app.use("/api/credentials", credentialsRoutes); +app.use("/api/executions", executionsRoutes); + +// Inngest webhook endpoint +app.use("/api/inngest", inngestServe); + +// ─── Error handling and 404 + +app.use(notFound); +app.use(errorHandler); + +export default app; diff --git a/nodebase_backend/src/config/constants.js b/nodebase_backend/src/config/constants.js new file mode 100644 index 0000000..4a0de0b --- /dev/null +++ b/nodebase_backend/src/config/constants.js @@ -0,0 +1,35 @@ +// ─── Enums (must match database enum types) ─── + +export const NodeType = Object.freeze({ + INITIAL: "INITIAL", + MANUAL_TRIGGER: "MANUAL_TRIGGER", + HTTP_REQUEST: "HTTP_REQUEST", + GOOGLE_FORM_TRIGGER: "GOOGLE_FORM_TRIGGER", + STRIPE_TRIGGER: "STRIPE_TRIGGER", + ANTHROPIC: "ANTHROPIC", + GEMINI: "GEMINI", + OPENAI: "OPENAI", + DISCORD: "DISCORD", + SLACK: "SLACK", +}); + +export const CredentialType = Object.freeze({ + OPENAI: "OPENAI", + ANTHROPIC: "ANTHROPIC", + GEMINI: "GEMINI", +}); + +export const ExecutionStatus = Object.freeze({ + RUNNING: "RUNNING", + SUCCESS: "SUCCESS", + FAILED: "FAILED", +}); + +// ─── Pagination defaults ─── + +export const PAGINATION = Object.freeze({ + DEFAULT_PAGE: 1, + DEFAULT_PAGE_SIZE: 10, + MAX_PAGE_SIZE: 100, + MIN_PAGE_SIZE: 1, +}); diff --git a/nodebase_backend/src/config/db.js b/nodebase_backend/src/config/db.js new file mode 100644 index 0000000..833578e --- /dev/null +++ b/nodebase_backend/src/config/db.js @@ -0,0 +1,34 @@ +import pg from "pg"; +import env from "./env.js"; + +const { Pool } = pg; + +const pool = new Pool({ + connectionString: env.DATABASE_URL, + ssl: { rejectUnauthorized: false }, + max: 20, + idleTimeoutMillis: 30000, + connectionTimeoutMillis: 5000, +}); + +pool.on("error", (err) => { + console.error("Unexpected error on idle database client:", err); + process.exit(-1); +}); + +/** + * Execute a single query. + * @param {string} text SQL query string + * @param {any[]} params Parameterised values + * @returns {Promise} + */ +export const query = (text, params) => pool.query(text, params); + +/** + * Get a client from the pool for transactions. + * Always release the client in a finally block. + * @returns {Promise} + */ +export const getClient = () => pool.connect(); + +export default pool; diff --git a/nodebase_backend/src/config/env.js b/nodebase_backend/src/config/env.js new file mode 100644 index 0000000..c9b9ed7 --- /dev/null +++ b/nodebase_backend/src/config/env.js @@ -0,0 +1,46 @@ +import dotenv from "dotenv"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); + +const env = { + PORT: parseInt(process.env.PORT, 10) || 4000, + NODE_ENV: process.env.NODE_ENV || "development", + + // Database + DATABASE_URL: process.env.DATABASE_URL, + + // JWT + JWT_SECRET: process.env.JWT_SECRET, + JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || "7d", + + // Encryption + ENCRYPTION_KEY: process.env.ENCRYPTION_KEY, + + // CORS + CLIENT_URL: process.env.CLIENT_URL || "http://localhost:3000", + + // Inngest + INNGEST_EVENT_KEY: process.env.INNGEST_EVENT_KEY, + + get isDev() { + return this.NODE_ENV === "development"; + }, + get isProd() { + return this.NODE_ENV === "production"; + }, +}; + +// Validate critical env vars at startup +const required = ["DATABASE_URL", "JWT_SECRET", "ENCRYPTION_KEY", "INNGEST_EVENT_KEY"]; +for (const key of required) { + if (!env[key]) { + console.warn(`Warning: Environment variable ${key} is not set.`); + } +} + +export default env; diff --git a/nodebase_backend/src/engine/runner.js b/nodebase_backend/src/engine/runner.js new file mode 100644 index 0000000..b448e5b --- /dev/null +++ b/nodebase_backend/src/engine/runner.js @@ -0,0 +1,70 @@ +import { buildExecutionOrder } from "./toposort.js"; +import { resolveTemplates } from "./template.js"; +import { getExecutorForType } from "../inngest/executors/index.js"; +import logger from "../utils/logger.js"; + +/** + * Run a workflow to completion, executing each node in topological order. + * + * @param {object} opts + * @param {object} opts.workflow – { id, nodes, connections } + * @param {object} opts.credentials – { [nodeId]: decryptedCredentialValue } + * @param {Function} opts.onNodeStart – (nodeId) => void + * @param {Function} opts.onNodeComplete – (nodeId, output) => void + * @param {Function} opts.onNodeError – (nodeId, error) => void + * @returns {object} – final context with all node outputs + */ +export const runWorkflow = async ({ + workflow, + credentials, + triggerPayload = {}, + onNodeStart, + onNodeComplete, + onNodeError, +}) => { + const { nodes, connections } = workflow; + const orderedIds = buildExecutionOrder(nodes, connections); + + // Lookup map: nodeId → node row + const nodeMap = Object.fromEntries(nodes.map((n) => [n.id, n])); + + // Execution context accumulates outputs keyed by node ID + const context = { nodes: {} }; + + for (const nodeId of orderedIds) { + const node = nodeMap[nodeId]; + if (!node) continue; + + // Skip the INITIAL placeholder node — it carries no logic + if (node.type === "INITIAL") continue; + + await onNodeStart?.(nodeId); + + try { + // Resolve {{template}} placeholders in node.data using prior outputs + const resolvedData = resolveTemplates(node.data ?? {}, context); + + const executor = getExecutorForType(node.type); + + const output = await executor({ + node: { ...node, data: resolvedData }, + credential: credentials[nodeId] ?? null, + context, + triggerPayload, + }); + + context.nodes[nodeId] = { output }; + await onNodeComplete?.(nodeId, output); + } catch (err) { + logger.error(`Node ${nodeId} (${node.type}) failed`, { + error: err.message, + }); + await onNodeError?.(nodeId, err); + + // Abort the rest of the workflow on first failure + throw err; + } + } + + return context; +}; diff --git a/nodebase_backend/src/engine/template.js b/nodebase_backend/src/engine/template.js new file mode 100644 index 0000000..8d570d3 --- /dev/null +++ b/nodebase_backend/src/engine/template.js @@ -0,0 +1,59 @@ +import Handlebars from "handlebars"; +import { decode } from "html-entities"; + +// ── Register custom helpers + +/** Serialize a value to a JSON string: {{json someObject}} */ +Handlebars.registerHelper("json", (context) => { + return JSON.stringify(context, null, 2); +}); + +/** URI-encode a string: {{encodeURI value}} */ +Handlebars.registerHelper("encodeURI", (str) => { + return encodeURIComponent(String(str ?? "")); +}); + +/** Equality check: {{#eq a b}}...{{/eq}} */ +Handlebars.registerHelper("eq", (a, b) => a === b); + +/** + * Resolve Handlebars `{{expressions}}` inside a node's `data` object. + * + * Works recursively on strings, arrays, and plain objects so that any + * string field in data can reference previous node outputs, e.g.: + * + * "prompt": "Summarise this: {{nodes.abc123.output.text}}" + * + * The context supplied should be the current workflow execution context + * containing `{ nodes: { [nodeId]: { output: ... } } }`. + * + * HTML-entities are decoded after template resolution so that values + * serialised through JSON round-trips are safe. + * + * @param {*} value – any value (string, object, array, primitive) + * @param {object} ctx – template context (e.g. { nodes: { ... } }) + * @returns {*} – resolved value with the same shape + */ +export const resolveTemplates = (value, ctx) => { + if (typeof value === "string") { + // Only compile if there's actually a placeholder + if (!value.includes("{{")) return value; + const template = Handlebars.compile(value, { noEscape: true }); + return decode(template(ctx)); + } + + if (Array.isArray(value)) { + return value.map((item) => resolveTemplates(item, ctx)); + } + + if (value !== null && typeof value === "object") { + const resolved = {}; + for (const [k, v] of Object.entries(value)) { + resolved[k] = resolveTemplates(v, ctx); + } + return resolved; + } + + // numbers, booleans, null — pass through + return value; +}; diff --git a/nodebase_backend/src/engine/toposort.js b/nodebase_backend/src/engine/toposort.js new file mode 100644 index 0000000..2c047da --- /dev/null +++ b/nodebase_backend/src/engine/toposort.js @@ -0,0 +1,22 @@ +import toposort from "toposort"; + +/** + * Build an execution-order array from nodes + connections. + * + * @param {Array} nodes – rows from the "node" table + * @param {Array} connections – rows from the "connection" table + * @returns {string[]} – ordered node IDs (trigger first → leaf last) + */ +export const buildExecutionOrder = (nodes, connections) => { + const nodeIds = new Set(nodes.map((n) => n.id)); + + // Build edge list for toposort: [from, to] + const edges = connections + .filter((c) => nodeIds.has(c.from_node_id) && nodeIds.has(c.to_node_id)) + .map((c) => [c.from_node_id, c.to_node_id]); + + // toposort returns an array from sources → sinks + const sorted = toposort.array([...nodeIds], edges); + + return sorted; +}; diff --git a/nodebase_backend/src/inngest/client.js b/nodebase_backend/src/inngest/client.js new file mode 100644 index 0000000..0f8d3ef --- /dev/null +++ b/nodebase_backend/src/inngest/client.js @@ -0,0 +1,9 @@ +import { Inngest } from "inngest"; +import env from "../config/env.js"; + +export const inngest = new Inngest({ + id: "nodebase", + // In development, use the Dev Server (no event key needed). + // In production, set INNGEST_EVENT_KEY in your environment. + ...(env.isDev ? { isDev: true } : { eventKey: process.env.INNGEST_EVENT_KEY }), +}); diff --git a/nodebase_backend/src/inngest/executors/anthropic.js b/nodebase_backend/src/inngest/executors/anthropic.js new file mode 100644 index 0000000..4c7bea4 --- /dev/null +++ b/nodebase_backend/src/inngest/executors/anthropic.js @@ -0,0 +1,60 @@ +import { generateText } from "ai"; +import { createAnthropic } from "@ai-sdk/anthropic"; +import logger from "../../utils/logger.js"; + +/** + * Anthropic executor — uses the Vercel AI SDK's `generateText`. + * + * Expected node.data shape: + * { + * model?: string (default "claude-sonnet-4-20250514"), + * userPrompt: string, (or legacy `prompt`) + * systemPrompt?: string, + * temperature?: number, + * maxTokens?: number, + * } + * + * credential: the user's decrypted Anthropic API key string. + */ +export const executeAnthropic = async ({ node, credential }) => { + if (!credential) + throw new Error("Anthropic node requires an API key credential."); + + const { + model = "claude-sonnet-4-20250514", + userPrompt, + prompt, + systemPrompt, + temperature, + maxTokens, + } = node.data; + + // Accept userPrompt (from frontend dialog) or legacy prompt field + const resolvedPrompt = userPrompt || prompt; + if (!resolvedPrompt) + throw new Error("Anthropic node requires a user prompt in data."); + + const anthropic = createAnthropic({ apiKey: credential }); + + logger.debug("Anthropic generateText", { model }); + + // Build messages array for proper system + user prompt handling + const messages = []; + if (systemPrompt) { + messages.push({ role: "system", content: systemPrompt }); + } + messages.push({ role: "user", content: resolvedPrompt }); + + const result = await generateText({ + model: anthropic(model), + messages, + temperature, + maxTokens, + }); + + return { + text: result.text, + usage: result.usage, + model, + }; +}; diff --git a/nodebase_backend/src/inngest/executors/discord.js b/nodebase_backend/src/inngest/executors/discord.js new file mode 100644 index 0000000..a4d5ce7 --- /dev/null +++ b/nodebase_backend/src/inngest/executors/discord.js @@ -0,0 +1,41 @@ +import logger from "../../utils/logger.js"; + +/** + * Discord executor — sends a message to a Discord webhook URL. + * + * Expected node.data shape: + * { + * webhookUrl: string, + * content: string, + * username?: string, + * avatarUrl?: string, + * } + */ +export const executeDiscord = async ({ node }) => { + const { webhookUrl, content, username, avatarUrl } = node.data; + + if (!webhookUrl) + throw new Error("Discord node requires a `webhookUrl` in data."); + if (!content) throw new Error("Discord node requires `content` in data."); + + const payload = { content }; + if (username) payload.username = username; + if (avatarUrl) payload.avatar_url = avatarUrl; + + logger.debug("Discord webhook", { + webhookUrl: webhookUrl.slice(0, 40) + "...", + }); + + const response = await fetch(webhookUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + + if (!response.ok) { + const text = await response.text(); + throw new Error(`Discord webhook failed (${response.status}): ${text}`); + } + + return { sent: true, status: response.status }; +}; diff --git a/nodebase_backend/src/inngest/executors/gemini.js b/nodebase_backend/src/inngest/executors/gemini.js new file mode 100644 index 0000000..8751af8 --- /dev/null +++ b/nodebase_backend/src/inngest/executors/gemini.js @@ -0,0 +1,60 @@ +import { generateText } from "ai"; +import { createGoogleGenerativeAI } from "@ai-sdk/google"; +import logger from "../../utils/logger.js"; + +/** + * Gemini executor — uses the Vercel AI SDK's `generateText`. + * + * Expected node.data shape: + * { + * model?: string (default "gemini-2.5-flash"), + * userPrompt: string, (or legacy `prompt`) + * systemPrompt?: string, + * temperature?: number, + * maxTokens?: number, + * } + * + * credential: the user's decrypted Google AI API key string. + */ +export const executeGemini = async ({ node, credential }) => { + if (!credential) + throw new Error("Gemini node requires an API key credential."); + + const { + model = "gemini-2.5-flash", + userPrompt, + prompt, + systemPrompt, + temperature, + maxTokens, + } = node.data; + + // Accept userPrompt (from frontend dialog) or legacy prompt field + const resolvedPrompt = userPrompt || prompt; + if (!resolvedPrompt) + throw new Error("Gemini node requires a user prompt in data."); + + const google = createGoogleGenerativeAI({ apiKey: credential }); + + logger.debug("Gemini generateText", { model }); + + // Build messages array for proper system + user prompt handling + const messages = []; + if (systemPrompt) { + messages.push({ role: "system", content: systemPrompt }); + } + messages.push({ role: "user", content: resolvedPrompt }); + + const result = await generateText({ + model: google(model), + messages, + temperature, + maxTokens, + }); + + return { + text: result.text, + usage: result.usage, + model, + }; +}; diff --git a/nodebase_backend/src/inngest/executors/google-form-trigger.js b/nodebase_backend/src/inngest/executors/google-form-trigger.js new file mode 100644 index 0000000..350e6b2 --- /dev/null +++ b/nodebase_backend/src/inngest/executors/google-form-trigger.js @@ -0,0 +1,13 @@ +/** + * Google Form trigger executor — passes through the webhook payload. + */ +export const executeGoogleFormTrigger = async ({ node, triggerPayload }) => { + return { + triggered: true, + nodeId: node.id, + type: node.type, + payload: triggerPayload?.formData ?? node.data?.payload ?? {}, + source: triggerPayload?.source ?? "manual", + receivedAt: triggerPayload?.receivedAt ?? new Date().toISOString(), + }; +}; diff --git a/nodebase_backend/src/inngest/executors/http-request.js b/nodebase_backend/src/inngest/executors/http-request.js new file mode 100644 index 0000000..b564316 --- /dev/null +++ b/nodebase_backend/src/inngest/executors/http-request.js @@ -0,0 +1,61 @@ +import logger from "../../utils/logger.js"; + +/** + * HTTP Request executor. + * + * Expected node.data shape: + * { + * url: string, + * method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", + * headers?: Record, + * body?: any, + * timeout?: number (ms, default 30 000) + * } + */ +export const executeHttpRequest = async ({ node }) => { + const { + url, + method = "GET", + headers = {}, + body, + timeout = 30_000, + } = node.data; + + if (!url) throw new Error("HTTP Request node requires a `url` in data."); + + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), timeout); + + try { + const fetchOpts = { + method: method.toUpperCase(), + headers: { "Content-Type": "application/json", ...headers }, + signal: controller.signal, + }; + + if (body && !["GET", "HEAD"].includes(fetchOpts.method)) { + fetchOpts.body = typeof body === "string" ? body : JSON.stringify(body); + } + + logger.debug("HTTP Request", { url, method: fetchOpts.method }); + + const response = await fetch(url, fetchOpts); + const contentType = response.headers.get("content-type") || ""; + let data; + + if (contentType.includes("application/json")) { + data = await response.json(); + } else { + data = await response.text(); + } + + return { + status: response.status, + statusText: response.statusText, + headers: Object.fromEntries(response.headers.entries()), + data, + }; + } finally { + clearTimeout(timer); + } +}; diff --git a/nodebase_backend/src/inngest/executors/index.js b/nodebase_backend/src/inngest/executors/index.js new file mode 100644 index 0000000..1066a60 --- /dev/null +++ b/nodebase_backend/src/inngest/executors/index.js @@ -0,0 +1,35 @@ +import { NodeType } from "../../config/constants.js"; +import { executeManualTrigger } from "./manual-trigger.js"; +import { executeHttpRequest } from "./http-request.js"; +import { executeOpenAI } from "./openai.js"; +import { executeAnthropic } from "./anthropic.js"; +import { executeGemini } from "./gemini.js"; +import { executeDiscord } from "./discord.js"; +import { executeSlack } from "./slack.js"; +import { executeGoogleFormTrigger } from "./google-form-trigger.js"; +import { executeStripeTrigger } from "./stripe-trigger.js"; + +const executorMap = { + [NodeType.MANUAL_TRIGGER]: executeManualTrigger, + [NodeType.HTTP_REQUEST]: executeHttpRequest, + [NodeType.OPENAI]: executeOpenAI, + [NodeType.ANTHROPIC]: executeAnthropic, + [NodeType.GEMINI]: executeGemini, + [NodeType.DISCORD]: executeDiscord, + [NodeType.SLACK]: executeSlack, + [NodeType.GOOGLE_FORM_TRIGGER]: executeGoogleFormTrigger, + [NodeType.STRIPE_TRIGGER]: executeStripeTrigger, +}; + +/** + * Return the executor function for a given node type. + * @param {string} type – a NodeType enum value + * @returns {Function} + */ +export const getExecutorForType = (type) => { + const executor = executorMap[type]; + if (!executor) { + throw new Error(`No executor registered for node type: ${type}`); + } + return executor; +}; diff --git a/nodebase_backend/src/inngest/executors/manual-trigger.js b/nodebase_backend/src/inngest/executors/manual-trigger.js new file mode 100644 index 0000000..5670770 --- /dev/null +++ b/nodebase_backend/src/inngest/executors/manual-trigger.js @@ -0,0 +1,7 @@ +/** + * Manual trigger executor — simply passes through. + * The trigger has already fired; this is a no-op entry point. + */ +export const executeManualTrigger = async ({ node }) => { + return { triggered: true, nodeId: node.id, type: node.type }; +}; diff --git a/nodebase_backend/src/inngest/executors/openai.js b/nodebase_backend/src/inngest/executors/openai.js new file mode 100644 index 0000000..aed17bd --- /dev/null +++ b/nodebase_backend/src/inngest/executors/openai.js @@ -0,0 +1,61 @@ +import { generateText } from "ai"; +import { createOpenAI } from "@ai-sdk/openai"; +import logger from "../../utils/logger.js"; + +/** + * OpenAI executor — uses the Vercel AI SDK's `generateText` for a + * single-turn completion. + * + * Expected node.data shape: + * { + * model?: string (default "gpt-4o-mini"), + * userPrompt: string, (or legacy `prompt`) + * systemPrompt?: string, + * temperature?: number, + * maxTokens?: number, + * } + * + * credential: the user's decrypted OpenAI API key string. + */ +export const executeOpenAI = async ({ node, credential }) => { + if (!credential) + throw new Error("OpenAI node requires an API key credential."); + + const { + model = "gpt-4o-mini", + userPrompt, + prompt, + systemPrompt, + temperature, + maxTokens, + } = node.data; + + // Accept userPrompt (from frontend dialog) or legacy prompt field + const resolvedPrompt = userPrompt || prompt; + if (!resolvedPrompt) + throw new Error("OpenAI node requires a user prompt in data."); + + const openai = createOpenAI({ apiKey: credential }); + + logger.debug("OpenAI generateText", { model }); + + // Build messages array for proper system + user prompt handling + const messages = []; + if (systemPrompt) { + messages.push({ role: "system", content: systemPrompt }); + } + messages.push({ role: "user", content: resolvedPrompt }); + + const result = await generateText({ + model: openai(model), + messages, + temperature, + maxTokens, + }); + + return { + text: result.text, + usage: result.usage, + model, + }; +}; diff --git a/nodebase_backend/src/inngest/executors/slack.js b/nodebase_backend/src/inngest/executors/slack.js new file mode 100644 index 0000000..477ea64 --- /dev/null +++ b/nodebase_backend/src/inngest/executors/slack.js @@ -0,0 +1,41 @@ +import logger from "../../utils/logger.js"; + +/** + * Slack executor — sends a message to a Slack webhook URL. + * + * Expected node.data shape: + * { + * webhookUrl: string, + * text: string, + * blocks?: Array (Slack Block Kit blocks, optional) + * } + */ +export const executeSlack = async ({ node }) => { + const { webhookUrl, text, blocks } = node.data; + + if (!webhookUrl) + throw new Error("Slack node requires a `webhookUrl` in data."); + if (!text && !blocks) + throw new Error("Slack node requires `text` or `blocks` in data."); + + const payload = {}; + if (text) payload.text = text; + if (blocks) payload.blocks = blocks; + + logger.debug("Slack webhook", { + webhookUrl: webhookUrl.slice(0, 40) + "...", + }); + + const response = await fetch(webhookUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + + if (!response.ok) { + const body = await response.text(); + throw new Error(`Slack webhook failed (${response.status}): ${body}`); + } + + return { sent: true, status: response.status }; +}; diff --git a/nodebase_backend/src/inngest/executors/stripe-trigger.js b/nodebase_backend/src/inngest/executors/stripe-trigger.js new file mode 100644 index 0000000..d3bb88c --- /dev/null +++ b/nodebase_backend/src/inngest/executors/stripe-trigger.js @@ -0,0 +1,13 @@ +/** + * Stripe trigger executor — passes through the webhook event payload. + */ +export const executeStripeTrigger = async ({ node, triggerPayload }) => { + return { + triggered: true, + nodeId: node.id, + type: node.type, + payload: triggerPayload?.event ?? node.data?.payload ?? {}, + source: triggerPayload?.source ?? "manual", + receivedAt: triggerPayload?.receivedAt ?? new Date().toISOString(), + }; +}; diff --git a/nodebase_backend/src/inngest/functions/execute-workflow.js b/nodebase_backend/src/inngest/functions/execute-workflow.js new file mode 100644 index 0000000..bf52dca --- /dev/null +++ b/nodebase_backend/src/inngest/functions/execute-workflow.js @@ -0,0 +1,122 @@ +import { inngest } from "../client.js"; +import { runWorkflow } from "../../engine/runner.js"; +import * as executionsService from "../../modules/executions/executions.service.js"; +import * as workflowsService from "../../modules/workflows/workflows.service.js"; +import { getCredentialsForWorkflow } from "../../modules/credentials/credentials.service.js"; +import { sseManager } from "../../modules/executions/sse.js"; +import logger from "../../utils/logger.js"; + +/** + * Inngest function: "workflow.execute" + * + * Triggered when a user runs a workflow (POST /api/workflows/:id/execute). + * Uses durable steps so each node execution is individually retryable. + */ +export const executeWorkflow = inngest.createFunction( + { + id: "execute-workflow", + retries: 0, // workflow-level retries off — individual nodes can retry inside + }, + { event: "workflow/execute" }, + async ({ event, step }) => { + const { executionId, workflowId, userId, triggerPayload } = event.data; + + logger.info("Inngest: starting workflow execution", { + executionId, + workflowId, + }); + + // Notify any workflow-level SSE subscribers (e.g. editor open on this workflow) + // so they can auto-subscribe to the execution-level stream. + sseManager.sendWorkflow(workflowId, "execution:started", { + executionId, + workflowId, + }); + + // ── Step 1: Load the workflow graph + credentials + const { workflow, credentials } = await step.run( + "load-workflow", + async () => { + const wf = await workflowsService.getWorkflowById(workflowId, userId); + const creds = await getCredentialsForWorkflow(wf.nodes, userId); + return { workflow: wf, credentials: creds }; + }, + ); + + // ── Step 2: Run the workflow engine + try { + const context = await step.run("run-engine", async () => { + return runWorkflow({ + workflow, + credentials, + triggerPayload: triggerPayload ?? {}, + + onNodeStart: async (nodeId) => { + await executionsService.createNodeExecution(executionId, nodeId); + sseManager.send(executionId, "node:start", { nodeId }); + }, + + onNodeComplete: async (nodeId, output) => { + await executionsService.updateNodeExecution( + executionId, + nodeId, + "SUCCESS", + output, + ); + sseManager.send(executionId, "node:complete", { nodeId, output }); + }, + + onNodeError: async (nodeId, error) => { + await executionsService.updateNodeExecution( + executionId, + nodeId, + "FAILED", + null, + error.message, + ); + sseManager.send(executionId, "node:error", { + nodeId, + error: error.message, + }); + }, + }); + }); + + // ── Step 3: Mark execution as SUCCESS + await step.run("mark-success", async () => { + await executionsService.updateExecution( + executionId, + "SUCCESS", + context, + ); + sseManager.send(executionId, "execution:complete", { + status: "SUCCESS", + }); + sseManager.close(executionId); + }); + + return { success: true, executionId }; + } catch (err) { + // ── Mark execution as FAILED + await step.run("mark-failed", async () => { + await executionsService.updateExecution( + executionId, + "FAILED", + null, + err.message, + err.stack, + ); + sseManager.send(executionId, "execution:error", { + error: err.message, + }); + sseManager.close(executionId); + }); + + logger.error("Workflow execution failed", { + executionId, + error: err.message, + }); + return { success: false, executionId, error: err.message }; + } + }, +); diff --git a/nodebase_backend/src/inngest/serve.js b/nodebase_backend/src/inngest/serve.js new file mode 100644 index 0000000..fe0d181 --- /dev/null +++ b/nodebase_backend/src/inngest/serve.js @@ -0,0 +1,12 @@ +import { serve } from "inngest/express"; +import { inngest } from "./client.js"; +import { executeWorkflow } from "./functions/execute-workflow.js"; + +/** + * Express middleware that exposes the Inngest webhook endpoint. + * Mount at: app.use("/api/inngest", inngestServe); + */ +export const inngestServe = serve({ + client: inngest, + functions: [executeWorkflow], +}); diff --git a/nodebase_backend/src/middleware/auth.js b/nodebase_backend/src/middleware/auth.js new file mode 100644 index 0000000..efc0167 --- /dev/null +++ b/nodebase_backend/src/middleware/auth.js @@ -0,0 +1,28 @@ +import jwt from "jsonwebtoken"; +import env from "../config/env.js"; +import AppError from "../utils/api-error.js"; + +/** + * Middleware that verifies the JWT from the `token` cookie. + * On success, attaches `req.user = { id, email }` and calls next(). + */ +const verifyToken = (req, _res, next) => { + const token = req.cookies?.token; + + if (!token) { + return next(new AppError("Authentication required. Please log in.", 401)); + } + + try { + const decoded = jwt.verify(token, env.JWT_SECRET); + req.user = { id: decoded.id, email: decoded.email }; + next(); + } catch (err) { + if (err.name === "TokenExpiredError") { + return next(new AppError("Session expired. Please log in again.", 401)); + } + return next(new AppError("Invalid token. Please log in again.", 401)); + } +}; + +export default verifyToken; diff --git a/nodebase_backend/src/middleware/error-handler.js b/nodebase_backend/src/middleware/error-handler.js new file mode 100644 index 0000000..02b5d62 --- /dev/null +++ b/nodebase_backend/src/middleware/error-handler.js @@ -0,0 +1,25 @@ +import env from "../config/env.js"; +import logger from "../utils/logger.js"; + +/** + * Global error-handling middleware. + * Express recognises it by the 4-argument signature. + */ +// eslint-disable-next-line no-unused-vars +const errorHandler = (err, _req, res, _next) => { + const statusCode = err.statusCode || 500; + const message = err.isOperational ? err.message : "Internal Server Error"; + + // Log the error without leaking sensitive details to the client + logger.error(`${statusCode} — ${message}`, { + stack: env.isDev ? err.stack : undefined, + }); + + res.status(statusCode).json({ + success: false, + message, + ...(env.isDev && { stack: err.stack }), + }); +}; + +export default errorHandler; diff --git a/nodebase_backend/src/middleware/not-found.js b/nodebase_backend/src/middleware/not-found.js new file mode 100644 index 0000000..e913b89 --- /dev/null +++ b/nodebase_backend/src/middleware/not-found.js @@ -0,0 +1,11 @@ +/** + * 404 fallback for unmatched routes. + */ +const notFound = (req, res, _next) => { + res.status(404).json({ + success: false, + message: `Route not found: ${req.method} ${req.originalUrl}`, + }); +}; + +export default notFound; diff --git a/nodebase_backend/src/middleware/request-logger.js b/nodebase_backend/src/middleware/request-logger.js new file mode 100644 index 0000000..8a7df2e --- /dev/null +++ b/nodebase_backend/src/middleware/request-logger.js @@ -0,0 +1,34 @@ +import logger from "../utils/logger.js"; + +/** + * Express middleware that logs every incoming request and its response. + * + * Logs: + * - Incoming: method, path, IP + * - Outgoing: method, path, status code, response time, authenticated userId + * + * Does NOT log response bodies to avoid leaking sensitive data. + */ +const requestLogger = (req, res, next) => { + const start = process.hrtime.bigint(); + + // Log incoming request + logger.http(`→ ${req.method} ${req.originalUrl}`, { + ip: req.ip, + }); + + // Capture response finish + res.on("finish", () => { + const durationMs = Number(process.hrtime.bigint() - start) / 1e6; + + logger.http(`← ${req.method} ${req.originalUrl} ${res.statusCode}`, { + statusCode: res.statusCode, + durationMs: Math.round(durationMs * 100) / 100, + userId: req.user?.id || "anonymous", + }); + }); + + next(); +}; + +export default requestLogger; diff --git a/nodebase_backend/src/middleware/validate.js b/nodebase_backend/src/middleware/validate.js new file mode 100644 index 0000000..bdb8d1e --- /dev/null +++ b/nodebase_backend/src/middleware/validate.js @@ -0,0 +1,28 @@ +/** + * Zod validation middleware factory. + * + * @param {import('zod').ZodSchema} schema A Zod schema to validate against + * @param {'body'|'query'|'params'} source Which part of the request to validate (default: "body") + * @returns {import('express').RequestHandler} + */ +const validate = + (schema, source = "body") => + (req, res, next) => { + const result = schema.safeParse(req[source]); + + if (!result.success) { + const errors = result.error.flatten().fieldErrors; + + return res.status(400).json({ + success: false, + message: "Validation failed", + errors, + }); + } + + // Replace with parsed (and potentially transformed) data + req[source] = result.data; + next(); + }; + +export default validate; diff --git a/nodebase_backend/src/modules/auth/auth.controller.js b/nodebase_backend/src/modules/auth/auth.controller.js new file mode 100644 index 0000000..aaa28dc --- /dev/null +++ b/nodebase_backend/src/modules/auth/auth.controller.js @@ -0,0 +1,33 @@ +import * as authService from "./auth.service.js"; +import catchAsync from "../../utils/catch-async.js"; +import ApiResponse from "../../utils/api-response.js"; +import env from "../../config/env.js"; + +const COOKIE_OPTIONS = { + httpOnly: true, + secure: env.isProd, + sameSite: env.isProd ? "none" : "lax", + maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days + path: "/", +}; + +export const register = catchAsync(async (req, res) => { + const { user, token } = await authService.register(req.body); + res.cookie("token", token, COOKIE_OPTIONS); + ApiResponse.success(res, { user }, "Registration successful", 201); +}); + +export const login = catchAsync(async (req, res) => { + const { user, token } = await authService.login(req.body); + res.cookie("token", token, COOKIE_OPTIONS); + ApiResponse.success(res, { user }, "Login successful"); +}); + +export const logout = catchAsync(async (_req, res) => { + res.clearCookie("token", COOKIE_OPTIONS); + ApiResponse.success(res, null, "Logged out successfully"); +}); + +export const me = catchAsync(async (req, res) => { + ApiResponse.success(res, { user: req.user }); +}); diff --git a/nodebase_backend/src/modules/auth/auth.routes.js b/nodebase_backend/src/modules/auth/auth.routes.js new file mode 100644 index 0000000..2463f48 --- /dev/null +++ b/nodebase_backend/src/modules/auth/auth.routes.js @@ -0,0 +1,14 @@ +import { Router } from "express"; +import * as authController from "./auth.controller.js"; +import validate from "../../middleware/validate.js"; +import verifyToken from "../../middleware/auth.js"; +import { registerSchema, loginSchema } from "./auth.validation.js"; + +const router = Router(); + +router.post("/register", validate(registerSchema), authController.register); +router.post("/login", validate(loginSchema), authController.login); +router.post("/logout", verifyToken, authController.logout); +router.get("/me", verifyToken, authController.me); + +export default router; diff --git a/nodebase_backend/src/modules/auth/auth.service.js b/nodebase_backend/src/modules/auth/auth.service.js new file mode 100644 index 0000000..a863f9c --- /dev/null +++ b/nodebase_backend/src/modules/auth/auth.service.js @@ -0,0 +1,87 @@ +import { query } from "../../config/db.js"; +import bcrypt from "bcryptjs"; +import jwt from "jsonwebtoken"; +import env from "../../config/env.js"; +import AppError from "../../utils/api-error.js"; +import withTransaction from "../../utils/transaction.js"; +import logger from "../../utils/logger.js"; + +const SALT_ROUNDS = 12; + +/** + * Register a new user with email + password. + */ +export const register = async ({ name, email, password }) => { + // Check if email already taken (pre-flight, outside transaction) + const existing = await query( + 'SELECT id FROM "user" WHERE email = $1 LIMIT 1', + [email], + ); + if (existing.rows.length > 0) { + throw new AppError("Email already registered", 409); + } + + const hashedPassword = await bcrypt.hash(password, SALT_ROUNDS); + + // Transaction: create user + account atomically + const { user, token } = await withTransaction(null, async (client) => { + const userResult = await client.query( + `INSERT INTO "user" (name, email) VALUES ($1, $2) RETURNING id, name, email, created_at`, + [name, email], + ); + const newUser = userResult.rows[0]; + + await client.query( + `INSERT INTO "account" (account_id, provider_id, user_id, password) VALUES ($1, $2, $3, $4)`, + [newUser.id, "credential", newUser.id, hashedPassword], + ); + + const jwt = generateToken(newUser); + return { user: newUser, token: jwt }; + }); + + logger.info("User registered", { userId: user.id }); + return { user, token }; +}; + +/** + * Log in with email + password. + */ +export const login = async ({ email, password }) => { + // Fetch user + credential in parallel for speed + const userResult = await query( + 'SELECT id, name, email FROM "user" WHERE email = $1 LIMIT 1', + [email], + ); + if (userResult.rows.length === 0) { + throw new AppError("Invalid email or password", 401); + } + const user = userResult.rows[0]; + + const accountResult = await query( + `SELECT password FROM "account" WHERE user_id = $1 AND provider_id = 'credential' LIMIT 1`, + [user.id], + ); + if (accountResult.rows.length === 0 || !accountResult.rows[0].password) { + throw new AppError("Invalid email or password", 401); + } + + const valid = await bcrypt.compare(password, accountResult.rows[0].password); + if (!valid) { + throw new AppError("Invalid email or password", 401); + } + + const token = generateToken(user); + + logger.info("User logged in", { userId: user.id }); + return { user, token }; +}; + +/** + * Generate a signed JWT for the given user. + */ +function generateToken(user) { + return jwt.sign({ id: user.id, email: user.email }, env.JWT_SECRET, { + expiresIn: env.JWT_EXPIRES_IN, + }); +} diff --git a/nodebase_backend/src/modules/auth/auth.validation.js b/nodebase_backend/src/modules/auth/auth.validation.js new file mode 100644 index 0000000..9c139c4 --- /dev/null +++ b/nodebase_backend/src/modules/auth/auth.validation.js @@ -0,0 +1,12 @@ +import { z } from "zod"; + +export const registerSchema = z.object({ + name: z.string().min(1, "Name is required").max(100), + email: z.string().email("Invalid email address"), + password: z.string().min(8, "Password must be at least 8 characters"), +}); + +export const loginSchema = z.object({ + email: z.string().email("Invalid email address"), + password: z.string().min(1, "Password is required"), +}); diff --git a/nodebase_backend/src/modules/connections/connections.controller.js b/nodebase_backend/src/modules/connections/connections.controller.js new file mode 100644 index 0000000..6a0baab --- /dev/null +++ b/nodebase_backend/src/modules/connections/connections.controller.js @@ -0,0 +1,17 @@ +import * as connectionsService from "./connections.service.js"; +import catchAsync from "../../utils/catch-async.js"; +import ApiResponse from "../../utils/api-response.js"; + +export const createConnection = catchAsync(async (req, res) => { + const connection = await connectionsService.createConnection( + req.params.workflowId, + req.user.id, + req.body, + ); + ApiResponse.success(res, { connection }, "Connection created", 201); +}); + +export const removeConnection = catchAsync(async (req, res) => { + await connectionsService.removeConnection(req.params.id, req.user.id); + ApiResponse.success(res, null, "Connection deleted"); +}); diff --git a/nodebase_backend/src/modules/connections/connections.routes.js b/nodebase_backend/src/modules/connections/connections.routes.js new file mode 100644 index 0000000..e2d6194 --- /dev/null +++ b/nodebase_backend/src/modules/connections/connections.routes.js @@ -0,0 +1,21 @@ +import { Router } from "express"; +import * as connectionsController from "./connections.controller.js"; +import verifyToken from "../../middleware/auth.js"; +import validate from "../../middleware/validate.js"; +import { createConnectionSchema } from "./connections.validation.js"; + +const router = Router(); + +router.use(verifyToken); + +// Create a connection inside a workflow +router.post( + "/workflows/:workflowId/connections", + validate(createConnectionSchema), + connectionsController.createConnection, +); + +// Delete a connection by its own ID +router.delete("/:id", connectionsController.removeConnection); + +export default router; diff --git a/nodebase_backend/src/modules/connections/connections.service.js b/nodebase_backend/src/modules/connections/connections.service.js new file mode 100644 index 0000000..f5e87ff --- /dev/null +++ b/nodebase_backend/src/modules/connections/connections.service.js @@ -0,0 +1,63 @@ +import { query } from "../../config/db.js"; +import AppError from "../../utils/api-error.js"; +import withTransaction from "../../utils/transaction.js"; +import logger from "../../utils/logger.js"; + +/** + * Create a connection between two nodes in a workflow. + */ +export const createConnection = async ( + workflowId, + userId, + { fromNodeId, toNodeId, fromOutput, toInput }, +) => { + const connection = await withTransaction(userId, async (client) => { + // Verify workflow ownership + const wf = await client.query( + 'SELECT id FROM "workflow" WHERE id = $1 AND user_id = $2 LIMIT 1', + [workflowId, userId], + ); + if (wf.rows.length === 0) throw new AppError("Workflow not found", 404); + + const result = await client.query( + `INSERT INTO "connection" (workflow_id, from_node_id, to_node_id, from_output, to_input) + VALUES ($1, $2, $3, $4, $5) + RETURNING id, workflow_id, from_node_id, to_node_id, from_output, to_input, created_at`, + [ + workflowId, + fromNodeId, + toNodeId, + fromOutput || "main", + toInput || "main", + ], + ); + return result.rows[0]; + }); + + logger.info("Connection created", { + connectionId: connection.id, + workflowId, + }); + return connection; +}; + +/** + * Delete a connection. + */ +export const removeConnection = async (connectionId, userId) => { + await withTransaction(userId, async (client) => { + const ownership = await client.query( + `SELECT c.id FROM "connection" c JOIN "workflow" w ON w.id = c.workflow_id WHERE c.id = $1 AND w.user_id = $2 LIMIT 1`, + [connectionId, userId], + ); + if (ownership.rows.length === 0) + throw new AppError("Connection not found", 404); + + await client.query('DELETE FROM "connection" WHERE id = $1', [ + connectionId, + ]); + }); + + logger.info("Connection deleted", { connectionId }); + return { id: connectionId }; +}; diff --git a/nodebase_backend/src/modules/connections/connections.validation.js b/nodebase_backend/src/modules/connections/connections.validation.js new file mode 100644 index 0000000..66ac336 --- /dev/null +++ b/nodebase_backend/src/modules/connections/connections.validation.js @@ -0,0 +1,8 @@ +import { z } from "zod"; + +export const createConnectionSchema = z.object({ + fromNodeId: z.string().min(1, "fromNodeId is required"), + toNodeId: z.string().min(1, "toNodeId is required"), + fromOutput: z.string().default("main"), + toInput: z.string().default("main"), +}); diff --git a/nodebase_backend/src/modules/credentials/credentials.controller.js b/nodebase_backend/src/modules/credentials/credentials.controller.js new file mode 100644 index 0000000..5bcb21b --- /dev/null +++ b/nodebase_backend/src/modules/credentials/credentials.controller.js @@ -0,0 +1,50 @@ +import * as credentialsService from "./credentials.service.js"; +import catchAsync from "../../utils/catch-async.js"; +import ApiResponse from "../../utils/api-response.js"; + +export const getCredentials = catchAsync(async (req, res) => { + const { page, pageSize } = req.query; + const data = await credentialsService.getCredentials(req.user.id, { + page: page ? parseInt(page, 10) : undefined, + pageSize: pageSize ? parseInt(pageSize, 10) : undefined, + }); + ApiResponse.success(res, data); +}); + +export const getCredential = catchAsync(async (req, res) => { + const credential = await credentialsService.getCredentialById( + req.params.id, + req.user.id, + ); + ApiResponse.success(res, { credential }); +}); + +export const getCredentialsByType = catchAsync(async (req, res) => { + const credentials = await credentialsService.getCredentialsByType( + req.params.type, + req.user.id, + ); + ApiResponse.success(res, { credentials }); +}); + +export const createCredential = catchAsync(async (req, res) => { + const credential = await credentialsService.createCredential( + req.user.id, + req.body, + ); + ApiResponse.success(res, { credential }, "Credential created", 201); +}); + +export const updateCredential = catchAsync(async (req, res) => { + const credential = await credentialsService.updateCredential( + req.params.id, + req.user.id, + req.body, + ); + ApiResponse.success(res, { credential }, "Credential updated"); +}); + +export const removeCredential = catchAsync(async (req, res) => { + await credentialsService.removeCredential(req.params.id, req.user.id); + ApiResponse.success(res, null, "Credential deleted"); +}); diff --git a/nodebase_backend/src/modules/credentials/credentials.routes.js b/nodebase_backend/src/modules/credentials/credentials.routes.js new file mode 100644 index 0000000..bc3df80 --- /dev/null +++ b/nodebase_backend/src/modules/credentials/credentials.routes.js @@ -0,0 +1,29 @@ +import { Router } from "express"; +import * as credentialsController from "./credentials.controller.js"; +import verifyToken from "../../middleware/auth.js"; +import validate from "../../middleware/validate.js"; +import { + createCredentialSchema, + updateCredentialSchema, +} from "./credentials.validation.js"; + +const router = Router(); + +router.use(verifyToken); + +router.get("/", credentialsController.getCredentials); +router.post( + "/", + validate(createCredentialSchema), + credentialsController.createCredential, +); +router.get("/type/:type", credentialsController.getCredentialsByType); +router.get("/:id", credentialsController.getCredential); +router.patch( + "/:id", + validate(updateCredentialSchema), + credentialsController.updateCredential, +); +router.delete("/:id", credentialsController.removeCredential); + +export default router; diff --git a/nodebase_backend/src/modules/credentials/credentials.service.js b/nodebase_backend/src/modules/credentials/credentials.service.js new file mode 100644 index 0000000..62849dc --- /dev/null +++ b/nodebase_backend/src/modules/credentials/credentials.service.js @@ -0,0 +1,164 @@ +import { query } from "../../config/db.js"; +import AppError from "../../utils/api-error.js"; +import { PAGINATION } from "../../config/constants.js"; +import withTransaction from "../../utils/transaction.js"; +import logger from "../../utils/logger.js"; +import { encrypt, decrypt } from "../../utils/encryption.js"; + +/** + * List all credentials for a user (paginated). + */ +export const getCredentials = async ( + userId, + { + page = PAGINATION.DEFAULT_PAGE, + pageSize = PAGINATION.DEFAULT_PAGE_SIZE, + } = {}, +) => { + const offset = (page - 1) * pageSize; + + const [dataResult, countResult] = await Promise.all([ + query( + `SELECT id, name, type, created_at, updated_at FROM "credential" WHERE user_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3`, + [userId, pageSize, offset], + ), + query('SELECT COUNT(*) FROM "credential" WHERE user_id = $1', [userId]), + ]); + + return { + credentials: dataResult.rows, + total: parseInt(countResult.rows[0].count, 10), + page, + pageSize, + }; +}; + +/** + * Get a single credential by ID (value excluded for safety — only returned on explicit request). + */ +export const getCredentialById = async (credentialId, userId) => { + const result = await query( + 'SELECT id, name, type, created_at, updated_at FROM "credential" WHERE id = $1 AND user_id = $2', + [credentialId, userId], + ); + if (result.rows.length === 0) throw new AppError("Credential not found", 404); + return result.rows[0]; +}; + +/** + * Get credentials by type for a user. + */ +export const getCredentialsByType = async (type, userId) => { + const result = await query( + 'SELECT id, name, type, created_at, updated_at FROM "credential" WHERE type = $1 AND user_id = $2 ORDER BY created_at DESC', + [type, userId], + ); + return result.rows; +}; + +/** + * Create a credential. + */ +export const createCredential = async (userId, { name, value, type }) => { + const encryptedValue = encrypt(value); + const credential = await withTransaction(userId, async (client) => { + const result = await client.query( + `INSERT INTO "credential" (name, value, type, user_id) VALUES ($1, $2, $3, $4) + RETURNING id, name, type, created_at, updated_at`, + [name, encryptedValue, type, userId], + ); + return result.rows[0]; + }); + + logger.info("Credential created", { credentialId: credential.id, type }); + return credential; +}; + +/** + * Update a credential. + */ +export const updateCredential = async ( + credentialId, + userId, + { name, value }, +) => { + const credential = await withTransaction(userId, async (client) => { + const fields = []; + const values = []; + let idx = 1; + + if (name !== undefined) { + fields.push(`name = $${idx++}`); + values.push(name); + } + if (value !== undefined) { + fields.push(`value = $${idx++}`); + values.push(encrypt(value)); + } + + if (fields.length === 0) throw new AppError("No fields to update", 400); + + values.push(credentialId, userId); + const result = await client.query( + `UPDATE "credential" SET ${fields.join(", ")} WHERE id = $${idx++} AND user_id = $${idx} + RETURNING id, name, type, updated_at`, + values, + ); + if (result.rows.length === 0) + throw new AppError("Credential not found", 404); + return result.rows[0]; + }); + + logger.info("Credential updated", { credentialId }); + return credential; +}; + +/** + * Delete a credential. + */ +export const removeCredential = async (credentialId, userId) => { + await withTransaction(userId, async (client) => { + const result = await client.query( + 'DELETE FROM "credential" WHERE id = $1 AND user_id = $2 RETURNING id', + [credentialId, userId], + ); + if (result.rows.length === 0) + throw new AppError("Credential not found", 404); + }); + + logger.info("Credential deleted", { credentialId }); + return { id: credentialId }; +}; + +/** + * For the execution engine: fetch and decrypt credential values for + * every node in a workflow that has a credential_id. + * + * @param {Array} nodes – node rows (must include id and credential_id) + * @param {string} userId + * @returns {Object} – { [nodeId]: decryptedPlaintext } + */ +export const getCredentialsForWorkflow = async (nodes, userId) => { + const nodesWithCred = nodes.filter((n) => n.credential_id); + if (nodesWithCred.length === 0) return {}; + + const credIds = [...new Set(nodesWithCred.map((n) => n.credential_id))]; + + // Fetch raw (encrypted) values — only for this user + const placeholders = credIds.map((_, i) => `$${i + 2}`).join(", "); + const result = await query( + `SELECT id, value FROM "credential" WHERE id IN (${placeholders}) AND user_id = $1`, + [userId, ...credIds], + ); + + const credMap = Object.fromEntries( + result.rows.map((r) => [r.id, decrypt(r.value)]), + ); + + // Map nodeId → decrypted credential value + const out = {}; + for (const node of nodesWithCred) { + out[node.id] = credMap[node.credential_id] ?? null; + } + return out; +}; diff --git a/nodebase_backend/src/modules/credentials/credentials.validation.js b/nodebase_backend/src/modules/credentials/credentials.validation.js new file mode 100644 index 0000000..fd8f7b8 --- /dev/null +++ b/nodebase_backend/src/modules/credentials/credentials.validation.js @@ -0,0 +1,17 @@ +import { z } from "zod"; +import { CredentialType } from "../../config/constants.js"; + +const credentialTypeValues = Object.values(CredentialType); + +export const createCredentialSchema = z.object({ + name: z.string().min(1, "Credential name is required").max(255), + value: z.string().min(1, "Credential value is required"), + type: z.enum(credentialTypeValues, { + errorMap: () => ({ message: "Invalid credential type" }), + }), +}); + +export const updateCredentialSchema = z.object({ + name: z.string().min(1).max(255).optional(), + value: z.string().min(1).optional(), +}); diff --git a/nodebase_backend/src/modules/executions/executions.controller.js b/nodebase_backend/src/modules/executions/executions.controller.js new file mode 100644 index 0000000..fb31b8c --- /dev/null +++ b/nodebase_backend/src/modules/executions/executions.controller.js @@ -0,0 +1,61 @@ +import * as executionsService from "./executions.service.js"; +import catchAsync from "../../utils/catch-async.js"; +import ApiResponse from "../../utils/api-response.js"; +import { sseManager } from "./sse.js"; + +export const getExecutions = catchAsync(async (req, res) => { + const { page, pageSize } = req.query; + const data = await executionsService.getExecutions(req.user.id, { + page: page ? parseInt(page, 10) : undefined, + pageSize: pageSize ? parseInt(pageSize, 10) : undefined, + }); + ApiResponse.success(res, data); +}); + +export const getExecution = catchAsync(async (req, res) => { + const execution = await executionsService.getExecutionById( + req.params.id, + req.user.id, + ); + ApiResponse.success(res, { execution }); +}); + +/** + * GET /api/executions/:id/nodes — per-node execution details + */ +export const getNodeExecutions = catchAsync(async (req, res) => { + // Verify the user owns this execution first + await executionsService.getExecutionById(req.params.id, req.user.id); + const nodeExecutions = await executionsService.getNodeExecutions( + req.params.id, + ); + ApiResponse.success(res, { nodeExecutions }); +}); + +/** + * GET /api/executions/:id/stream — SSE endpoint for real-time updates. + */ +export const streamExecution = catchAsync(async (req, res) => { + // Verify the user owns this execution + await executionsService.getExecutionById(req.params.id, req.user.id); + + // SSE headers + res.writeHead(200, { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + Connection: "keep-alive", + }); + + // Send initial connected event + res.write( + `event: connected\ndata: ${JSON.stringify({ executionId: req.params.id })}\n\n`, + ); + + // Register this response with the SSE manager + sseManager.add(req.params.id, res); + + // Clean up on client disconnect + req.on("close", () => { + sseManager.remove(req.params.id, res); + }); +}); diff --git a/nodebase_backend/src/modules/executions/executions.routes.js b/nodebase_backend/src/modules/executions/executions.routes.js new file mode 100644 index 0000000..5ca6453 --- /dev/null +++ b/nodebase_backend/src/modules/executions/executions.routes.js @@ -0,0 +1,14 @@ +import { Router } from "express"; +import * as executionsController from "./executions.controller.js"; +import verifyToken from "../../middleware/auth.js"; + +const router = Router(); + +router.use(verifyToken); + +router.get("/", executionsController.getExecutions); +router.get("/:id", executionsController.getExecution); +router.get("/:id/nodes", executionsController.getNodeExecutions); +router.get("/:id/stream", executionsController.streamExecution); + +export default router; diff --git a/nodebase_backend/src/modules/executions/executions.service.js b/nodebase_backend/src/modules/executions/executions.service.js new file mode 100644 index 0000000..719eb07 --- /dev/null +++ b/nodebase_backend/src/modules/executions/executions.service.js @@ -0,0 +1,162 @@ +import { query } from "../../config/db.js"; +import AppError from "../../utils/api-error.js"; +import { PAGINATION } from "../../config/constants.js"; +import withTransaction from "../../utils/transaction.js"; +import logger from "../../utils/logger.js"; + +/** + * List executions for a user's workflows (paginated). + */ +export const getExecutions = async ( + userId, + { + page = PAGINATION.DEFAULT_PAGE, + pageSize = PAGINATION.DEFAULT_PAGE_SIZE, + } = {}, +) => { + const offset = (page - 1) * pageSize; + + const [dataResult, countResult] = await Promise.all([ + query( + `SELECT e.id, e.workflow_id, e.status, e.started_at, e.completed_at, e.trigger_event_id, + w.name AS workflow_name + FROM "execution" e + JOIN "workflow" w ON w.id = e.workflow_id + WHERE w.user_id = $1 + ORDER BY e.started_at DESC + LIMIT $2 OFFSET $3`, + [userId, pageSize, offset], + ), + query( + `SELECT COUNT(*) FROM "execution" e JOIN "workflow" w ON w.id = e.workflow_id WHERE w.user_id = $1`, + [userId], + ), + ]); + + return { + executions: dataResult.rows, + total: parseInt(countResult.rows[0].count, 10), + page, + pageSize, + }; +}; + +/** + * Get a single execution with its output. + */ +export const getExecutionById = async (executionId, userId) => { + const result = await query( + `SELECT e.* FROM "execution" e + JOIN "workflow" w ON w.id = e.workflow_id + WHERE e.id = $1 AND w.user_id = $2`, + [executionId, userId], + ); + if (result.rows.length === 0) throw new AppError("Execution not found", 404); + return result.rows[0]; +}; + +// ─── Write Operations ────────────────────────────────────────────── + +/** + * Create a new execution row (status defaults to RUNNING). + * Called when POST /api/workflows/:id/execute fires. + */ +export const createExecution = async (userId, workflowId) => { + const execution = await withTransaction(userId, async (client) => { + const result = await client.query( + `INSERT INTO "execution" (workflow_id, started_at) + VALUES ($1, now()) + RETURNING id, workflow_id, status, started_at`, + [workflowId], + ); + return result.rows[0]; + }); + + logger.info("Execution created", { executionId: execution.id, workflowId }); + return execution; +}; + +/** + * Update an execution's status, output, and error fields. + */ +export const updateExecution = async ( + executionId, + status, + output = null, + error = null, + errorStack = null, +) => { + await query( + `UPDATE "execution" + SET status = $2, + output = $3, + error = $4, + error_stack = $5, + completed_at = now() + WHERE id = $1`, + [ + executionId, + status, + output ? JSON.stringify(output) : null, + error, + errorStack, + ], + ); + logger.info("Execution updated", { executionId, status }); +}; + +// ─── Node Execution Tracking ─────────────────────────────────────── + +/** + * Record the start of a single node execution. + */ +export const createNodeExecution = async (executionId, nodeId) => { + const result = await query( + `INSERT INTO "node_execution" (execution_id, node_id, started_at) + VALUES ($1, $2, now()) + RETURNING id`, + [executionId, nodeId], + ); + return result.rows[0]; +}; + +/** + * Record the completion (or failure) of a node execution. + */ +export const updateNodeExecution = async ( + executionId, + nodeId, + status, + output = null, + error = null, +) => { + await query( + `UPDATE "node_execution" + SET status = $3, + output = $4, + error = $5, + completed_at = now() + WHERE execution_id = $1 AND node_id = $2`, + [ + executionId, + nodeId, + status, + output ? JSON.stringify(output) : null, + error, + ], + ); +}; + +/** + * Get all node executions for a given execution (for the detail view). + */ +export const getNodeExecutions = async (executionId) => { + const result = await query( + `SELECT id, node_id, status, output, error, started_at, completed_at + FROM "node_execution" + WHERE execution_id = $1 + ORDER BY started_at ASC`, + [executionId], + ); + return result.rows; +}; diff --git a/nodebase_backend/src/modules/executions/sse.js b/nodebase_backend/src/modules/executions/sse.js new file mode 100644 index 0000000..8fc3e60 --- /dev/null +++ b/nodebase_backend/src/modules/executions/sse.js @@ -0,0 +1,123 @@ +import logger from "../../utils/logger.js"; + +/** + * SSE Connection Manager + * + * Keeps a map of execution IDs → active SSE response objects so that + * the Inngest background function can push real-time events to the + * connected client. + * + * Also supports workflow-level subscriptions so that editors watching + * a workflow are notified when a new execution starts (e.g. via webhook). + */ +class SSEManager { + constructor() { + /** @type {Map} */ + this.connections = new Map(); + + /** @type {Map} */ + this.workflowConnections = new Map(); + } + + // ── Execution-level ──────────────────────────────────────────── + + /** + * Register a new SSE client for an execution. + * @param {string} executionId + * @param {import("express").Response} res + */ + add(executionId, res) { + if (!this.connections.has(executionId)) { + this.connections.set(executionId, []); + } + this.connections.get(executionId).push(res); + logger.debug("SSE client connected", { executionId }); + } + + /** + * Remove a specific client (e.g. on disconnect). + */ + remove(executionId, res) { + const clients = this.connections.get(executionId); + if (!clients) return; + const idx = clients.indexOf(res); + if (idx !== -1) clients.splice(idx, 1); + if (clients.length === 0) this.connections.delete(executionId); + logger.debug("SSE client disconnected", { executionId }); + } + + /** + * Send an SSE event to all clients watching a given execution. + * @param {string} executionId + * @param {string} eventName – e.g. "node:start", "execution:complete" + * @param {object} data + */ + send(executionId, eventName, data) { + const clients = this.connections.get(executionId); + if (!clients || clients.length === 0) return; + + const payload = `event: ${eventName}\ndata: ${JSON.stringify(data)}\n\n`; + for (const res of clients) { + res.write(payload); + } + } + + /** + * Close all SSE connections for an execution (workflow finished). + */ + close(executionId) { + const clients = this.connections.get(executionId); + if (!clients) return; + for (const res of clients) { + res.write("event: done\ndata: {}\n\n"); + res.end(); + } + this.connections.delete(executionId); + logger.debug("SSE connections closed", { executionId }); + } + + // ── Workflow-level ───────────────────────────────────────────── + + /** + * Register a new SSE client for a workflow (editor watching for new executions). + * @param {string} workflowId + * @param {import("express").Response} res + */ + addWorkflow(workflowId, res) { + if (!this.workflowConnections.has(workflowId)) { + this.workflowConnections.set(workflowId, []); + } + this.workflowConnections.get(workflowId).push(res); + logger.debug("SSE workflow client connected", { workflowId }); + } + + /** + * Remove a workflow-level SSE client. + */ + removeWorkflow(workflowId, res) { + const clients = this.workflowConnections.get(workflowId); + if (!clients) return; + const idx = clients.indexOf(res); + if (idx !== -1) clients.splice(idx, 1); + if (clients.length === 0) this.workflowConnections.delete(workflowId); + logger.debug("SSE workflow client disconnected", { workflowId }); + } + + /** + * Send an SSE event to all workflow-level clients. + * @param {string} workflowId + * @param {string} eventName – e.g. "execution:started" + * @param {object} data + */ + sendWorkflow(workflowId, eventName, data) { + const clients = this.workflowConnections.get(workflowId); + if (!clients || clients.length === 0) return; + + const payload = `event: ${eventName}\ndata: ${JSON.stringify(data)}\n\n`; + for (const res of clients) { + res.write(payload); + } + } +} + +export const sseManager = new SSEManager(); diff --git a/nodebase_backend/src/modules/nodes/nodes.controller.js b/nodebase_backend/src/modules/nodes/nodes.controller.js new file mode 100644 index 0000000..9402742 --- /dev/null +++ b/nodebase_backend/src/modules/nodes/nodes.controller.js @@ -0,0 +1,26 @@ +import * as nodesService from "./nodes.service.js"; +import catchAsync from "../../utils/catch-async.js"; +import ApiResponse from "../../utils/api-response.js"; + +export const createNode = catchAsync(async (req, res) => { + const node = await nodesService.createNode( + req.params.workflowId, + req.user.id, + req.body, + ); + ApiResponse.success(res, { node }, "Node created", 201); +}); + +export const updateNode = catchAsync(async (req, res) => { + const node = await nodesService.updateNode( + req.params.id, + req.user.id, + req.body, + ); + ApiResponse.success(res, { node }, "Node updated"); +}); + +export const removeNode = catchAsync(async (req, res) => { + await nodesService.removeNode(req.params.id, req.user.id); + ApiResponse.success(res, null, "Node deleted"); +}); diff --git a/nodebase_backend/src/modules/nodes/nodes.routes.js b/nodebase_backend/src/modules/nodes/nodes.routes.js new file mode 100644 index 0000000..0188049 --- /dev/null +++ b/nodebase_backend/src/modules/nodes/nodes.routes.js @@ -0,0 +1,22 @@ +import { Router } from "express"; +import * as nodesController from "./nodes.controller.js"; +import verifyToken from "../../middleware/auth.js"; +import validate from "../../middleware/validate.js"; +import { createNodeSchema, updateNodeSchema } from "./nodes.validation.js"; + +const router = Router(); + +router.use(verifyToken); + +// Create a node inside a workflow +router.post( + "/workflows/:workflowId/nodes", + validate(createNodeSchema), + nodesController.createNode, +); + +// Update / delete a node by its own ID +router.patch("/:id", validate(updateNodeSchema), nodesController.updateNode); +router.delete("/:id", nodesController.removeNode); + +export default router; diff --git a/nodebase_backend/src/modules/nodes/nodes.service.js b/nodebase_backend/src/modules/nodes/nodes.service.js new file mode 100644 index 0000000..4c749df --- /dev/null +++ b/nodebase_backend/src/modules/nodes/nodes.service.js @@ -0,0 +1,105 @@ +import { query } from "../../config/db.js"; +import AppError from "../../utils/api-error.js"; +import withTransaction from "../../utils/transaction.js"; +import logger from "../../utils/logger.js"; + +/** + * Create a node inside a workflow. + */ +export const createNode = async ( + workflowId, + userId, + { name, type, position, data, credentialId }, +) => { + const node = await withTransaction(userId, async (client) => { + // Verify workflow ownership + const wf = await client.query( + 'SELECT id FROM "workflow" WHERE id = $1 AND user_id = $2 LIMIT 1', + [workflowId, userId], + ); + if (wf.rows.length === 0) throw new AppError("Workflow not found", 404); + + const result = await client.query( + `INSERT INTO "node" (workflow_id, name, type, position, data, credential_id) + VALUES ($1, $2, $3, $4, $5, $6) + RETURNING id, workflow_id, name, type, position, data, credential_id, created_at, updated_at`, + [ + workflowId, + name, + type, + JSON.stringify(position), + JSON.stringify(data || {}), + credentialId || null, + ], + ); + return result.rows[0]; + }); + + logger.info("Node created", { nodeId: node.id, workflowId }); + return node; +}; + +/** + * Update a node. + */ +export const updateNode = async (nodeId, userId, updates) => { + const node = await withTransaction(userId, async (client) => { + // Verify ownership through workflow + const ownership = await client.query( + `SELECT n.id FROM "node" n JOIN "workflow" w ON w.id = n.workflow_id WHERE n.id = $1 AND w.user_id = $2 LIMIT 1`, + [nodeId, userId], + ); + if (ownership.rows.length === 0) throw new AppError("Node not found", 404); + + const fields = []; + const values = []; + let idx = 1; + + if (updates.name !== undefined) { + fields.push(`name = $${idx++}`); + values.push(updates.name); + } + if (updates.position !== undefined) { + fields.push(`position = $${idx++}`); + values.push(JSON.stringify(updates.position)); + } + if (updates.data !== undefined) { + fields.push(`data = $${idx++}`); + values.push(JSON.stringify(updates.data)); + } + if (updates.credentialId !== undefined) { + fields.push(`credential_id = $${idx++}`); + values.push(updates.credentialId); + } + + if (fields.length === 0) throw new AppError("No fields to update", 400); + + values.push(nodeId); + const result = await client.query( + `UPDATE "node" SET ${fields.join(", ")} WHERE id = $${idx} RETURNING id, workflow_id, name, type, position, data, credential_id, updated_at`, + values, + ); + return result.rows[0]; + }); + + logger.info("Node updated", { nodeId }); + return node; +}; + +/** + * Delete a node. + */ +export const removeNode = async (nodeId, userId) => { + await withTransaction(userId, async (client) => { + const ownership = await client.query( + `SELECT n.id FROM "node" n JOIN "workflow" w ON w.id = n.workflow_id WHERE n.id = $1 AND w.user_id = $2 LIMIT 1`, + [nodeId, userId], + ); + if (ownership.rows.length === 0) throw new AppError("Node not found", 404); + + await client.query('DELETE FROM "node" WHERE id = $1', [nodeId]); + }); + + logger.info("Node deleted", { nodeId }); + return { id: nodeId }; +}; diff --git a/nodebase_backend/src/modules/nodes/nodes.validation.js b/nodebase_backend/src/modules/nodes/nodes.validation.js new file mode 100644 index 0000000..bf33e99 --- /dev/null +++ b/nodebase_backend/src/modules/nodes/nodes.validation.js @@ -0,0 +1,21 @@ +import { z } from "zod"; +import { NodeType } from "../../config/constants.js"; + +const nodeTypeValues = Object.values(NodeType); + +export const createNodeSchema = z.object({ + name: z.string().min(1, "Node name is required").max(255), + type: z.enum(nodeTypeValues, { + errorMap: () => ({ message: "Invalid node type" }), + }), + position: z.object({ x: z.number(), y: z.number() }), + data: z.record(z.any()).optional().default({}), + credentialId: z.string().nullable().optional(), +}); + +export const updateNodeSchema = z.object({ + name: z.string().min(1).max(255).optional(), + position: z.object({ x: z.number(), y: z.number() }).optional(), + data: z.record(z.any()).optional(), + credentialId: z.string().nullable().optional(), +}); diff --git a/nodebase_backend/src/modules/users/users.controller.js b/nodebase_backend/src/modules/users/users.controller.js new file mode 100644 index 0000000..a281e8c --- /dev/null +++ b/nodebase_backend/src/modules/users/users.controller.js @@ -0,0 +1,13 @@ +import * as usersService from "./users.service.js"; +import catchAsync from "../../utils/catch-async.js"; +import ApiResponse from "../../utils/api-response.js"; + +export const getMe = catchAsync(async (req, res) => { + const user = await usersService.getUserById(req.user.id); + ApiResponse.success(res, { user }); +}); + +export const updateMe = catchAsync(async (req, res) => { + const user = await usersService.updateUser(req.user.id, req.body); + ApiResponse.success(res, { user }, "Profile updated"); +}); diff --git a/nodebase_backend/src/modules/users/users.routes.js b/nodebase_backend/src/modules/users/users.routes.js new file mode 100644 index 0000000..e842c6a --- /dev/null +++ b/nodebase_backend/src/modules/users/users.routes.js @@ -0,0 +1,12 @@ +import { Router } from "express"; +import * as usersController from "./users.controller.js"; +import verifyToken from "../../middleware/auth.js"; + +const router = Router(); + +router.use(verifyToken); + +router.get("/me", usersController.getMe); +router.patch("/me", usersController.updateMe); + +export default router; diff --git a/nodebase_backend/src/modules/users/users.service.js b/nodebase_backend/src/modules/users/users.service.js new file mode 100644 index 0000000..63b8225 --- /dev/null +++ b/nodebase_backend/src/modules/users/users.service.js @@ -0,0 +1,52 @@ +import { query } from "../../config/db.js"; +import AppError from "../../utils/api-error.js"; +import logger from "../../utils/logger.js"; + +/** + * Get user profile by ID. + */ +export const getUserById = async (userId) => { + const result = await query( + 'SELECT id, name, email, email_verified, image, created_at, updated_at FROM "user" WHERE id = $1 LIMIT 1', + [userId], + ); + if (result.rows.length === 0) { + throw new AppError("User not found", 404); + } + return result.rows[0]; +}; + +/** + * Update user profile. + */ +export const updateUser = async (userId, { name, image }) => { + const fields = []; + const values = []; + let idx = 1; + + if (name !== undefined) { + fields.push(`name = $${idx++}`); + values.push(name); + } + if (image !== undefined) { + fields.push(`image = $${idx++}`); + values.push(image); + } + + if (fields.length === 0) { + throw new AppError("No fields to update", 400); + } + + values.push(userId); + const result = await query( + `UPDATE "user" SET ${fields.join(", ")} WHERE id = $${idx} RETURNING id, name, email, image, updated_at`, + values, + ); + + if (result.rows.length === 0) { + throw new AppError("User not found", 404); + } + + logger.info("User profile updated", { userId }); + return result.rows[0]; +}; diff --git a/nodebase_backend/src/modules/webhooks/webhooks.controller.js b/nodebase_backend/src/modules/webhooks/webhooks.controller.js new file mode 100644 index 0000000..ecda0c3 --- /dev/null +++ b/nodebase_backend/src/modules/webhooks/webhooks.controller.js @@ -0,0 +1,110 @@ +import { query } from "../../config/db.js"; +import * as executionsService from "../executions/executions.service.js"; +import { inngest } from "../../inngest/client.js"; +import catchAsync from "../../utils/catch-async.js"; +import ApiResponse from "../../utils/api-response.js"; +import AppError from "../../utils/api-error.js"; +import logger from "../../utils/logger.js"; + +/** + * Look up a workflow and its owner by workflow ID. + * Used by webhook handlers (no auth token available). + */ +const getWorkflowOwner = async (workflowId) => { + const result = await query( + 'SELECT id, user_id FROM "workflow" WHERE id = $1', + [workflowId], + ); + if (result.rows.length === 0) { + throw new AppError("Workflow not found", 404); + } + return result.rows[0]; +}; + +/** + * Shared helper: create an execution and fire the Inngest event + * with the trigger payload attached. + */ +const triggerWorkflowExecution = async (workflowId, userId, triggerPayload) => { + const execution = await executionsService.createExecution( + userId, + workflowId, + ); + + await inngest.send({ + name: "workflow/execute", + data: { + executionId: execution.id, + workflowId, + userId, + triggerPayload, + }, + }); + + logger.info("Webhook triggered workflow execution", { + workflowId, + executionId: execution.id, + }); + + return execution; +}; + +/** + * POST /api/webhooks/google-form?workflowId=... + * Called by Google Forms (via Apps Script) on submission. + */ +export const handleGoogleFormWebhook = catchAsync(async (req, res) => { + const { workflowId } = req.query; + if (!workflowId) { + throw new AppError("workflowId query parameter is required", 400); + } + + const workflow = await getWorkflowOwner(workflowId); + + const execution = await triggerWorkflowExecution( + workflow.id, + workflow.user_id, + { + source: "google-form", + formData: req.body, + receivedAt: new Date().toISOString(), + }, + ); + + ApiResponse.success( + res, + { executionId: execution.id }, + "Workflow execution triggered", + 202, + ); +}); + +/** + * POST /api/webhooks/stripe?workflowId=... + * Called by Stripe when an event fires. + */ +export const handleStripeWebhook = catchAsync(async (req, res) => { + const { workflowId } = req.query; + if (!workflowId) { + throw new AppError("workflowId query parameter is required", 400); + } + + const workflow = await getWorkflowOwner(workflowId); + + const execution = await triggerWorkflowExecution( + workflow.id, + workflow.user_id, + { + source: "stripe", + event: req.body, + receivedAt: new Date().toISOString(), + }, + ); + + ApiResponse.success( + res, + { executionId: execution.id }, + "Workflow execution triggered", + 202, + ); +}); diff --git a/nodebase_backend/src/modules/webhooks/webhooks.routes.js b/nodebase_backend/src/modules/webhooks/webhooks.routes.js new file mode 100644 index 0000000..cd9c045 --- /dev/null +++ b/nodebase_backend/src/modules/webhooks/webhooks.routes.js @@ -0,0 +1,12 @@ +import { Router } from "express"; +import * as webhooksController from "./webhooks.controller.js"; + +const router = Router(); + +// Google Form submission webhook +router.post("/google-form", webhooksController.handleGoogleFormWebhook); + +// Stripe event webhook +router.post("/stripe", webhooksController.handleStripeWebhook); + +export default router; diff --git a/nodebase_backend/src/modules/workflows/workflows.controller.js b/nodebase_backend/src/modules/workflows/workflows.controller.js new file mode 100644 index 0000000..0378ef1 --- /dev/null +++ b/nodebase_backend/src/modules/workflows/workflows.controller.js @@ -0,0 +1,107 @@ +import * as workflowsService from "./workflows.service.js"; +import * as executionsService from "../executions/executions.service.js"; +import { inngest } from "../../inngest/client.js"; +import { sseManager } from "../executions/sse.js"; +import catchAsync from "../../utils/catch-async.js"; +import ApiResponse from "../../utils/api-response.js"; + +export const getWorkflows = catchAsync(async (req, res) => { + const { page, pageSize } = req.query; + const data = await workflowsService.getWorkflows(req.user.id, { + page: page ? parseInt(page, 10) : undefined, + pageSize: pageSize ? parseInt(pageSize, 10) : undefined, + }); + ApiResponse.success(res, data); +}); + +export const getWorkflow = catchAsync(async (req, res) => { + const workflow = await workflowsService.getWorkflowById( + req.params.id, + req.user.id, + ); + ApiResponse.success(res, { workflow }); +}); + +export const createWorkflow = catchAsync(async (req, res) => { + const workflow = await workflowsService.createWorkflow(req.user.id, req.body); + ApiResponse.success(res, { workflow }, "Workflow created", 201); +}); + +export const updateWorkflowName = catchAsync(async (req, res) => { + const workflow = await workflowsService.updateWorkflowName( + req.params.id, + req.user.id, + req.body, + ); + ApiResponse.success(res, { workflow }, "Workflow name updated"); +}); + +export const saveWorkflow = catchAsync(async (req, res) => { + const workflow = await workflowsService.saveWorkflow( + req.params.id, + req.user.id, + req.body, + ); + ApiResponse.success(res, { workflow }, "Workflow saved"); +}); + +export const removeWorkflow = catchAsync(async (req, res) => { + await workflowsService.removeWorkflow(req.params.id, req.user.id); + ApiResponse.success(res, null, "Workflow deleted"); +}); + +/** + * POST /api/workflows/:id/execute + * Creates an execution row, fires an Inngest event, returns immediately. + */ +export const executeWorkflow = catchAsync(async (req, res) => { + // Verify ownership + await workflowsService.getWorkflowById(req.params.id, req.user.id); + + // Create the execution row (RUNNING) + const execution = await executionsService.createExecution( + req.user.id, + req.params.id, + ); + + // Fire the Inngest event — actual execution happens in the background + await inngest.send({ + name: "workflow/execute", + data: { + executionId: execution.id, + workflowId: req.params.id, + userId: req.user.id, + }, + }); + + ApiResponse.success(res, { execution }, "Workflow execution started", 202); +}); + +/** + * GET /api/workflows/:id/stream — workflow-level SSE. + * Lets an open editor know when any execution starts on this workflow + * (e.g. triggered by a webhook rather than the Execute button). + */ +export const streamWorkflow = catchAsync(async (req, res) => { + // Verify ownership + await workflowsService.getWorkflowById(req.params.id, req.user.id); + + const workflowId = req.params.id; + + // SSE headers + res.writeHead(200, { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache", + Connection: "keep-alive", + }); + + // Send initial connected event + res.write(`event: connected\ndata: ${JSON.stringify({ workflowId })}\n\n`); + + sseManager.addWorkflow(workflowId, res); + + // Clean up when the client disconnects + req.on("close", () => { + sseManager.removeWorkflow(workflowId, res); + }); +}); diff --git a/nodebase_backend/src/modules/workflows/workflows.routes.js b/nodebase_backend/src/modules/workflows/workflows.routes.js new file mode 100644 index 0000000..c969069 --- /dev/null +++ b/nodebase_backend/src/modules/workflows/workflows.routes.js @@ -0,0 +1,36 @@ +import { Router } from "express"; +import * as workflowsController from "./workflows.controller.js"; +import verifyToken from "../../middleware/auth.js"; +import validate from "../../middleware/validate.js"; +import { + createWorkflowSchema, + updateWorkflowNameSchema, + saveWorkflowSchema, +} from "./workflows.validation.js"; + +const router = Router(); + +router.use(verifyToken); + +router.get("/", workflowsController.getWorkflows); +router.post( + "/", + validate(createWorkflowSchema), + workflowsController.createWorkflow, +); +router.get("/:id", workflowsController.getWorkflow); +router.patch( + "/:id/name", + validate(updateWorkflowNameSchema), + workflowsController.updateWorkflowName, +); +router.put( + "/:id", + validate(saveWorkflowSchema), + workflowsController.saveWorkflow, +); +router.delete("/:id", workflowsController.removeWorkflow); +router.post("/:id/execute", workflowsController.executeWorkflow); +router.get("/:id/stream", workflowsController.streamWorkflow); + +export default router; diff --git a/nodebase_backend/src/modules/workflows/workflows.service.js b/nodebase_backend/src/modules/workflows/workflows.service.js new file mode 100644 index 0000000..1e94e0f --- /dev/null +++ b/nodebase_backend/src/modules/workflows/workflows.service.js @@ -0,0 +1,197 @@ +import { query } from "../../config/db.js"; +import AppError from "../../utils/api-error.js"; +import { PAGINATION } from "../../config/constants.js"; +import withTransaction from "../../utils/transaction.js"; +import logger from "../../utils/logger.js"; + +/** + * List all workflows for a user (paginated). + */ +export const getWorkflows = async ( + userId, + { + page = PAGINATION.DEFAULT_PAGE, + pageSize = PAGINATION.DEFAULT_PAGE_SIZE, + } = {}, +) => { + const offset = (page - 1) * pageSize; + + const [dataResult, countResult] = await Promise.all([ + query( + `SELECT id, name, created_at, updated_at FROM "workflow" WHERE user_id = $1 ORDER BY updated_at DESC LIMIT $2 OFFSET $3`, + [userId, pageSize, offset], + ), + query('SELECT COUNT(*) FROM "workflow" WHERE user_id = $1', [userId]), + ]); + + return { + workflows: dataResult.rows, + total: parseInt(countResult.rows[0].count, 10), + page, + pageSize, + }; +}; + +/** + * Get a single workflow with its nodes and connections. + */ +export const getWorkflowById = async (workflowId, userId) => { + const result = await query( + 'SELECT id, name, created_at, updated_at FROM "workflow" WHERE id = $1 AND user_id = $2', + [workflowId, userId], + ); + if (result.rows.length === 0) { + throw new AppError("Workflow not found", 404); + } + + const workflow = result.rows[0]; + + const [nodesResult, connectionsResult] = await Promise.all([ + query( + `SELECT id, name, type, position, data, credential_id, created_at, updated_at FROM "node" WHERE workflow_id = $1 ORDER BY created_at ASC`, + [workflowId], + ), + query( + `SELECT id, from_node_id, to_node_id, from_output, to_input FROM "connection" WHERE workflow_id = $1`, + [workflowId], + ), + ]); + + return { + ...workflow, + nodes: nodesResult.rows, + connections: connectionsResult.rows, + }; +}; + +/** + * Create a new workflow. + */ +export const createWorkflow = async (userId, { name }) => { + const workflow = await withTransaction(userId, async (client) => { + const result = await client.query( + `INSERT INTO "workflow" (name, user_id) VALUES ($1, $2) RETURNING id, name, created_at, updated_at`, + [name, userId], + ); + return result.rows[0]; + }); + + logger.info("Workflow created", { workflowId: workflow.id }); + return workflow; +}; + +/** + * Update workflow name. + */ +export const updateWorkflowName = async (workflowId, userId, { name }) => { + const workflow = await withTransaction(userId, async (client) => { + const result = await client.query( + `UPDATE "workflow" SET name = $1 WHERE id = $2 AND user_id = $3 RETURNING id, name, updated_at`, + [name, workflowId, userId], + ); + if (result.rows.length === 0) { + throw new AppError("Workflow not found", 404); + } + return result.rows[0]; + }); + + logger.info("Workflow name updated", { workflowId }); + return workflow; +}; + +/** + * Save the full workflow graph (nodes + connections) in a single transaction. + * Deletes all existing nodes/connections and re-inserts the provided ones. + */ +export const saveWorkflow = async ( + workflowId, + userId, + { nodes, connections }, +) => { + const workflow = await withTransaction(userId, async (client) => { + // Verify ownership + const wfResult = await client.query( + 'SELECT id FROM "workflow" WHERE id = $1 AND user_id = $2', + [workflowId, userId], + ); + if (wfResult.rows.length === 0) { + throw new AppError("Workflow not found", 404); + } + + // Wipe existing graph (connections first due to FK) + await client.query('DELETE FROM "connection" WHERE workflow_id = $1', [ + workflowId, + ]); + await client.query('DELETE FROM "node" WHERE workflow_id = $1', [ + workflowId, + ]); + + // Insert nodes + for (const n of nodes) { + await client.query( + `INSERT INTO "node" (id, workflow_id, name, type, position, data, credential_id) + VALUES ($1, $2, $3, $4, $5, $6, $7)`, + [ + n.id, + workflowId, + n.name || "", + n.type, + JSON.stringify(n.position), + JSON.stringify(n.data || {}), + n.credential_id || null, + ], + ); + } + + // Insert connections + for (const c of connections) { + await client.query( + `INSERT INTO "connection" (id, workflow_id, from_node_id, to_node_id, from_output, to_input) + VALUES ($1, $2, $3, $4, $5, $6)`, + [ + c.id, + workflowId, + c.from_node_id, + c.to_node_id, + c.from_output || "main", + c.to_input || "main", + ], + ); + } + + // Touch updated_at + await client.query( + 'UPDATE "workflow" SET updated_at = now() WHERE id = $1 RETURNING id, name, created_at, updated_at', + [workflowId], + ); + + return wfResult.rows[0]; + }); + + // Return the full graph after save + const saved = await getWorkflowById(workflowId, userId); + logger.info("Workflow saved", { + workflowId, + nodeCount: nodes.length, + connectionCount: connections.length, + }); + return saved; +}; + +/** + * Delete a workflow. + */ +export const removeWorkflow = async (workflowId, userId) => { + await withTransaction(userId, async (client) => { + const result = await client.query( + `DELETE FROM "workflow" WHERE id = $1 AND user_id = $2 RETURNING id`, + [workflowId, userId], + ); + if (result.rows.length === 0) { + throw new AppError("Workflow not found", 404); + } + }); + + logger.info("Workflow deleted", { workflowId }); + return { id: workflowId }; +}; diff --git a/nodebase_backend/src/modules/workflows/workflows.validation.js b/nodebase_backend/src/modules/workflows/workflows.validation.js new file mode 100644 index 0000000..448e479 --- /dev/null +++ b/nodebase_backend/src/modules/workflows/workflows.validation.js @@ -0,0 +1,31 @@ +import { z } from "zod"; + +export const createWorkflowSchema = z.object({ + name: z.string().min(1, "Workflow name is required").max(255), +}); + +export const saveWorkflowSchema = z.object({ + nodes: z.array( + z.object({ + id: z.string().min(1), + type: z.string().min(1), + name: z.string().default(""), + position: z.object({ x: z.number(), y: z.number() }), + data: z.record(z.string(), z.any()).default({}), + credential_id: z.string().nullable().optional(), + }), + ), + connections: z.array( + z.object({ + id: z.string().min(1), + from_node_id: z.string().min(1), + to_node_id: z.string().min(1), + from_output: z.string().default("main"), + to_input: z.string().default("main"), + }), + ), +}); + +export const updateWorkflowNameSchema = z.object({ + name: z.string().min(1, "Name is required").max(255), +}); diff --git a/nodebase_backend/src/scripts/000_create_extensions.sql b/nodebase_backend/src/scripts/000_create_extensions.sql new file mode 100644 index 0000000..10a3a50 --- /dev/null +++ b/nodebase_backend/src/scripts/000_create_extensions.sql @@ -0,0 +1,9 @@ +-- ============================================================ +-- 000_create_extensions.sql +-- Enable required PostgreSQL extensions +-- ============================================================ + +CREATE EXTENSION IF NOT EXISTS "pgcrypto"; +-- gen_random_uuid() +CREATE EXTENSION IF NOT EXISTS "pg_trgm"; +-- trigram-based text search (future use) \ No newline at end of file diff --git a/nodebase_backend/src/scripts/001_create_enums.sql b/nodebase_backend/src/scripts/001_create_enums.sql new file mode 100644 index 0000000..921cb67 --- /dev/null +++ b/nodebase_backend/src/scripts/001_create_enums.sql @@ -0,0 +1,39 @@ +-- ============================================================ +-- 001_create_enums.sql +-- Custom enum types used across multiple tables +-- ============================================================ + +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'node_type') THEN + CREATE TYPE node_type AS ENUM ( + 'INITIAL', + 'MANUAL_TRIGGER', + 'HTTP_REQUEST', + 'GOOGLE_FORM_TRIGGER', + 'STRIPE_TRIGGER', + 'ANTHROPIC', + 'GEMINI', + 'OPENAI', + 'DISCORD', + 'SLACK' + ); + END IF; + + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'credential_type') THEN + CREATE TYPE credential_type AS ENUM ( + 'OPENAI', + 'ANTHROPIC', + 'GEMINI' + ); + END IF; + + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'execution_status') THEN + CREATE TYPE execution_status AS ENUM ( + 'RUNNING', + 'SUCCESS', + 'FAILED' + ); + END IF; +END +$$; \ No newline at end of file diff --git a/nodebase_backend/src/scripts/002_create_users.sql b/nodebase_backend/src/scripts/002_create_users.sql new file mode 100644 index 0000000..d7ddc98 --- /dev/null +++ b/nodebase_backend/src/scripts/002_create_users.sql @@ -0,0 +1,53 @@ +-- ============================================================ +-- 002_create_users.sql +-- Users table + updated_at trigger function (reused by all tables) +-- ============================================================ + +-- ── Reusable trigger function: auto-set updated_at ────────── +CREATE OR REPLACE FUNCTION fn_set_updated_at() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- ── Table ─────────────────────────────────────────────────── +CREATE TABLE IF NOT EXISTS "user" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + name TEXT NOT NULL, + email TEXT NOT NULL, + email_verified BOOLEAN NOT NULL DEFAULT false, + image TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- ── Unique constraint ─────────────────────────────────────── +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint WHERE conname = 'user_email_unique' + ) THEN + ALTER TABLE "user" ADD CONSTRAINT user_email_unique UNIQUE (email); + END IF; +END $$; + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_users_email ON "user" (email); + +-- ── Trigger ───────────────────────────────────────────────── +DROP TRIGGER IF EXISTS trg_user_updated_at ON "user"; + +CREATE TRIGGER trg_user_updated_at + BEFORE UPDATE ON "user" + FOR EACH ROW + EXECUTE FUNCTION fn_set_updated_at(); + +-- ── Row Level Security ────────────────────────────────────── +ALTER TABLE "user" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS users_own_data ON "user"; + +CREATE POLICY users_own_data ON "user" + USING (id = current_setting('app.current_user_id', true)::text); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/003_create_sessions.sql b/nodebase_backend/src/scripts/003_create_sessions.sql new file mode 100644 index 0000000..0e8e8c1 --- /dev/null +++ b/nodebase_backend/src/scripts/003_create_sessions.sql @@ -0,0 +1,46 @@ +-- ============================================================ +-- 003_create_sessions.sql +-- Sessions table for auth token management +-- ============================================================ + +CREATE TABLE IF NOT EXISTS "session" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + expires_at TIMESTAMPTZ NOT NULL, + token TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), + ip_address TEXT, + user_agent TEXT, + user_id TEXT NOT NULL REFERENCES "user" (id) ON DELETE CASCADE +); + +-- ── Unique constraint ─────────────────────────────────────── +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint WHERE conname = 'session_token_unique' + ) THEN + ALTER TABLE "session" ADD CONSTRAINT session_token_unique UNIQUE (token); + END IF; +END $$; + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_sessions_token ON "session" (token); + +CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON "session" (user_id); + +-- ── Trigger ───────────────────────────────────────────────── +DROP TRIGGER IF EXISTS trg_session_updated_at ON "session"; + +CREATE TRIGGER trg_session_updated_at + BEFORE UPDATE ON "session" + FOR EACH ROW + EXECUTE FUNCTION fn_set_updated_at(); + +-- ── Row Level Security ────────────────────────────────────── +ALTER TABLE "session" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS sessions_own_data ON "session"; + +CREATE POLICY sessions_own_data ON "session" + USING (user_id = current_setting('app.current_user_id', true)::text); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/004_create_accounts.sql b/nodebase_backend/src/scripts/004_create_accounts.sql new file mode 100644 index 0000000..6b4fca1 --- /dev/null +++ b/nodebase_backend/src/scripts/004_create_accounts.sql @@ -0,0 +1,41 @@ +-- ============================================================ +-- 004_create_accounts.sql +-- OAuth / provider accounts linked to users +-- ============================================================ + +CREATE TABLE IF NOT EXISTS "account" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + account_id TEXT NOT NULL, + provider_id TEXT NOT NULL, + user_id TEXT NOT NULL REFERENCES "user" (id) ON DELETE CASCADE, + access_token TEXT, + refresh_token TEXT, + id_token TEXT, + access_token_expires_at TIMESTAMPTZ, + refresh_token_expires_at TIMESTAMPTZ, + scope TEXT, + password TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_accounts_user_id ON "account" (user_id); + +CREATE INDEX IF NOT EXISTS idx_accounts_provider_id ON "account" (provider_id); + +-- ── Trigger ───────────────────────────────────────────────── +DROP TRIGGER IF EXISTS trg_account_updated_at ON "account"; + +CREATE TRIGGER trg_account_updated_at + BEFORE UPDATE ON "account" + FOR EACH ROW + EXECUTE FUNCTION fn_set_updated_at(); + +-- ── Row Level Security ────────────────────────────────────── +ALTER TABLE "account" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS accounts_own_data ON "account"; + +CREATE POLICY accounts_own_data ON "account" + USING (user_id = current_setting('app.current_user_id', true)::text); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/005_create_verifications.sql b/nodebase_backend/src/scripts/005_create_verifications.sql new file mode 100644 index 0000000..cc29d0a --- /dev/null +++ b/nodebase_backend/src/scripts/005_create_verifications.sql @@ -0,0 +1,24 @@ +-- ============================================================ +-- 005_create_verifications.sql +-- Verification tokens (email verification, password reset, etc.) +-- ============================================================ + +CREATE TABLE IF NOT EXISTS "verification" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + identifier TEXT NOT NULL, + value TEXT NOT NULL, + expires_at TIMESTAMPTZ NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_verifications_identifier ON "verification" (identifier); + +-- ── Trigger ───────────────────────────────────────────────── +DROP TRIGGER IF EXISTS trg_verification_updated_at ON "verification"; + +CREATE TRIGGER trg_verification_updated_at + BEFORE UPDATE ON "verification" + FOR EACH ROW + EXECUTE FUNCTION fn_set_updated_at(); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/006_create_credentials.sql b/nodebase_backend/src/scripts/006_create_credentials.sql new file mode 100644 index 0000000..1bdfc70 --- /dev/null +++ b/nodebase_backend/src/scripts/006_create_credentials.sql @@ -0,0 +1,35 @@ +-- ============================================================ +-- 006_create_credentials.sql +-- User credentials for third-party API keys (encrypted at rest) +-- ============================================================ + +CREATE TABLE IF NOT EXISTS "credential" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + name TEXT NOT NULL, + value TEXT NOT NULL, + type credential_type NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), + user_id TEXT NOT NULL REFERENCES "user" (id) ON DELETE CASCADE +); + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_credentials_user_id ON "credential" (user_id); + +CREATE INDEX IF NOT EXISTS idx_credentials_type ON "credential" (type); + +-- ── Trigger ───────────────────────────────────────────────── +DROP TRIGGER IF EXISTS trg_credential_updated_at ON "credential"; + +CREATE TRIGGER trg_credential_updated_at + BEFORE UPDATE ON "credential" + FOR EACH ROW + EXECUTE FUNCTION fn_set_updated_at(); + +-- ── Row Level Security ────────────────────────────────────── +ALTER TABLE "credential" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS credentials_own_data ON "credential"; + +CREATE POLICY credentials_own_data ON "credential" + USING (user_id = current_setting('app.current_user_id', true)::text); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/007_create_workflows.sql b/nodebase_backend/src/scripts/007_create_workflows.sql new file mode 100644 index 0000000..4cc4d1a --- /dev/null +++ b/nodebase_backend/src/scripts/007_create_workflows.sql @@ -0,0 +1,31 @@ +-- ============================================================ +-- 007_create_workflows.sql +-- Workflows owned by users +-- ============================================================ + +CREATE TABLE IF NOT EXISTS "workflow" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + name TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), + user_id TEXT NOT NULL REFERENCES "user" (id) ON DELETE CASCADE +); + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_workflows_user_id ON "workflow" (user_id); + +-- ── Trigger ───────────────────────────────────────────────── +DROP TRIGGER IF EXISTS trg_workflow_updated_at ON "workflow"; + +CREATE TRIGGER trg_workflow_updated_at + BEFORE UPDATE ON "workflow" + FOR EACH ROW + EXECUTE FUNCTION fn_set_updated_at(); + +-- ── Row Level Security ────────────────────────────────────── +ALTER TABLE "workflow" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS workflows_own_data ON "workflow"; + +CREATE POLICY workflows_own_data ON "workflow" + USING (user_id = current_setting('app.current_user_id', true)::text); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/008_create_nodes.sql b/nodebase_backend/src/scripts/008_create_nodes.sql new file mode 100644 index 0000000..921b802 --- /dev/null +++ b/nodebase_backend/src/scripts/008_create_nodes.sql @@ -0,0 +1,45 @@ +-- ============================================================ +-- 008_create_nodes.sql +-- Nodes within workflows +-- ============================================================ + +CREATE TABLE IF NOT EXISTS "node" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + workflow_id TEXT NOT NULL REFERENCES "workflow" (id) ON DELETE CASCADE, + name TEXT NOT NULL, + type node_type NOT NULL, + position JSONB NOT NULL, + data JSONB NOT NULL DEFAULT '{}', + credential_id TEXT REFERENCES "credential" (id) ON DELETE SET NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_nodes_workflow_id ON "node" (workflow_id); + +CREATE INDEX IF NOT EXISTS idx_nodes_credential_id ON "node" (credential_id); + +CREATE INDEX IF NOT EXISTS idx_nodes_type ON "node" (type); + +-- ── Trigger ───────────────────────────────────────────────── +DROP TRIGGER IF EXISTS trg_node_updated_at ON "node"; + +CREATE TRIGGER trg_node_updated_at + BEFORE UPDATE ON "node" + FOR EACH ROW + EXECUTE FUNCTION fn_set_updated_at(); + +-- ── Row Level Security ────────────────────────────────────── +ALTER TABLE "node" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS nodes_own_data ON "node"; + +CREATE POLICY nodes_own_data ON "node" + USING ( + EXISTS ( + SELECT 1 FROM "workflow" + WHERE "workflow".id = "node".workflow_id + AND "workflow".user_id = current_setting('app.current_user_id', true)::text + ) + ); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/009_create_connections.sql b/nodebase_backend/src/scripts/009_create_connections.sql new file mode 100644 index 0000000..f0d2c2e --- /dev/null +++ b/nodebase_backend/src/scripts/009_create_connections.sql @@ -0,0 +1,55 @@ +-- ============================================================ +-- 009_create_connections.sql +-- Edges between nodes in a workflow +-- ============================================================ + +CREATE TABLE IF NOT EXISTS "connection" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + workflow_id TEXT NOT NULL REFERENCES "workflow" (id) ON DELETE CASCADE, + from_node_id TEXT NOT NULL REFERENCES "node" (id) ON DELETE CASCADE, + to_node_id TEXT NOT NULL REFERENCES "node" (id) ON DELETE CASCADE, + from_output TEXT NOT NULL DEFAULT 'main', + to_input TEXT NOT NULL DEFAULT 'main', + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- ── Unique constraint ─────────────────────────────────────── +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint WHERE conname = 'connection_edge_unique' + ) THEN + ALTER TABLE "connection" ADD CONSTRAINT connection_edge_unique + UNIQUE (from_node_id, to_node_id, from_output, to_input); + END IF; +END $$; + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_connections_workflow_id ON "connection" (workflow_id); + +CREATE INDEX IF NOT EXISTS idx_connections_from_node_id ON "connection" (from_node_id); + +CREATE INDEX IF NOT EXISTS idx_connections_to_node_id ON "connection" (to_node_id); + +-- ── Trigger ───────────────────────────────────────────────── +DROP TRIGGER IF EXISTS trg_connection_updated_at ON "connection"; + +CREATE TRIGGER trg_connection_updated_at + BEFORE UPDATE ON "connection" + FOR EACH ROW + EXECUTE FUNCTION fn_set_updated_at(); + +-- ── Row Level Security ────────────────────────────────────── +ALTER TABLE "connection" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS connections_own_data ON "connection"; + +CREATE POLICY connections_own_data ON "connection" + USING ( + EXISTS ( + SELECT 1 FROM "workflow" + WHERE "workflow".id = "connection".workflow_id + AND "workflow".user_id = current_setting('app.current_user_id', true)::text + ) + ); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/010_create_executions.sql b/nodebase_backend/src/scripts/010_create_executions.sql new file mode 100644 index 0000000..8850541 --- /dev/null +++ b/nodebase_backend/src/scripts/010_create_executions.sql @@ -0,0 +1,34 @@ +-- ============================================================ +-- 010_create_executions.sql +-- Workflow execution records +-- ============================================================ + +CREATE TABLE IF NOT EXISTS "execution" ( + id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text, + workflow_id TEXT NOT NULL REFERENCES "workflow" (id) ON DELETE CASCADE, + status execution_status NOT NULL DEFAULT 'RUNNING', + error TEXT, + error_stack TEXT, + started_at TIMESTAMPTZ NOT NULL DEFAULT now(), + completed_at TIMESTAMPTZ, + trigger_event_id TEXT UNIQUE, + output JSONB +); + +-- ── Indexes ───────────────────────────────────────────────── +CREATE INDEX IF NOT EXISTS idx_executions_workflow_id ON "execution" (workflow_id); +CREATE INDEX IF NOT EXISTS idx_executions_status ON "execution" (status); +CREATE INDEX IF NOT EXISTS idx_executions_trigger_event_id ON "execution" (trigger_event_id); + +-- ── Row Level Security ────────────────────────────────────── +ALTER TABLE "execution" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS executions_own_data ON "execution"; +CREATE POLICY executions_own_data ON "execution" + USING ( + EXISTS ( + SELECT 1 FROM "workflow" + WHERE "workflow".id = "execution".workflow_id + AND "workflow".user_id = current_setting('app.current_user_id', true)::text + ) + ); diff --git a/nodebase_backend/src/scripts/011_create_node_executions.sql b/nodebase_backend/src/scripts/011_create_node_executions.sql new file mode 100644 index 0000000..4bf40f8 --- /dev/null +++ b/nodebase_backend/src/scripts/011_create_node_executions.sql @@ -0,0 +1,33 @@ +-- ─── Per-node execution tracking ──────────────────────────── + +CREATE TABLE IF NOT EXISTS "node_execution" ( + id TEXT DEFAULT gen_random_uuid()::text PRIMARY KEY, + execution_id TEXT NOT NULL REFERENCES "execution" (id) ON DELETE CASCADE, + node_id TEXT NOT NULL REFERENCES "node" (id) ON DELETE CASCADE, + status execution_status NOT NULL DEFAULT 'RUNNING', + output JSONB, + error TEXT, + started_at TIMESTAMPTZ NOT NULL DEFAULT now(), + completed_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- Fast look-ups: all node results for one execution, ordered by start time +CREATE INDEX IF NOT EXISTS idx_node_execution_execution ON "node_execution" (execution_id, started_at ASC); + +-- Fast look-ups by node +CREATE INDEX IF NOT EXISTS idx_node_execution_node ON "node_execution" (node_id); + +-- ─── RLS ──────────────────────────────────────────────────── +ALTER TABLE "node_execution" ENABLE ROW LEVEL SECURITY; + +DROP POLICY IF EXISTS node_execution_owner ON "node_execution"; + +CREATE POLICY node_execution_owner ON "node_execution" + USING ( + execution_id IN ( + SELECT e.id FROM "execution" e + JOIN "workflow" w ON w.id = e.workflow_id + WHERE w.user_id = current_setting('app.current_user_id', true)::text + ) + ); \ No newline at end of file diff --git a/nodebase_backend/src/scripts/migrate.js b/nodebase_backend/src/scripts/migrate.js new file mode 100644 index 0000000..1dc039d --- /dev/null +++ b/nodebase_backend/src/scripts/migrate.js @@ -0,0 +1,60 @@ +/** + * migrate.js — reads all .sql files in src/scripts/ in lexicographic order + * and executes them sequentially against the database. + * + * Usage: node src/scripts/migrate.js + */ + +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import pg from "pg"; +import dotenv from "dotenv"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Load env +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); + +const { Pool } = pg; +const pool = new Pool({ + connectionString: process.env.DATABASE_URL, + ssl: { rejectUnauthorized: false }, +}); + +async function migrate() { + const scriptsDir = __dirname; + + // Collect and sort .sql files + const files = fs + .readdirSync(scriptsDir) + .filter((f) => f.endsWith(".sql")) + .sort(); + + console.log(`\n🗂 Found ${files.length} migration file(s):\n`); + + const client = await pool.connect(); + + try { + for (const file of files) { + const filePath = path.join(scriptsDir, file); + const sql = fs.readFileSync(filePath, "utf-8"); + + console.log(` ▶ Running ${file} …`); + await client.query(sql); + console.log(` ✔ ${file} done.`); + } + + console.log("\n✅ All migrations completed successfully.\n"); + } catch (err) { + console.error(`\n❌ Migration failed:`, err.message); + console.error(err.stack); + process.exit(1); + } finally { + client.release(); + await pool.end(); + } +} + +migrate(); diff --git a/nodebase_backend/src/server.js b/nodebase_backend/src/server.js new file mode 100644 index 0000000..dca7048 --- /dev/null +++ b/nodebase_backend/src/server.js @@ -0,0 +1,11 @@ +import app from "./app.js"; +import env from "./config/env.js"; +import logger from "./utils/logger.js"; + +const PORT = env.PORT; + +app.listen(PORT, () => { + logger.info(`Nodebase API server running on http://localhost:${PORT}`, { + environment: env.NODE_ENV, + }); +}); diff --git a/nodebase_backend/src/utils/api-error.js b/nodebase_backend/src/utils/api-error.js new file mode 100644 index 0000000..01f200d --- /dev/null +++ b/nodebase_backend/src/utils/api-error.js @@ -0,0 +1,17 @@ +/** + * Custom operational error class for API responses. + */ +export class AppError extends Error { + /** + * @param {string} message Human-readable error message + * @param {number} statusCode HTTP status code (default 500) + */ + constructor(message, statusCode = 500) { + super(message); + this.statusCode = statusCode; + this.isOperational = true; + Error.captureStackTrace(this, this.constructor); + } +} + +export default AppError; diff --git a/nodebase_backend/src/utils/api-response.js b/nodebase_backend/src/utils/api-response.js new file mode 100644 index 0000000..da4323d --- /dev/null +++ b/nodebase_backend/src/utils/api-response.js @@ -0,0 +1,25 @@ +/** + * Unified API response helper. + * + * Usage: + * ApiResponse.success(res, { user }, "Login successful"); + * ApiResponse.success(res, { workflow }, "Workflow created", 201); + * ApiResponse.success(res, null, "Deleted"); + */ +class ApiResponse { + /** + * Send a standardised success JSON response. + * + * @param {import('express').Response} res + * @param {object|null} [data=null] Payload to include under `data` key + * @param {string} [message="Success"] Human-readable message + * @param {number} [statusCode=200] HTTP status code + */ + static success(res, data = null, message = "Success", statusCode = 200) { + const body = { success: true, message }; + if (data !== null) body.data = data; + return res.status(statusCode).json(body); + } +} + +export default ApiResponse; diff --git a/nodebase_backend/src/utils/catch-async.js b/nodebase_backend/src/utils/catch-async.js new file mode 100644 index 0000000..3313545 --- /dev/null +++ b/nodebase_backend/src/utils/catch-async.js @@ -0,0 +1,10 @@ +/** + * Wraps an async route handler so thrown errors are forwarded to next(). + * @param {Function} fn Async (req, res, next) => Promise + * @returns {Function} + */ +const catchAsync = (fn) => (req, res, next) => { + Promise.resolve(fn(req, res, next)).catch(next); +}; + +export default catchAsync; diff --git a/nodebase_backend/src/utils/encryption.js b/nodebase_backend/src/utils/encryption.js new file mode 100644 index 0000000..2a147c2 --- /dev/null +++ b/nodebase_backend/src/utils/encryption.js @@ -0,0 +1,57 @@ +import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto"; +import env from "../config/env.js"; + +const ALGORITHM = "aes-256-gcm"; +const IV_LENGTH = 16; +const AUTH_TAG_LENGTH = 16; + +/** + * Get the encryption key as a Buffer (32 bytes for AES-256). + */ +const getKey = () => { + const hex = env.ENCRYPTION_KEY; + if (!hex || hex.length !== 64) { + throw new Error( + "ENCRYPTION_KEY must be a 64-character hex string (32 bytes).", + ); + } + return Buffer.from(hex, "hex"); +}; + +/** + * Encrypt a plaintext string using AES-256-GCM. + * Returns a compact string: iv:authTag:ciphertext (all hex-encoded). + */ +export const encrypt = (plaintext) => { + const key = getKey(); + const iv = randomBytes(IV_LENGTH); + const cipher = createCipheriv(ALGORITHM, key, iv); + + let encrypted = cipher.update(plaintext, "utf8", "hex"); + encrypted += cipher.final("hex"); + const authTag = cipher.getAuthTag().toString("hex"); + + return `${iv.toString("hex")}:${authTag}:${encrypted}`; +}; + +/** + * Decrypt a value previously encrypted with `encrypt()`. + * Expects input format: iv:authTag:ciphertext (all hex-encoded). + */ +export const decrypt = (encryptedString) => { + const key = getKey(); + const [ivHex, authTagHex, ciphertext] = encryptedString.split(":"); + + if (!ivHex || !authTagHex || !ciphertext) { + throw new Error("Invalid encrypted value format."); + } + + const iv = Buffer.from(ivHex, "hex"); + const authTag = Buffer.from(authTagHex, "hex"); + const decipher = createDecipheriv(ALGORITHM, key, iv); + decipher.setAuthTag(authTag); + + let decrypted = decipher.update(ciphertext, "hex", "utf8"); + decrypted += decipher.final("utf8"); + return decrypted; +}; diff --git a/nodebase_backend/src/utils/logger.js b/nodebase_backend/src/utils/logger.js new file mode 100644 index 0000000..353759c --- /dev/null +++ b/nodebase_backend/src/utils/logger.js @@ -0,0 +1,94 @@ +import env from "../config/env.js"; + +// ─── Sensitive keys to redact in logged objects +const SENSITIVE_KEYS = new Set([ + "password", + "token", + "secret", + "authorization", + "cookie", + "access_token", + "refresh_token", + "id_token", + "creditcard", + "jwt_secret", + "database_url", + "value", // credential values +]); + +/** + * Deep-clone an object and replace sensitive field values with "[REDACTED]". + */ +function redact(obj) { + if (obj === null || obj === undefined) return obj; + if (typeof obj !== "object") return obj; + + if (Array.isArray(obj)) return obj.map(redact); + + const clean = {}; + for (const [key, val] of Object.entries(obj)) { + if (SENSITIVE_KEYS.has(key.toLowerCase())) { + clean[key] = "[REDACTED]"; + } else if (typeof val === "object" && val !== null) { + clean[key] = redact(val); + } else { + clean[key] = val; + } + } + return clean; +} + +// ─── Log levels +const LEVELS = { error: 0, warn: 1, info: 2, http: 3, debug: 4 }; +const CURRENT_LEVEL = env.isDev ? LEVELS.debug : LEVELS.info; + +function timestamp() { + return new Date().toISOString(); +} + +function formatMessage(level, message, meta) { + const base = `[${timestamp()}] [${level.toUpperCase()}] ${message}`; + if (meta && Object.keys(meta).length > 0) { + return `${base} ${JSON.stringify(redact(meta))}`; + } + return base; +} + +// ─── Logger + +const logger = { + error(message, meta = {}) { + if (CURRENT_LEVEL >= LEVELS.error) { + console.error(formatMessage("error", message, meta)); + } + }, + + warn(message, meta = {}) { + if (CURRENT_LEVEL >= LEVELS.warn) { + console.warn(formatMessage("warn", message, meta)); + } + }, + + info(message, meta = {}) { + if (CURRENT_LEVEL >= LEVELS.info) { + console.log(formatMessage("info", message, meta)); + } + }, + + http(message, meta = {}) { + if (CURRENT_LEVEL >= LEVELS.http) { + console.log(formatMessage("http", message, meta)); + } + }, + + debug(message, meta = {}) { + if (CURRENT_LEVEL >= LEVELS.debug) { + console.log(formatMessage("debug", message, meta)); + } + }, + + /** Redact an object (useful externally). */ + redact, +}; + +export default logger; diff --git a/nodebase_backend/src/utils/transaction.js b/nodebase_backend/src/utils/transaction.js new file mode 100644 index 0000000..7229194 --- /dev/null +++ b/nodebase_backend/src/utils/transaction.js @@ -0,0 +1,45 @@ +import { getClient } from "../config/db.js"; +import logger from "./logger.js"; + +/** + * Execute a callback inside a database transaction with optional RLS enforcement. + * + * When `userId` is provided, sets `SET LOCAL app.current_user_id` so that + * PostgreSQL Row-Level Security policies are enforced for every query + * within the transaction. + * + * @param {string|null} userId The authenticated user's ID (null to skip RLS) + * @param {(client: import('pg').PoolClient) => Promise} callback + * @returns {Promise} + * @template T + */ +export const withTransaction = async (userId, callback) => { + const client = await getClient(); + + try { + await client.query("BEGIN"); + + // Enforce RLS by setting the current user for this transaction + if (userId) { + await client.query( + `SET LOCAL app.current_user_id = ${client.escapeLiteral(String(userId))}`, + ); + } + + const result = await callback(client); + + await client.query("COMMIT"); + return result; + } catch (err) { + await client.query("ROLLBACK"); + logger.error("Transaction rolled back", { + userId: userId || "none", + error: err.message, + }); + throw err; + } finally { + client.release(); + } +}; + +export default withTransaction; diff --git a/package-lock.json b/package-lock.json index d42f2a4..07bc1c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,15 +8,8 @@ "name": "nodebase", "version": "0.1.0", "dependencies": { - "@ai-sdk/anthropic": "^2.0.23", - "@ai-sdk/google": "^2.0.17", - "@ai-sdk/openai": "^2.0.44", "@hookform/resolvers": "^5.2.2", - "@inngest/realtime": "^0.4.4", "@paralleldrive/cuid2": "^2.2.2", - "@polar-sh/better-auth": "^1.1.9", - "@polar-sh/sdk": "^0.35.4", - "@prisma/client": "^6.16.3", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-aspect-ratio": "^1.1.7", @@ -43,24 +36,14 @@ "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", - "@sentry/nextjs": "^10.18.0", "@tanstack/react-query": "^5.90.2", - "@trpc/client": "^11.6.0", - "@trpc/server": "^11.6.0", - "@trpc/tanstack-react-query": "^11.6.0", "@xyflow/react": "^12.8.6", - "ai": "^5.0.60", - "better-auth": "^1.3.26", "class-variance-authority": "^0.7.1", "client-only": "^0.0.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", - "cryptr": "^6.4.0", "date-fns": "^4.1.0", "embla-carousel-react": "^8.6.0", - "handlebars": "^4.7.8", - "html-entities": "^2.6.0", - "inngest": "^3.44.1", "input-otp": "^1.4.2", "jotai": "^2.15.0", "ky": "^1.12.0", @@ -76,11 +59,8 @@ "react-hook-form": "^7.64.0", "react-resizable-panels": "^3.0.6", "recharts": "^2.15.4", - "server-only": "^0.0.1", "sonner": "^2.0.7", - "superjson": "^2.2.2", "tailwind-merge": "^3.3.1", - "toposort": "^2.0.2", "vaul": "^1.1.2", "zod": "^4.1.11" }, @@ -90,111 +70,12 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "@types/toposort": "^2.0.7", - "dotenv-cli": "^10.0.0", - "inngest-cli": "^1.12.1", - "mprocs": "^0.7.3", - "prisma": "^6.16.3", "tailwindcss": "^4", "tsx": "^4.20.6", "tw-animate-css": "^1.4.0", "typescript": "^5" } }, - "node_modules/@ai-sdk/anthropic": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/@ai-sdk/anthropic/-/anthropic-2.0.23.tgz", - "integrity": "sha512-ZEBiiv1UhjGjBwUU63pFhLK5LCSlNDb1idY9K1oZHm5/Fda1cuTojf32tOp0opH0RPbPAN/F8fyyNjbU33n9Kw==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/gateway": { - "version": "1.0.33", - "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-1.0.33.tgz", - "integrity": "sha512-v9i3GPEo4t3fGcSkQkc07xM6KJN75VUv7C1Mqmmsu2xD8lQwnQfsrgAXyNuWe20yGY0eHuheSPDZhiqsGKtH1g==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.10", - "@vercel/oidc": "^3.0.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/google": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-2.0.17.tgz", - "integrity": "sha512-6LyuUrCZuiULg0rUV+kT4T2jG19oUntudorI4ttv1ARkSbwl8A39ue3rA487aDDy6fUScdbGFiV5Yv/o4gidVA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/openai": { - "version": "2.0.44", - "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-2.0.44.tgz", - "integrity": "sha512-caK9v5YbBd38mjPmjBP5LSWiWhmHgK9mPwc7dE/3ED3c+SypH6/QWimGDA1oSsxDEdXgVCO9ORUVV+Uphzjf8Q==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/@ai-sdk/provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.0.tgz", - "integrity": "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==", - "license": "Apache-2.0", - "dependencies": { - "json-schema": "^0.4.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ai-sdk/provider-utils": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.10.tgz", - "integrity": "sha512-T1gZ76gEIwffep6MWI0QNy9jgoybUHE7TRaHB5k54K8mF91ciGFlbtCGxDYhMH3nCRergKwYFIDeFF0hJSIQHQ==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/provider": "2.0.0", - "@standard-schema/spec": "^1.0.0", - "eventsource-parser": "^3.0.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -208,220 +89,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@apm-js-collab/code-transformer": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@apm-js-collab/code-transformer/-/code-transformer-0.8.2.tgz", - "integrity": "sha512-YRjJjNq5KFSjDUoqu5pFUWrrsvGOxl6c3bu+uMFc9HNNptZ2rNU/TI2nLw4jnhQNtka972Ee2m3uqbvDQtPeCA==", - "license": "Apache-2.0" - }, - "node_modules/@apm-js-collab/tracing-hooks": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@apm-js-collab/tracing-hooks/-/tracing-hooks-0.3.1.tgz", - "integrity": "sha512-Vu1CbmPURlN5fTboVuKMoJjbO5qcq9fA5YXpskx3dXe/zTBvjODFoerw+69rVBlRLrJpwPqSDqEuJDEKIrTldw==", - "license": "Apache-2.0", - "dependencies": { - "@apm-js-collab/code-transformer": "^0.8.0", - "debug": "^4.4.1", - "module-details-from-path": "^1.0.4" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.4" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/runtime": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", @@ -431,71 +98,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@better-auth/core": { - "version": "1.3.26", - "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.3.26.tgz", - "integrity": "sha512-S5ooXaOcn9eLV3/JayfbMsAB5PkfoTRaRrtpb5djwvI/UAJOgLyjqhd+rObsBycovQ/nPQvMKjzyM/G1oBKngA==", - "dependencies": { - "better-call": "1.0.19", - "zod": "^4.1.5" - } - }, - "node_modules/@better-auth/utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==", - "license": "MIT" - }, - "node_modules/@better-fetch/fetch": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.18.tgz", - "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==" - }, "node_modules/@biomejs/biome": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.0.tgz", @@ -659,12 +261,6 @@ "node": ">=14.21.3" } }, - "node_modules/@bufbuild/protobuf": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.9.0.tgz", - "integrity": "sha512-rnJenoStJ8nvmt9Gzye8nkYd6V22xUAnu4086ER7h1zJ508vStko4pMvDeQ446ilDTFpV5wnoc5YS7XvMwwMqA==", - "license": "(Apache-2.0 AND BSD-3-Clause)" - }, "node_modules/@date-fns/tz": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz", @@ -1161,43 +757,6 @@ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, - "node_modules/@grpc/grpc-js": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.0.tgz", - "integrity": "sha512-N8Jx6PaYzcTRNzirReJCtADVoq4z7+1KQ4E70jTg/koQiMoUSN1kbNjPOqpPbhMFhfU1/l7ixspPl8dNY+FoUg==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.8.0", - "@js-sdsl/ordered-map": "^4.4.2" - }, - "engines": { - "node": ">=12.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz", - "integrity": "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.5.3", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@hexagon/base64": { - "version": "1.1.28", - "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz", - "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==", - "license": "MIT" - }, "node_modules/@hookform/resolvers": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz", @@ -1638,49 +1197,6 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@inngest/ai": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@inngest/ai/-/ai-0.1.6.tgz", - "integrity": "sha512-4hIvD87LnMFSphkbSToB1EkE9epktyZU2xUj6OFCCj/bn379KfbZbhWcCJEyso0P9Ux4vsNTxiSu9E7JSI9HCQ==", - "license": "Apache-2.0", - "dependencies": { - "@types/node": "^22.10.5", - "typescript": "^5.7.3" - } - }, - "node_modules/@inngest/ai/node_modules/@types/node": { - "version": "22.18.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.8.tgz", - "integrity": "sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@inngest/realtime": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@inngest/realtime/-/realtime-0.4.4.tgz", - "integrity": "sha512-8s/JTZ19trHYX3c5Fo+J+2mdJtjUv4Ogr8dngOukqKzeSub9Uaxi7aP6Ci7e/f2pp+IxbFZMvr66voReiIf1iQ==", - "license": "Apache-2.0", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "debug": "^4.3.4", - "inngest": "^3.42.3", - "zod": "^3.25.76" - }, - "peerDependencies": { - "react": ">=18.0.0" - } - }, - "node_modules/@inngest/realtime/node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", @@ -1694,16 +1210,11 @@ "node": ">=18.0.0" } }, - "node_modules/@jpwilliams/waitgroup": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@jpwilliams/waitgroup/-/waitgroup-2.1.1.tgz", - "integrity": "sha512-0CxRhNfkvFCTLZBKGvKxY2FYtYW1yWhO2McLqBL0X5UWvYjIf9suH8anKW/DNutl369A75Ewyoh2iJMwBZ2tRg==", - "license": "MIT" - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1714,6 +1225,7 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -1724,54 +1236,30 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@js-sdsl/ordered-map": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz", - "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, - "node_modules/@levischuck/tiny-cbor": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz", - "integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==", - "license": "MIT" - }, "node_modules/@next/env": { "version": "15.5.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.4.tgz", @@ -1906,7633 +1394,2333 @@ "node": ">= 10" } }, - "node_modules/@noble/ciphers": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-2.0.1.tgz", - "integrity": "sha512-xHK3XHPUW8DTAobU+G0XT+/w+JLM7/8k1UFdB5xg/zTFPnFCobhftzw8wl4Lw2aq/Rvir5pxfZV5fEazmeCJ2g==", + "node_modules/@paralleldrive/cuid2": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", + "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } + "dependencies": { + "@noble/hashes": "^1.1.5" + } }, - "node_modules/@noble/hashes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz", - "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==", + "node_modules/@paralleldrive/cuid2/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "license": "MIT", "engines": { - "node": ">= 20.19.0" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, - "node_modules/@opentelemetry/api": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", - "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", - "license": "Apache-2.0", - "engines": { - "node": ">=8.0.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/@opentelemetry/api-logs": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", - "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=14" - } + "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/@opentelemetry/auto-instrumentations-node": { - "version": "0.56.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.56.1.tgz", - "integrity": "sha512-4cK0+unfkXRRbQQg2r9K3ki8JlE0j9Iw8+4DZEkChShAnmviiE+/JMgHGvK+VVcLrSlgV6BBHv4+ZTLukQwhkA==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "license": "MIT", "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/instrumentation-amqplib": "^0.46.1", - "@opentelemetry/instrumentation-aws-lambda": "^0.50.3", - "@opentelemetry/instrumentation-aws-sdk": "^0.49.1", - "@opentelemetry/instrumentation-bunyan": "^0.45.1", - "@opentelemetry/instrumentation-cassandra-driver": "^0.45.1", - "@opentelemetry/instrumentation-connect": "^0.43.1", - "@opentelemetry/instrumentation-cucumber": "^0.14.1", - "@opentelemetry/instrumentation-dataloader": "^0.16.1", - "@opentelemetry/instrumentation-dns": "^0.43.1", - "@opentelemetry/instrumentation-express": "^0.47.1", - "@opentelemetry/instrumentation-fastify": "^0.44.2", - "@opentelemetry/instrumentation-fs": "^0.19.1", - "@opentelemetry/instrumentation-generic-pool": "^0.43.1", - "@opentelemetry/instrumentation-graphql": "^0.47.1", - "@opentelemetry/instrumentation-grpc": "^0.57.1", - "@opentelemetry/instrumentation-hapi": "^0.45.2", - "@opentelemetry/instrumentation-http": "^0.57.1", - "@opentelemetry/instrumentation-ioredis": "^0.47.1", - "@opentelemetry/instrumentation-kafkajs": "^0.7.1", - "@opentelemetry/instrumentation-knex": "^0.44.1", - "@opentelemetry/instrumentation-koa": "^0.47.1", - "@opentelemetry/instrumentation-lru-memoizer": "^0.44.1", - "@opentelemetry/instrumentation-memcached": "^0.43.1", - "@opentelemetry/instrumentation-mongodb": "^0.52.0", - "@opentelemetry/instrumentation-mongoose": "^0.46.1", - "@opentelemetry/instrumentation-mysql": "^0.45.1", - "@opentelemetry/instrumentation-mysql2": "^0.45.2", - "@opentelemetry/instrumentation-nestjs-core": "^0.44.1", - "@opentelemetry/instrumentation-net": "^0.43.1", - "@opentelemetry/instrumentation-pg": "^0.51.1", - "@opentelemetry/instrumentation-pino": "^0.46.1", - "@opentelemetry/instrumentation-redis": "^0.46.1", - "@opentelemetry/instrumentation-redis-4": "^0.46.1", - "@opentelemetry/instrumentation-restify": "^0.45.1", - "@opentelemetry/instrumentation-router": "^0.44.1", - "@opentelemetry/instrumentation-socket.io": "^0.46.1", - "@opentelemetry/instrumentation-tedious": "^0.18.1", - "@opentelemetry/instrumentation-undici": "^0.10.1", - "@opentelemetry/instrumentation-winston": "^0.44.1", - "@opentelemetry/resource-detector-alibaba-cloud": "^0.30.1", - "@opentelemetry/resource-detector-aws": "^1.12.0", - "@opentelemetry/resource-detector-azure": "^0.6.1", - "@opentelemetry/resource-detector-container": "^0.6.1", - "@opentelemetry/resource-detector-gcp": "^0.33.1", - "@opentelemetry/resources": "^1.24.0", - "@opentelemetry/sdk-node": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.4.1" - } - }, - "node_modules/@opentelemetry/context-async-hooks": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz", - "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/core": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", - "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", + "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", + "license": "MIT", "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dialog": "1.1.15", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-grpc": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-grpc/-/exporter-logs-otlp-grpc-0.57.2.tgz", - "integrity": "sha512-eovEy10n3umjKJl2Ey6TLzikPE+W4cUQ4gCwgGP1RqzTGtgDra0WjIqdy29ohiUKfvmbiL3MndZww58xfIvyFw==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-grpc-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/sdk-logs": "0.57.2" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/exporter-logs-otlp-http": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.57.2.tgz", - "integrity": "sha512-0rygmvLcehBRp56NQVLSleJ5ITTduq/QfU7obOkyWgPpFHulwpw2LYTqNIz5TczKZuy5YY+5D3SDnXZL1tXImg==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/api-logs": "0.57.2", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/sdk-logs": "0.57.2" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-logs-otlp-proto": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-logs-otlp-proto/-/exporter-logs-otlp-proto-0.57.2.tgz", - "integrity": "sha512-ta0ithCin0F8lu9eOf4lEz9YAScecezCHkMMyDkvd9S7AnZNX5ikUmC5EQOQADU+oCcgo/qkQIaKcZvQ0TYKDw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.57.2", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-logs": "0.57.2", - "@opentelemetry/sdk-trace-base": "1.30.1" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.57.2.tgz", - "integrity": "sha512-r70B8yKR41F0EC443b5CGB4rUaOMm99I5N75QQt6sHKxYDzSEc6gm48Diz1CI1biwa5tDPznpylTrywO/pT7qw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-aspect-ratio": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.7.tgz", + "integrity": "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==", + "license": "MIT", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.57.2", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-grpc-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-metrics": "1.30.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-metrics-otlp-http": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.57.2.tgz", - "integrity": "sha512-ttb9+4iKw04IMubjm3t0EZsYRNWr3kg44uUuzfo9CaccYlOh8cDooe4QObDUkvx9d5qQUrbEckhrWKfJnKhemA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-metrics": "1.30.1" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/exporter-metrics-otlp-proto": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-proto/-/exporter-metrics-otlp-proto-0.57.2.tgz", - "integrity": "sha512-HX068Q2eNs38uf7RIkNN9Hl4Ynl+3lP0++KELkXMCpsCbFO03+0XNNZ1SkwxPlP9jrhQahsMPMkzNXpq3fKsnw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", + "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/exporter-metrics-otlp-http": "0.57.2", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-metrics": "1.30.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-is-hydrated": "0.1.0", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/exporter-prometheus": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.57.2.tgz", - "integrity": "sha512-VqIqXnuxWMWE/1NatAGtB1PvsQipwxDcdG4RwA/umdBcW3/iOHp0uejvFHTRN2O78ZPged87ErJajyUBPUhlDQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-checkbox": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", + "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-metrics": "1.30.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/exporter-trace-otlp-grpc": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-grpc/-/exporter-trace-otlp-grpc-0.57.2.tgz", - "integrity": "sha512-gHU1vA3JnHbNxEXg5iysqCWxN9j83d7/epTYBZflqQnTyCC4N7yZXn/dMM+bEmyhQPGjhCkNZLx4vZuChH1PYw==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-grpc-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/exporter-trace-otlp-http": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.57.2.tgz", - "integrity": "sha512-sB/gkSYFu+0w2dVQ0PWY9fAMl172PKMZ/JrHkkW8dmjCL0CYkmXeE+ssqIL/yBUTPOvpLIpenX5T9RwXRBW/3g==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/exporter-trace-otlp-proto": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.57.2.tgz", - "integrity": "sha512-awDdNRMIwDvUtoRYxRhja5QYH6+McBLtoz1q9BeEsskhZcrGmH/V1fWpGx8n+Rc+542e8pJA6y+aullbIzQmlw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/exporter-zipkin": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-zipkin/-/exporter-zipkin-1.30.1.tgz", - "integrity": "sha512-6S2QIMJahIquvFaaxmcwpvQQRD/YFaMTNoIxrfPIPOeITN+a8lfEcPDxNxn8JDAaxkg+4EnXhz8upVDYenoQjA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" - }, + "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": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/instrumentation": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz", - "integrity": "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.57.2", - "@types/shimmer": "^1.2.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1", - "semver": "^7.5.2", - "shimmer": "^1.2.1" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-amqplib": { - "version": "0.46.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.46.1.tgz", - "integrity": "sha512-AyXVnlCf/xV3K/rNumzKxZqsULyITJH6OVLiW6730JPRqWA7Zc9bvYoVNpN6iOpTU8CasH34SU/ksVJmObFibQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" - }, + "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": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-aws-lambda": { - "version": "0.50.3", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-lambda/-/instrumentation-aws-lambda-0.50.3.tgz", - "integrity": "sha512-kotm/mRvSWUauudxcylc5YCDei+G/r+jnOH6q5S99aPLQ/Ms8D2yonMIxEJUILIPlthEmwLYxkw3ualWzMjm/A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/aws-lambda": "8.10.147" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-aws-sdk": { - "version": "0.49.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-aws-sdk/-/instrumentation-aws-sdk-0.49.1.tgz", - "integrity": "sha512-Vbj4BYeV/1K4Pbbfk+gQ8gwYL0w+tBeUwG88cOxnF7CLPO1XnskGV8Q3Gzut2Ah/6Dg17dBtlzEqL3UiFP2Z6A==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-context-menu": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", + "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/propagation-utils": "^0.30.16", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-bunyan": { - "version": "0.45.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-bunyan/-/instrumentation-bunyan-0.45.1.tgz", - "integrity": "sha512-T9POV9ccS41UjpsjLrJ4i0m8LfplBiN3dMeH9XZ2btiDrjoaWtDrst6tNb1avetBjkeshOuBp1EWKP22EVSr0g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "^0.57.1", - "@opentelemetry/instrumentation": "^0.57.1", - "@types/bunyan": "1.8.11" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-cassandra-driver": { - "version": "0.45.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cassandra-driver/-/instrumentation-cassandra-driver-0.45.1.tgz", - "integrity": "sha512-RqnP0rK2hcKK1AKcmYvedLiL6G5TvFGiSUt2vI9wN0cCBdTt9Y9+wxxY19KoGxq7e9T/aHow6P5SUhCVI1sHvQ==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-connect": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.43.1.tgz", - "integrity": "sha512-ht7YGWQuV5BopMcw5Q2hXn3I8eG8TH0J/kc/GMcW4CuNTgiP6wCu44BOnucJWL3CmFWaRHI//vWyAhaC8BwePw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/connect": "3.4.38" - }, - "engines": { - "node": ">=14" - }, + "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": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-cucumber": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-cucumber/-/instrumentation-cucumber-0.14.1.tgz", - "integrity": "sha512-ybO+tmH85pDO0ywTskmrMtZcccKyQr7Eb7wHy1keR2HFfx46SzZbjHo1AuGAX//Hook3gjM7+w211gJ2bwKe1Q==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.0.0" + "@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/@opentelemetry/instrumentation-dataloader": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.16.1.tgz", - "integrity": "sha512-K/qU4CjnzOpNkkKO4DfCLSQshejRNAJtd4esgigo/50nxCB6XCyi1dhAblUHM9jG5dRm8eu0FB+t87nIo99LYQ==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-dns": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dns/-/instrumentation-dns-0.43.1.tgz", - "integrity": "sha512-e/tMZYU1nc+k+J3259CQtqVZIPsPRSLNoAQbGEmSKrjLEY/KJSbpBZ17lu4dFVBzqoF1cZYIZxn9WPQxy4V9ng==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" - }, + "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": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-express": { - "version": "0.47.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.47.1.tgz", - "integrity": "sha512-QNXPTWteDclR2B4pDFpz0TNghgB33UMjUt14B+BZPmtH1MwUFAfLHBaP5If0Z5NZC+jaH8oF2glgYjrmhZWmSw==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-fastify": { - "version": "0.44.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.44.2.tgz", - "integrity": "sha512-arSp97Y4D2NWogoXRb8CzFK3W2ooVdvqRRtQDljFt9uC3zI6OuShgey6CVFC0JxT1iGjkAr1r4PDz23mWrFULQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-hover-card": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz", + "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-fs": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.19.1.tgz", - "integrity": "sha512-6g0FhB3B9UobAR60BGTcXg4IHZ6aaYJzp0Ki5FhnxyAPt8Ns+9SSvgcrnsN2eGmk3RWG5vYycUGOEApycQL24A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-generic-pool": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.43.1.tgz", - "integrity": "sha512-M6qGYsp1cURtvVLGDrPPZemMFEbuMmCXgQYTReC/IbimV5sGrLBjB+/hANUpRZjX67nGLdKSVLZuQQAiNz+sww==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-graphql": { - "version": "0.47.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.47.1.tgz", - "integrity": "sha512-EGQRWMGqwiuVma8ZLAZnExQ7sBvbOx0N/AE/nlafISPs8S+QtXX+Viy6dcQwVWwYHQPAcuY3bFt3xgoAwb4ZNQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-label": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", + "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", + "license": "MIT", "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-grpc": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-grpc/-/instrumentation-grpc-0.57.2.tgz", - "integrity": "sha512-TR6YQA67cLSZzdxbf2SrbADJy2Y8eBW1+9mF15P0VK2MYcpdoUSmQTF1oMkBwa3B9NwqDFA2fq7wYTTutFQqaQ==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "0.57.2", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-hapi": { - "version": "0.45.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.45.2.tgz", - "integrity": "sha512-7Ehow/7Wp3aoyCrZwQpU7a2CnoMq0XhIcioFuKjBb0PLYfBfmTsFTUyatlHu0fRxhwcRsSQRTvEhmZu8CppBpQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-menubar": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz", + "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-http": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.2.tgz", - "integrity": "sha512-1Uz5iJ9ZAlFOiPuwYg29Bf7bJJc/GeoeJIFKJYQf67nTVKFe8RHbEtxgkOmK4UGZNHKXcpW4P8cWBYzBn1USpg==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-navigation-menu": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz", + "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/instrumentation": "0.57.2", - "@opentelemetry/semantic-conventions": "1.28.0", - "forwarded-parse": "2.1.2", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-ioredis": { - "version": "0.47.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.47.1.tgz", - "integrity": "sha512-OtFGSN+kgk/aoKgdkKQnBsQFDiG8WdCxu+UrHr0bXScdAmtSzLSraLo7wFIb25RVHfRWvzI5kZomqJYEg/l1iA==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-popover": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", + "license": "MIT", "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-kafkajs": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.7.1.tgz", - "integrity": "sha512-OtjaKs8H7oysfErajdYr1yuWSjMAectT7Dwr+axIoZqT9lmEOkD/H/3rgAs8h/NIuEi2imSXD+vL4MZtOuJfqQ==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-knex": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.44.1.tgz", - "integrity": "sha512-U4dQxkNhvPexffjEmGwCq68FuftFK15JgUF05y/HlK3M6W/G2iEaACIfXdSnwVNe9Qh0sPfw8LbOPxrWzGWGMQ==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-koa": { - "version": "0.47.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.47.1.tgz", - "integrity": "sha512-l/c+Z9F86cOiPJUllUCt09v+kICKvT+Vg1vOAJHtHPsJIzurGayucfCMq2acd/A/yxeNWunl9d9eqZ0G+XiI6A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.44.1.tgz", - "integrity": "sha512-5MPkYCvG2yw7WONEjYj5lr5JFehTobW7wX+ZUFy81oF2lr9IPfZk9qO+FTaM0bGEiymwfLwKe6jE15nHn1nmHg==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-memcached": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-memcached/-/instrumentation-memcached-0.43.1.tgz", - "integrity": "sha512-rK5YWC22gmsLp2aEbaPk5F+9r6BFFZuc9GTnW/ErrWpz2XNHUgeFInoPDg4t+Trs8OttIfn8XwkfFkSKqhxanw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/memcached": "^2.2.6" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.52.0.tgz", - "integrity": "sha512-1xmAqOtRUQGR7QfJFfGV/M2kC7wmI2WgZdpru8hJl3S0r4hW0n3OQpEHlSGXJAaNFyvT+ilnwkT+g5L4ljHR6g==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mongoose": { - "version": "0.46.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.46.1.tgz", - "integrity": "sha512-3kINtW1LUTPkiXFRSSBmva1SXzS/72we/jL22N+BnF3DFcoewkdkHPYOIdAAk9gSicJ4d5Ojtt1/HeibEc5OQg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-mysql": { - "version": "0.45.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.45.1.tgz", - "integrity": "sha512-TKp4hQ8iKQsY7vnp/j0yJJ4ZsP109Ht6l4RHTj0lNEG1TfgTrIH5vJMbgmoYXWzNHAqBH2e7fncN12p3BP8LFg==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-progress": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", + "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", + "license": "MIT", "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/mysql": "2.15.26" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.45.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.2.tgz", - "integrity": "sha512-h6Ad60FjCYdJZ5DTz1Lk2VmQsShiViKe0G7sYikb0GHI0NVvApp2XQNRHNjEMz87roFttGPLHOYVPlfy+yVIhQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@opentelemetry/sql-common": "^0.40.1" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-nestjs-core": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.44.1.tgz", - "integrity": "sha512-4TXaqJK27QXoMqrt4+hcQ6rKFd8B6V4JfrTJKnqBmWR1cbaqd/uwyl9yxhNH1JEkyo8GaBfdpBC4ZE4FuUhPmg==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/instrumentation-net": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-net/-/instrumentation-net-0.43.1.tgz", - "integrity": "sha512-TaMqP6tVx9/SxlY81dHlSyP5bWJIKq+K7vKfk4naB/LX4LBePPY3++1s0edpzH+RfwN+tEGVW9zTb9ci0up/lQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@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" }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.51.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.51.1.tgz", - "integrity": "sha512-QxgjSrxyWZc7Vk+qGSfsejPVFL1AgAJdSBMYZdDUbwg730D09ub3PXScB9d04vIqPriZ+0dqzjmQx0yWKiCi2Q==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@opentelemetry/sql-common": "^0.40.1", - "@types/pg": "8.6.1", - "@types/pg-pool": "2.0.6" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-pino": { - "version": "0.46.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pino/-/instrumentation-pino-0.46.1.tgz", - "integrity": "sha512-HB8gD/9CNAKlTV+mdZehnFC4tLUtQ7e+729oGq88e4WipxzZxmMYuRwZ2vzOA9/APtq+MRkERJ9PcoDqSIjZ+g==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", + "license": "MIT", "dependencies": { - "@opentelemetry/api-logs": "^0.57.1", - "@opentelemetry/core": "^1.25.0", - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-redis": { - "version": "0.46.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.46.1.tgz", - "integrity": "sha512-AN7OvlGlXmlvsgbLHs6dS1bggp6Fcki+GxgYZdSrb/DB692TyfjR7sVILaCe0crnP66aJuXsg9cge3hptHs9UA==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-redis-4": { - "version": "0.46.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.46.1.tgz", - "integrity": "sha512-UMqleEoabYMsWoTkqyt9WAzXwZ4BlFZHO40wr3d5ZvtjKCHlD4YXLm+6OLCeIi/HkX7EXvQaz8gtAwkwwSEvcQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-separator": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", + "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "license": "MIT", "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/redis-common": "^0.36.2", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-restify": { - "version": "0.45.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-restify/-/instrumentation-restify-0.45.1.tgz", - "integrity": "sha512-Zd6Go9iEa+0zcoA2vDka9r/plYKaT3BhD3ESIy4JNIzFWXeQBGbH3zZxQIsz0jbNTMEtonlymU7eTLeaGWiApA==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-slider": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", + "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-router": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-router/-/instrumentation-router-0.44.1.tgz", - "integrity": "sha512-l4T/S7ByjpY5TCUPeDe1GPns02/5BpR0jroSMexyH3ZnXJt9PtYqx1IKAlOjaFEGEOQF2tGDsMi4PY5l+fSniQ==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/instrumentation-socket.io": { - "version": "0.46.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-socket.io/-/instrumentation-socket.io-0.46.1.tgz", - "integrity": "sha512-9AsCVUAHOqvfe2RM/2I0DsDnx2ihw1d5jIN4+Bly1YPFTJIbk4+bXjAkr9+X6PUfhiV5urQHZkiYYPU1Q4yzPA==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-switch": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", + "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", + "license": "MIT", "dependencies": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-tedious": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.18.1.tgz", - "integrity": "sha512-5Cuy/nj0HBaH+ZJ4leuD7RjgvA844aY2WW+B5uLcWtxGjRZl3MNLuxnNg5DYWZNPO+NafSSnra0q49KWAHsKBg==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/instrumentation": "^0.57.1", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/tedious": "^4.0.14" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/instrumentation-undici": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.10.1.tgz", - "integrity": "sha512-rkOGikPEyRpMCmNu9AQuV5dtRlDmJp2dK5sw8roVshAGoB6hH/3QjDtRhdwd75SsJwgynWUNRUYe0wAkTo16tQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-toggle": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz", + "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==", + "license": "MIT", "dependencies": { - "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.7.0" + "@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/@opentelemetry/instrumentation-winston": { - "version": "0.44.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-winston/-/instrumentation-winston-0.44.1.tgz", - "integrity": "sha512-iexblTsT3fP0hHUz/M1mWr+Ylg3bsYN2En/jvKXZtboW3Qkvt17HrQJYTF9leVIkXAfN97QxAcTE99YGbQW7vQ==", - "license": "Apache-2.0", + "node_modules/@radix-ui/react-toggle-group": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz", + "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==", + "license": "MIT", "dependencies": { - "@opentelemetry/api-logs": "^0.57.1", - "@opentelemetry/instrumentation": "^0.57.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-toggle": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/otlp-exporter-base": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.57.2.tgz", - "integrity": "sha512-XdxEzL23Urhidyebg5E6jZoaiW5ygP/mRjxLHixogbqwDy2Faduzb5N0o/Oi+XTIJu+iyxXdVORjXax+Qgfxag==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-transformer": "0.57.2" - }, - "engines": { - "node": ">=14" + "@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": { - "@opentelemetry/api": "^1.3.0" + "@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/@opentelemetry/otlp-grpc-exporter-base": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.57.2.tgz", - "integrity": "sha512-USn173KTWy0saqqRB5yU9xUZ2xdgb1Rdu5IosJnm9aV4hMTuFFRTUsQxbgc24QxpCHeoKzzCSnS/JzdV0oM2iQ==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/grpc-js": "^1.7.1", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/otlp-exporter-base": "0.57.2", - "@opentelemetry/otlp-transformer": "0.57.2" - }, - "engines": { - "node": ">=14" - }, + "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": { - "@opentelemetry/api": "^1.3.0" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/otlp-transformer": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.57.2.tgz", - "integrity": "sha512-48IIRj49gbQVK52jYsw70+Jv+JbahT8BqT2Th7C4H7RCM9d0gZ5sgNPoMpWldmfjvIsSgiGJtjfk9MeZvjhoig==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/api-logs": "0.57.2", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-logs": "0.57.2", - "@opentelemetry/sdk-metrics": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1", - "protobufjs": "^7.3.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@opentelemetry/propagation-utils": { - "version": "0.30.16", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagation-utils/-/propagation-utils-0.30.16.tgz", - "integrity": "sha512-ZVQ3Z/PQ+2GQlrBfbMMMT0U7MzvYZLCPP800+ooyaBqm4hMvuQHfP028gB9/db0mwkmyEAMad9houukUVxhwcw==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/propagator-b3": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.30.1.tgz", - "integrity": "sha512-oATwWWDIJzybAZ4pO76ATN5N6FFbOA1otibAVlS8v90B4S1wClnhRUk7K+2CHAwN1JKYuj4jh/lpCEG5BAqFuQ==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/core": "1.30.1" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/propagator-jaeger": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.30.1.tgz", - "integrity": "sha512-Pj/BfnYEKIOImirH76M4hDaBSx6HyZ2CXUqk+Kj02m6BB80c/yo4BdWkn/1gDFfU+YPY+bPR2U0DKBfdxCKwmg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/redis-common": { - "version": "0.36.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", - "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/resource-detector-alibaba-cloud": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-alibaba-cloud/-/resource-detector-alibaba-cloud-0.30.1.tgz", - "integrity": "sha512-9l0FVP3F4+Z6ax27vMzkmhZdNtxAbDqEfy7rduzya3xFLaRiJSvOpw6cru6Edl5LwO+WvgNui+VzHa9ViE8wCg==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/resource-detector-aws": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-aws/-/resource-detector-aws-1.12.0.tgz", - "integrity": "sha512-Cvi7ckOqiiuWlHBdA1IjS0ufr3sltex2Uws2RK6loVp4gzIJyOijsddAI6IZ5kiO8h/LgCWe8gxPmwkTKImd+Q==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/resource-detector-azure": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-azure/-/resource-detector-azure-0.6.1.tgz", - "integrity": "sha512-Djr31QCExVfWViaf9cGJnH+bUInD72p0GEfgDGgjCAztyvyji6WJvKjs6qmkpPN+Ig6KLk0ho2VgzT5Kdl4L2Q==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/core": "^1.25.1", - "@opentelemetry/resources": "^1.10.1", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "use-sync-external-store": "^1.5.0" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/resource-detector-container": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-container/-/resource-detector-container-0.6.1.tgz", - "integrity": "sha512-o4sLzx149DQXDmVa8pgjBDEEKOj9SuQnkSLbjUVOpQNnn10v0WNR6wLwh30mFsK26xOJ6SpqZBGKZiT7i5MjlA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.26.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/resource-detector-gcp": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resource-detector-gcp/-/resource-detector-gcp-0.33.1.tgz", - "integrity": "sha512-/aZJXI1rU6Eus04ih2vU0hxXAibXXMzH1WlDZ8bXcTJmhwmTY8cP392+6l7cWeMnTQOibBUz8UKV3nhcCBAefw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.10.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "gcp-metadata": "^6.0.0" - }, - "engines": { - "node": ">=14" - }, + "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": { - "@opentelemetry/api": "^1.0.0" - } - }, - "node_modules/@opentelemetry/resources": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", - "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-logs": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.57.2.tgz", - "integrity": "sha512-TXFHJ5c+BKggWbdEQ/inpgIzEmS2BGQowLE9UhsMd7YYlUfBQJ4uax0VF/B5NYigdM/75OoJGhAV3upEhK+3gg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.57.2", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1" - }, - "engines": { - "node": ">=14" - }, + "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": { - "@opentelemetry/api": ">=1.4.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz", - "integrity": "sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-node": { - "version": "0.57.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-node/-/sdk-node-0.57.2.tgz", - "integrity": "sha512-8BaeqZyN5sTuPBtAoY+UtKwXBdqyuRKmekN5bFzAO40CgbGzAxfTpiL3PBerT7rhZ7p2nBdq7FaMv/tBQgHE4A==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/api-logs": "0.57.2", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/exporter-logs-otlp-grpc": "0.57.2", - "@opentelemetry/exporter-logs-otlp-http": "0.57.2", - "@opentelemetry/exporter-logs-otlp-proto": "0.57.2", - "@opentelemetry/exporter-metrics-otlp-grpc": "0.57.2", - "@opentelemetry/exporter-metrics-otlp-http": "0.57.2", - "@opentelemetry/exporter-metrics-otlp-proto": "0.57.2", - "@opentelemetry/exporter-prometheus": "0.57.2", - "@opentelemetry/exporter-trace-otlp-grpc": "0.57.2", - "@opentelemetry/exporter-trace-otlp-http": "0.57.2", - "@opentelemetry/exporter-trace-otlp-proto": "0.57.2", - "@opentelemetry/exporter-zipkin": "1.30.1", - "@opentelemetry/instrumentation": "0.57.2", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/sdk-logs": "0.57.2", - "@opentelemetry/sdk-metrics": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1", - "@opentelemetry/sdk-trace-node": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" + "@radix-ui/rect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", - "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "1.30.1", - "@opentelemetry/resources": "1.30.1", - "@opentelemetry/semantic-conventions": "1.28.0" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@opentelemetry/sdk-trace-node": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.30.1.tgz", - "integrity": "sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ==", - "license": "Apache-2.0", + "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": { - "@opentelemetry/context-async-hooks": "1.30.1", - "@opentelemetry/core": "1.30.1", - "@opentelemetry/propagator-b3": "1.30.1", - "@opentelemetry/propagator-jaeger": "1.30.1", - "@opentelemetry/sdk-trace-base": "1.30.1", - "semver": "^7.5.2" - }, - "engines": { - "node": ">=14" + "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", - "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@opentelemetry/sql-common": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", - "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^1.1.0" - }, - "engines": { - "node": ">=14" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@paralleldrive/cuid2": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz", - "integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==", + "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": { - "@noble/hashes": "^1.1.5" - } - }, - "node_modules/@paralleldrive/cuid2/node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" + "@radix-ui/react-primitive": "2.1.3" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "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/@peculiar/asn1-android": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.5.0.tgz", - "integrity": "sha512-t8A83hgghWQkcneRsgGs2ebAlRe54ns88p7ouv8PW2tzF1nAW4yHcL4uZKrFpIU+uszIRzTkcCuie37gpkId0A==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" - } + "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/@peculiar/asn1-cms": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.5.0.tgz", - "integrity": "sha512-p0SjJ3TuuleIvjPM4aYfvYw8Fk1Hn/zAVyPJZTtZ2eE9/MIer6/18ROxX6N/e6edVSfvuZBqhxAj3YgsmSjQ/A==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.5.0", - "@peculiar/asn1-x509": "^2.5.0", - "@peculiar/asn1-x509-attr": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" - } + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "license": "MIT" }, - "node_modules/@peculiar/asn1-csr": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.5.0.tgz", - "integrity": "sha512-ioigvA6WSYN9h/YssMmmoIwgl3RvZlAYx4A/9jD2qaqXZwGcNlAxaw54eSx2QG1Yu7YyBC5Rku3nNoHrQ16YsQ==", - "license": "MIT", + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", "dependencies": { - "@peculiar/asn1-schema": "^2.5.0", - "@peculiar/asn1-x509": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" + "tslib": "^2.8.0" } }, - "node_modules/@peculiar/asn1-ecc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.5.0.tgz", - "integrity": "sha512-t4eYGNhXtLRxaP50h3sfO6aJebUCDGQACoeexcelL4roMFRRVgB20yBIu2LxsPh/tdW9I282gNgMOyg3ywg/mg==", + "node_modules/@tailwindcss/node": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.14.tgz", + "integrity": "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==", + "dev": true, "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.5.0", - "@peculiar/asn1-x509": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.6.0", + "lightningcss": "1.30.1", + "magic-string": "^0.30.19", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.14" } }, - "node_modules/@peculiar/asn1-pfx": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.5.0.tgz", - "integrity": "sha512-Vj0d0wxJZA+Ztqfb7W+/iu8Uasw6hhKtCdLKXLG/P3kEPIQpqGI4P4YXlROfl7gOCqFIbgsj1HzFIFwQ5s20ug==", + "node_modules/@tailwindcss/oxide": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz", + "integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==", + "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { - "@peculiar/asn1-cms": "^2.5.0", - "@peculiar/asn1-pkcs8": "^2.5.0", - "@peculiar/asn1-rsa": "^2.5.0", - "@peculiar/asn1-schema": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-pkcs8": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.5.0.tgz", - "integrity": "sha512-L7599HTI2SLlitlpEP8oAPaJgYssByI4eCwQq2C9eC90otFpm8MRn66PpbKviweAlhinWQ3ZjDD2KIVtx7PaVw==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.5.0", - "@peculiar/asn1-x509": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-pkcs9": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.5.0.tgz", - "integrity": "sha512-UgqSMBLNLR5TzEZ5ZzxR45Nk6VJrammxd60WMSkofyNzd3DQLSNycGWSK5Xg3UTYbXcDFyG8pA/7/y/ztVCa6A==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-cms": "^2.5.0", - "@peculiar/asn1-pfx": "^2.5.0", - "@peculiar/asn1-pkcs8": "^2.5.0", - "@peculiar/asn1-schema": "^2.5.0", - "@peculiar/asn1-x509": "^2.5.0", - "@peculiar/asn1-x509-attr": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-rsa": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.5.0.tgz", - "integrity": "sha512-qMZ/vweiTHy9syrkkqWFvbT3eLoedvamcUdnnvwyyUNv5FgFXA3KP8td+ATibnlZ0EANW5PYRm8E6MJzEB/72Q==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.5.0", - "@peculiar/asn1-x509": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-schema": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.5.0.tgz", - "integrity": "sha512-YM/nFfskFJSlHqv59ed6dZlLZqtZQwjRVJ4bBAiWV08Oc+1rSd5lDZcBEx0lGDHfSoH3UziI2pXt2UM33KerPQ==", - "license": "MIT", - "dependencies": { - "asn1js": "^3.0.6", - "pvtsutils": "^1.3.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-x509": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.5.0.tgz", - "integrity": "sha512-CpwtMCTJvfvYTFMuiME5IH+8qmDe3yEWzKHe7OOADbGfq7ohxeLaXwQo0q4du3qs0AII3UbLCvb9NF/6q0oTKQ==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.5.0", - "asn1js": "^3.0.6", - "pvtsutils": "^1.3.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/asn1-x509-attr": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.5.0.tgz", - "integrity": "sha512-9f0hPOxiJDoG/bfNLAFven+Bd4gwz/VzrCIIWc1025LEI4BXO0U5fOCTNDPbbp2ll+UzqKsZ3g61mpBp74gk9A==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-schema": "^2.5.0", - "@peculiar/asn1-x509": "^2.5.0", - "asn1js": "^3.0.6", - "tslib": "^2.8.1" - } - }, - "node_modules/@peculiar/x509": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.0.tgz", - "integrity": "sha512-Yc4PDxN3OrxUPiXgU63c+ZRXKGE8YKF2McTciYhUHFtHVB0KMnjeFSU0qpztGhsp4P0uKix4+J2xEpIEDu8oXg==", - "license": "MIT", - "dependencies": { - "@peculiar/asn1-cms": "^2.5.0", - "@peculiar/asn1-csr": "^2.5.0", - "@peculiar/asn1-ecc": "^2.5.0", - "@peculiar/asn1-pkcs9": "^2.5.0", - "@peculiar/asn1-rsa": "^2.5.0", - "@peculiar/asn1-schema": "^2.5.0", - "@peculiar/asn1-x509": "^2.5.0", - "pvtsutils": "^1.3.6", - "reflect-metadata": "^0.2.2", - "tslib": "^2.8.1", - "tsyringe": "^4.10.0" - } - }, - "node_modules/@polar-sh/better-auth": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@polar-sh/better-auth/-/better-auth-1.1.9.tgz", - "integrity": "sha512-inrA7Wznv1hn1u1pVpXp4dhGZrIwTaNVDHfK4UdiJQ2LaAqvaVAKCUgKj2QM8buEorcVllJcWMGRk8zHjiAtGw==", - "dependencies": { - "@polar-sh/checkout": "^0.1.12" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polar-sh/sdk": "^0.35.3", - "better-auth": "^1.3.9", - "zod": "^3.24.2 || ^4" - } - }, - "node_modules/@polar-sh/checkout": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@polar-sh/checkout/-/checkout-0.1.12.tgz", - "integrity": "sha512-CmNdrZKOnr22Z2Cj0yeD0VfxeHW4eJufHjdufORBZwjoSnr9/xkUm+mdGIBlTGZRfAC2AekQ/ie8aqx9PVWfLQ==", - "license": "Apache-2.0", - "dependencies": { - "@polar-sh/sdk": "^0.34.9", - "@polar-sh/ui": "^0.1.1", - "event-source-plus": "^0.1.11", - "eventemitter3": "^5.0.1", - "markdown-to-jsx": "^7.7.12", - "react-hook-form": "^7.60.0" - }, - "peerDependencies": { - "@stripe/react-stripe-js": "^3.6.0", - "@stripe/stripe-js": "^7.1.0", - "react": "^18 || ^19" - } - }, - "node_modules/@polar-sh/checkout/node_modules/@polar-sh/sdk": { - "version": "0.34.17", - "resolved": "https://registry.npmjs.org/@polar-sh/sdk/-/sdk-0.34.17.tgz", - "integrity": "sha512-+eJAAyyP4CAtMy9Hd6gaNXErjaH3KuTXJFv72kqlCCvv7SweBlM4U2+zpeYAZvd/YMRZq/c447f0a0DD2e7UEA==", - "dependencies": { - "standardwebhooks": "^1.0.0", - "zod": "^3.25.76" - }, - "bin": { - "mcp": "bin/mcp-server.js" - }, - "peerDependencies": { - "@modelcontextprotocol/sdk": ">=1.5.0 <1.10.0" - }, - "peerDependenciesMeta": { - "@modelcontextprotocol/sdk": { - "optional": true - } - } - }, - "node_modules/@polar-sh/checkout/node_modules/@polar-sh/ui": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@polar-sh/ui/-/ui-0.1.1.tgz", - "integrity": "sha512-DZfYUTMxqXNPmYr2l9dhaY+zmFNANlKe7bzjV5mgUrBFo4SjxytELErOjM2g5aTmuDm7kPuGB2YJnuqnvhqRTw==", - "license": "Apache-2.0", - "dependencies": { - "@radix-ui/react-accordion": "^1.1.2", - "@radix-ui/react-alert-dialog": "^1.1.2", - "@radix-ui/react-checkbox": "^1.0.4", - "@radix-ui/react-dialog": "^1.1.2", - "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-label": "^2.0.2", - "@radix-ui/react-popover": "^1.0.7", - "@radix-ui/react-radio-group": "^1.1.3", - "@radix-ui/react-select": "^2.1.4", - "@radix-ui/react-separator": "^1.0.3", - "@radix-ui/react-slot": "^1.1.0", - "@radix-ui/react-switch": "^1.0.3", - "@radix-ui/react-tabs": "^1.0.4", - "@radix-ui/react-toast": "^1.2.2", - "@radix-ui/react-toggle": "^1.1.0", - "@radix-ui/react-toggle-group": "^1.1.0", - "@radix-ui/react-tooltip": "^1.0.7", - "@tanstack/react-table": "^8.20.5", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "cmdk": "^1.0.0", - "countries-list": "^3.1.1", - "date-fns": "^3.6.0", - "input-otp": "^1.4.1", - "lucide-react": "^0.461.0", - "react-day-picker": "^8.10.1", - "react-hook-form": "^7.54.2", - "react-timeago": "^7.2.0", - "tailwind-merge": "^2.5.5" - }, - "peerDependencies": { - "react": "^18.3.1", - "react-dom": "^18.3.1" - } - }, - "node_modules/@polar-sh/checkout/node_modules/@polar-sh/ui/node_modules/react-day-picker": { - "version": "8.10.1", - "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz", - "integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==", - "license": "MIT", - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/gpbl" - }, - "peerDependencies": { - "date-fns": "^2.28.0 || ^3.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@polar-sh/checkout/node_modules/@polar-sh/ui/node_modules/react-timeago": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/react-timeago/-/react-timeago-7.2.0.tgz", - "integrity": "sha512-2KsBEEs+qRhKx/kekUVNSTIpop3Jwd7SRBm0R4Eiq3mPeswRGSsftY9FpKsE/lXLdURyQFiHeHFrIUxLYskG5g==", - "license": "MIT", - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@polar-sh/checkout/node_modules/date-fns": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz", - "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } - }, - "node_modules/@polar-sh/checkout/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/@polar-sh/checkout/node_modules/lucide-react": { - "version": "0.461.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.461.0.tgz", - "integrity": "sha512-Scpw3D/dV1bgVRC5Kh774RCm99z0iZpPv75M6kg7QL1lLvkQ1rmI1Sjjic1aGp1ULBwd7FokV6ry0g+d6pMB+w==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" - } - }, - "node_modules/@polar-sh/checkout/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", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/@polar-sh/checkout/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", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/@polar-sh/checkout/node_modules/tailwind-merge": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", - "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/dcastil" - } - }, - "node_modules/@polar-sh/checkout/node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/@polar-sh/sdk": { - "version": "0.35.4", - "resolved": "https://registry.npmjs.org/@polar-sh/sdk/-/sdk-0.35.4.tgz", - "integrity": "sha512-vv4Ptl5jNsHIZoLvzKr0wR+dGXJOpz8VWOOTEGqaiYx6YJvzIvrayg52qp8ZtBjsRBkySLZS2EVTV3wDHTACwA==", - "dependencies": { - "standardwebhooks": "^1.0.0", - "zod": "^3.25.76" - }, - "bin": { - "mcp": "bin/mcp-server.js" - }, - "peerDependencies": { - "@modelcontextprotocol/sdk": ">=1.5.0 <1.10.0" - }, - "peerDependenciesMeta": { - "@modelcontextprotocol/sdk": { - "optional": true - } - } - }, - "node_modules/@polar-sh/sdk/node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/@prisma/client": { - "version": "6.16.3", - "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.16.3.tgz", - "integrity": "sha512-JfNfAtXG+/lIopsvoZlZiH2k5yNx87mcTS4t9/S5oufM1nKdXYxOvpDC1XoTCFBa5cQh7uXnbMPsmZrwZY80xw==", - "hasInstallScript": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "prisma": "*", - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "prisma": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@prisma/config": { - "version": "6.16.3", - "resolved": "https://registry.npmjs.org/@prisma/config/-/config-6.16.3.tgz", - "integrity": "sha512-VlsLnG4oOuKGGMToEeVaRhoTBZu5H3q51jTQXb/diRags3WV0+BQK5MolJTtP6G7COlzoXmWeS11rNBtvg+qFQ==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "c12": "3.1.0", - "deepmerge-ts": "7.1.5", - "effect": "3.16.12", - "empathic": "2.0.0" - } - }, - "node_modules/@prisma/debug": { - "version": "6.16.3", - "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-6.16.3.tgz", - "integrity": "sha512-89DdqWtdKd7qoc9/qJCKLTazj3W3zPEiz0hc7HfZdpjzm21c7orOUB5oHWJsG+4KbV4cWU5pefq3CuDVYF9vgA==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/engines": { - "version": "6.16.3", - "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-6.16.3.tgz", - "integrity": "sha512-b+Rl4nzQDcoqe6RIpSHv8f5lLnwdDGvXhHjGDiokObguAAv/O1KaX1Oc69mBW/GFWKQpCkOraobLjU6s1h8HGg==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.16.3", - "@prisma/engines-version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", - "@prisma/fetch-engine": "6.16.3", - "@prisma/get-platform": "6.16.3" - } - }, - "node_modules/@prisma/engines-version": { - "version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", - "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a.tgz", - "integrity": "sha512-fftRmosBex48Ph1v2ll1FrPpirwtPZpNkE5CDCY1Lw2SD2ctyrLlVlHiuxDAAlALwWBOkPbAll4+EaqdGuMhJw==", - "devOptional": true, - "license": "Apache-2.0" - }, - "node_modules/@prisma/fetch-engine": { - "version": "6.16.3", - "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-6.16.3.tgz", - "integrity": "sha512-bUoRIkVaI+CCaVGrSfcKev0/Mk4ateubqWqGZvQ9uCqFv2ENwWIR3OeNuGin96nZn5+SkebcD7RGgKr/+mJelw==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.16.3", - "@prisma/engines-version": "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a", - "@prisma/get-platform": "6.16.3" - } - }, - "node_modules/@prisma/get-platform": { - "version": "6.16.3", - "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-6.16.3.tgz", - "integrity": "sha512-X1LxiFXinJ4iQehrodGp0f66Dv6cDL0GbRlcCoLtSu6f4Wi+hgo7eND/afIs5029GQLgNWKZ46vn8hjyXTsHLA==", - "devOptional": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/debug": "6.16.3" - } - }, - "node_modules/@prisma/instrumentation": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.15.0.tgz", - "integrity": "sha512-6TXaH6OmDkMOQvOxwLZ8XS51hU2v4A3vmE2pSijCIiGRJYyNeMcL6nMHQMyYdZRD8wl7LF3Wzc+AMPMV/9Oo7A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.8" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, - "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-accordion": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", - "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collapsible": "1.1.12", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-alert-dialog": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", - "integrity": "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dialog": "1.1.15", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", - "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-aspect-ratio": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.1.7.tgz", - "integrity": "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-avatar": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz", - "integrity": "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-is-hydrated": "0.1.0", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-checkbox": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", - "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-collapsible": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", - "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", - "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-context": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-context-menu": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", - "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-menu": "2.1.16", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dialog": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", - "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", - "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-escape-keydown": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", - "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-menu": "2.1.16", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", - "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", - "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-hover-card": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz", - "integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-id": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-label": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", - "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-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-menubar": { - "version": "1.1.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.1.16.tgz", - "integrity": "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-menu": "2.1.16", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-navigation-menu": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz", - "integrity": "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-visually-hidden": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popover": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", - "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", - "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-rect": "1.1.1", - "@radix-ui/react-use-size": "1.1.1", - "@radix-ui/rect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-portal": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-presence": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", - "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-primitive": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-slot": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-progress": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", - "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-radio-group": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", - "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", - "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-scroll-area": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", - "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.1", - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-select": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", - "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.1", - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-focus-guards": "1.1.3", - "@radix-ui/react-focus-scope": "1.1.7", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-popper": "1.2.8", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-slot": "1.2.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-visually-hidden": "1.2.3", - "aria-hidden": "^1.2.4", - "react-remove-scroll": "^2.6.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-separator": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", - "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slider": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.6.tgz", - "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==", - "license": "MIT", - "dependencies": { - "@radix-ui/number": "1.1.1", - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-slot": { - "version": "1.2.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-switch": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", - "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-previous": "1.1.1", - "@radix-ui/react-use-size": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-tabs": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", - "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-id": "1.1.1", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-toast": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.15.tgz", - "integrity": "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-collection": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.2", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-dismissable-layer": "1.1.11", - "@radix-ui/react-portal": "1.1.9", - "@radix-ui/react-presence": "1.1.5", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-callback-ref": "1.1.1", - "@radix-ui/react-use-controllable-state": "1.2.2", - "@radix-ui/react-use-layout-effect": "1.1.1", - "@radix-ui/react-visually-hidden": "1.2.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-toggle": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz", - "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-toggle-group": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz", - "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==", - "license": "MIT", - "dependencies": { - "@radix-ui/primitive": "1.1.3", - "@radix-ui/react-context": "1.1.2", - "@radix-ui/react-direction": "1.1.1", - "@radix-ui/react-primitive": "2.1.3", - "@radix-ui/react-roving-focus": "1.1.11", - "@radix-ui/react-toggle": "1.1.10", - "@radix-ui/react-use-controllable-state": "1.2.2" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-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-use-callback-ref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-effect-event": "0.0.2", - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", - "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-escape-keydown": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-callback-ref": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-is-hydrated": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz", - "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==", - "license": "MIT", - "dependencies": { - "use-sync-external-store": "^1.5.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", - "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", - "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", - "license": "MIT", - "dependencies": { - "@radix-ui/rect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-use-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.1" - }, - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", - "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-primitive": "2.1.3" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@radix-ui/rect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", - "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", - "license": "MIT" - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "28.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.1.tgz", - "integrity": "sha512-+tNWdlWKbpB3WgBN7ijjYkq9X5uhjmcvyjEght4NmH5fAU++zfQzAJ6wumLS+dNcvwEZhKx2Z+skY8m7v0wGSA==", - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.2.0", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=16.0.0 || 14 >= 14.17" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", - "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz", - "integrity": "sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz", - "integrity": "sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz", - "integrity": "sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz", - "integrity": "sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz", - "integrity": "sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz", - "integrity": "sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz", - "integrity": "sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz", - "integrity": "sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz", - "integrity": "sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz", - "integrity": "sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz", - "integrity": "sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz", - "integrity": "sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz", - "integrity": "sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz", - "integrity": "sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz", - "integrity": "sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz", - "integrity": "sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz", - "integrity": "sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz", - "integrity": "sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz", - "integrity": "sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz", - "integrity": "sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz", - "integrity": "sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz", - "integrity": "sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sentry-internal/browser-utils": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.18.0.tgz", - "integrity": "sha512-6Y5VkNcj5ecIFsKdL8/7hrLt7pCuWR4BRLsKOHAmhdCnXtobf7v6DeBow2Hk5yEYO0AwjP5mqvoBAewbS+h3GA==", - "license": "MIT", - "dependencies": { - "@sentry/core": "10.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/feedback": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.18.0.tgz", - "integrity": "sha512-uuupIivGPCpRStMU1I3sYPgD+pl8PqNV1DSVgVS5LF99h8tqjmRGS1xkCrUaUhVhVmsnxzbnvXb1hsOaCXX7DA==", - "license": "MIT", - "dependencies": { - "@sentry/core": "10.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/replay": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.18.0.tgz", - "integrity": "sha512-ixr3K19q4oTRgM0xANi+8ThDUbxV5iixUIgvJrT7c1L6yyidovIwO0D82ZY3phUfMkgE+mX3cxX46gXTRTglKQ==", - "license": "MIT", - "dependencies": { - "@sentry-internal/browser-utils": "10.18.0", - "@sentry/core": "10.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/replay-canvas": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.18.0.tgz", - "integrity": "sha512-asp1biXA+F5HAKl7RvPbf5s087bg1bpxMB9E69xWc1ECUfFMPrFRNS7mAJ5A8DTd1K74E9cFsLl6zO29HpH4+w==", - "license": "MIT", - "dependencies": { - "@sentry-internal/replay": "10.18.0", - "@sentry/core": "10.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.3.0.tgz", - "integrity": "sha512-OuxqBprXRyhe8Pkfyz/4yHQJc5c3lm+TmYWSSx8u48g5yKewSQDOxkiLU5pAk3WnbLPy8XwU/PN+2BG0YFU9Nw==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/@sentry/browser": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.18.0.tgz", - "integrity": "sha512-JrPfxjCsuVYUe16U4fo4W2Fn0f9BwRev3G28a4ZIkwKwJo+qSnIk1mT8Eam8nwNCU8MZjB4KNE9w2p0kaoQxvQ==", - "license": "MIT", - "dependencies": { - "@sentry-internal/browser-utils": "10.18.0", - "@sentry-internal/feedback": "10.18.0", - "@sentry-internal/replay": "10.18.0", - "@sentry-internal/replay-canvas": "10.18.0", - "@sentry/core": "10.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry/bundler-plugin-core": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-4.3.0.tgz", - "integrity": "sha512-dmR4DJhJ4jqVWGWppuTL2blNFqOZZnt4aLkewbD1myFG3KVfUx8CrMQWEmGjkgPOtj5TO6xH9PyTJjXC6o5tnA==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "4.3.0", - "@sentry/cli": "^2.51.0", - "dotenv": "^16.3.1", - "find-up": "^5.0.0", - "glob": "^9.3.2", - "magic-string": "0.30.8", - "unplugin": "1.0.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@sentry/bundler-plugin-core/node_modules/magic-string": { - "version": "0.30.8", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", - "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@sentry/cli": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.56.0.tgz", - "integrity": "sha512-br6+1nTPUV5EG1oaxLzxv31kREFKr49Y1+3jutfMUz9Nl8VyVP7o9YwakB/YWl+0Vi0NXg5vq7qsd/OOuV5j8w==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.7", - "progress": "^2.0.3", - "proxy-from-env": "^1.1.0", - "which": "^2.0.2" - }, - "bin": { - "sentry-cli": "bin/sentry-cli" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@sentry/cli-darwin": "2.56.0", - "@sentry/cli-linux-arm": "2.56.0", - "@sentry/cli-linux-arm64": "2.56.0", - "@sentry/cli-linux-i686": "2.56.0", - "@sentry/cli-linux-x64": "2.56.0", - "@sentry/cli-win32-arm64": "2.56.0", - "@sentry/cli-win32-i686": "2.56.0", - "@sentry/cli-win32-x64": "2.56.0" - } - }, - "node_modules/@sentry/cli-darwin": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.56.0.tgz", - "integrity": "sha512-CzXFWbv3GrjU0gFlUM9jt0fvJmyo5ktty4HGxRFfS/eMC6xW58Gg/sEeMVEkdvk5osKooX/YEgfLBdo4zvuWDA==", - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-linux-arm": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.56.0.tgz", - "integrity": "sha512-vQCCMhZLugPmr25XBoP94dpQsFa110qK5SBUVJcRpJKyzMZd+6ueeHNslq2mB0OF4BwL1qd/ZDIa4nxa1+0rjQ==", - "cpu": [ - "arm" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd", - "android" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-linux-arm64": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.56.0.tgz", - "integrity": "sha512-91d5ZlC989j/t+TXor/glPyx6SnLFS/SlJ9fIrHIQohdGKyWWSFb4VKUan8Ok3GYu9SUzKTMByryIOoYEmeGVw==", - "cpu": [ - "arm64" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd", - "android" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-linux-i686": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.56.0.tgz", - "integrity": "sha512-MZzXuq1Q/TktN81DUs6XSBU752pG3XWSJdZR+NCStIg3l8s3O/Pwh6OcDHTYqgwsYJaGBpA0fP2Afl5XeSAUNg==", - "cpu": [ - "x86", - "ia32" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd", - "android" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-linux-x64": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.56.0.tgz", - "integrity": "sha512-INOO2OQ90Y3UzYgHRdrHdKC/0es3YSHLv0iNNgQwllL0YZihSVNYSSrZqcPq8oSDllEy9Vt9oOm/7qEnUP2Kfw==", - "cpu": [ - "x64" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux", - "freebsd", - "android" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-win32-arm64": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.56.0.tgz", - "integrity": "sha512-eUvkVk9KK01q6/qyugQPh7dAxqFPbgOa62QAoSwo11WQFYc3NPgJLilFWLQo+nahHGYKh6PKuCJ5tcqnQq5Hkg==", - "cpu": [ - "arm64" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-win32-i686": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.56.0.tgz", - "integrity": "sha512-mpCA8hKXuvT17bl1H/54KOa5i+02VBBHVlOiP3ltyBuQUqfvX/30Zl/86Spy+ikodovZWAHv5e5FpyXbY1/mPw==", - "cpu": [ - "x86", - "ia32" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli-win32-x64": { - "version": "2.56.0", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.56.0.tgz", - "integrity": "sha512-UV0pXNls+/ViAU/3XsHLLNEHCsRYaGEwJdY3HyGIufSlglxrX6BVApkV9ziGi4WAxcJWLjQdfcEs6V5B+wBy0A==", - "cpu": [ - "x64" - ], - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@sentry/cli/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/@sentry/cli/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@sentry/core": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.18.0.tgz", - "integrity": "sha512-zlhAlzc/Qpza8f/CMUb7zg/9FOhWouKAm9zyV9jZlx9lL6WceVbUEwQ3rq8ncGgM+LMwlASCOjsz5a728vAhCw==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry/nextjs": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/nextjs/-/nextjs-10.18.0.tgz", - "integrity": "sha512-W18mknUnIuAdBBflGcCogF7h1iW12Pnhq2mRDtlj10UeMmXRdfKDUPH0Ib06tiTRFJltlfw66JumISSI+75rVw==", - "license": "MIT", - "dependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/semantic-conventions": "^1.37.0", - "@rollup/plugin-commonjs": "28.0.1", - "@sentry-internal/browser-utils": "10.18.0", - "@sentry/bundler-plugin-core": "^4.3.0", - "@sentry/core": "10.18.0", - "@sentry/node": "10.18.0", - "@sentry/opentelemetry": "10.18.0", - "@sentry/react": "10.18.0", - "@sentry/vercel-edge": "10.18.0", - "@sentry/webpack-plugin": "^4.3.0", - "chalk": "3.0.0", - "resolve": "1.22.8", - "rollup": "^4.35.0", - "stacktrace-parser": "^0.1.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "next": "^13.2.0 || ^14.0 || ^15.0.0-rc.0" - } - }, - "node_modules/@sentry/nextjs/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.37.0.tgz", - "integrity": "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@sentry/nextjs/node_modules/@sentry/opentelemetry": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.18.0.tgz", - "integrity": "sha512-aORyzWbDuU0xDHDa4PRqQHxSStn9nuEKI6g4nysO2kSBbV9tnoa0eA94xnvHw+VAK86ti6sKOfe2wUHAk++rcQ==", - "license": "MIT", - "dependencies": { - "@sentry/core": "10.18.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", - "@opentelemetry/core": "^1.30.1 || ^2.1.0", - "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", - "@opentelemetry/semantic-conventions": "^1.37.0" - } - }, - "node_modules/@sentry/nextjs/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/nextjs/node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@sentry/node": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.18.0.tgz", - "integrity": "sha512-hCAC6sPmaLcpuspt8wdokr35Mee/JZFRZA1Drzz43Kk9thHw8sIYj20u+655GZMnBXHhnxeKFewpbBCQxYhenw==", - "license": "MIT", - "dependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^2.1.0", - "@opentelemetry/core": "^2.1.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/instrumentation-amqplib": "0.51.0", - "@opentelemetry/instrumentation-connect": "0.48.0", - "@opentelemetry/instrumentation-dataloader": "0.22.0", - "@opentelemetry/instrumentation-express": "0.53.0", - "@opentelemetry/instrumentation-fs": "0.24.0", - "@opentelemetry/instrumentation-generic-pool": "0.48.0", - "@opentelemetry/instrumentation-graphql": "0.52.0", - "@opentelemetry/instrumentation-hapi": "0.51.0", - "@opentelemetry/instrumentation-http": "0.204.0", - "@opentelemetry/instrumentation-ioredis": "0.52.0", - "@opentelemetry/instrumentation-kafkajs": "0.14.0", - "@opentelemetry/instrumentation-knex": "0.49.0", - "@opentelemetry/instrumentation-koa": "0.52.0", - "@opentelemetry/instrumentation-lru-memoizer": "0.49.0", - "@opentelemetry/instrumentation-mongodb": "0.57.0", - "@opentelemetry/instrumentation-mongoose": "0.51.0", - "@opentelemetry/instrumentation-mysql": "0.50.0", - "@opentelemetry/instrumentation-mysql2": "0.51.0", - "@opentelemetry/instrumentation-pg": "0.57.0", - "@opentelemetry/instrumentation-redis": "0.53.0", - "@opentelemetry/instrumentation-tedious": "0.23.0", - "@opentelemetry/instrumentation-undici": "0.15.0", - "@opentelemetry/resources": "^2.1.0", - "@opentelemetry/sdk-trace-base": "^2.1.0", - "@opentelemetry/semantic-conventions": "^1.37.0", - "@prisma/instrumentation": "6.15.0", - "@sentry/core": "10.18.0", - "@sentry/node-core": "10.18.0", - "@sentry/opentelemetry": "10.18.0", - "import-in-the-middle": "^1.14.2", - "minimatch": "^9.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/api-logs": { - "version": "0.204.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.204.0.tgz", - "integrity": "sha512-DqxY8yoAaiBPivoJD4UtgrMS8gEmzZ5lnaxzPojzLVHBGqPxgWm4zcuvcUHZiqQ6kRX2Klel2r9y8cA2HAtqpw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api": "^1.3.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/context-async-hooks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.1.0.tgz", - "integrity": "sha512-zOyetmZppnwTyPrt4S7jMfXiSX9yyfF0hxlA8B5oo2TtKl+/RGCy7fi4DrBfIf3lCPrkKsRBWZZD7RFojK7FDg==", - "license": "Apache-2.0", - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/core": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", - "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation": { - "version": "0.204.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.204.0.tgz", - "integrity": "sha512-vV5+WSxktzoMP8JoYWKeopChy6G3HKk4UQ2hESCRDUUTZqQ3+nM3u8noVG0LmNfRWwcFBnbZ71GKC7vaYYdJ1g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/api-logs": "0.204.0", - "import-in-the-middle": "^1.8.1", - "require-in-the-middle": "^7.1.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-amqplib": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.51.0.tgz", - "integrity": "sha512-XGmjYwjVRktD4agFnWBWQXo9SiYHKBxR6Ag3MLXwtLE4R99N3a08kGKM5SC1qOFKIELcQDGFEFT9ydXMH00Luw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-connect": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.48.0.tgz", - "integrity": "sha512-OMjc3SFL4pC16PeK+tDhwP7MRvDPalYCGSvGqUhX5rASkI2H0RuxZHOWElYeXkV0WP+70Gw6JHWac/2Zqwmhdw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/connect": "3.4.38" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-dataloader": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.22.0.tgz", - "integrity": "sha512-bXnTcwtngQsI1CvodFkTemrrRSQjAjZxqHVc+CJZTDnidT0T6wt3jkKhnsjU/Kkkc0lacr6VdRpCu2CUWa0OKw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-express": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.53.0.tgz", - "integrity": "sha512-r/PBafQmFYRjuxLYEHJ3ze1iBnP2GDA1nXOSS6E02KnYNZAVjj6WcDA1MSthtdAUUK0XnotHvvWM8/qz7DMO5A==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-fs": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.24.0.tgz", - "integrity": "sha512-HjIxJ6CBRD770KNVaTdMXIv29Sjz4C1kPCCK5x1Ujpc6SNnLGPqUVyJYZ3LUhhnHAqdbrl83ogVWjCgeT4Q0yw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-generic-pool": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.48.0.tgz", - "integrity": "sha512-TLv/On8pufynNR+pUbpkyvuESVASZZKMlqCm4bBImTpXKTpqXaJJ3o/MUDeMlM91rpen+PEv2SeyOKcHCSlgag==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-graphql": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.52.0.tgz", - "integrity": "sha512-3fEJ8jOOMwopvldY16KuzHbRhPk8wSsOTSF0v2psmOCGewh6ad+ZbkTx/xyUK9rUdUMWAxRVU0tFpj4Wx1vkPA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-hapi": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.51.0.tgz", - "integrity": "sha512-qyf27DaFNL1Qhbo/da+04MSCw982B02FhuOS5/UF+PMhM61CcOiu7fPuXj8TvbqyReQuJFljXE6UirlvoT/62g==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-http": { - "version": "0.204.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.204.0.tgz", - "integrity": "sha512-1afJYyGRA4OmHTv0FfNTrTAzoEjPQUYgd+8ih/lX0LlZBnGio/O80vxA0lN3knsJPS7FiDrsDrWq25K7oAzbkw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/instrumentation": "0.204.0", - "@opentelemetry/semantic-conventions": "^1.29.0", - "forwarded-parse": "2.1.2" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-ioredis": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.52.0.tgz", - "integrity": "sha512-rUvlyZwI90HRQPYicxpDGhT8setMrlHKokCtBtZgYxQWRF5RBbG4q0pGtbZvd7kyseuHbFpA3I/5z7M8b/5ywg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/redis-common": "^0.38.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-kafkajs": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.14.0.tgz", - "integrity": "sha512-kbB5yXS47dTIdO/lfbbXlzhvHFturbux4EpP0+6H78Lk0Bn4QXiZQW7rmZY1xBCY16mNcCb8Yt0mhz85hTnSVA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.30.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-knex": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.49.0.tgz", - "integrity": "sha512-NKsRRT27fbIYL4Ix+BjjP8h4YveyKc+2gD6DMZbr5R5rUeDqfC8+DTfIt3c3ex3BIc5Vvek4rqHnN7q34ZetLQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.33.1" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-koa": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.52.0.tgz", - "integrity": "sha512-JJSBYLDx/mNSy8Ibi/uQixu2rH0bZODJa8/cz04hEhRaiZQoeJ5UrOhO/mS87IdgVsHrnBOsZ6vDu09znupyuA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.49.0.tgz", - "integrity": "sha512-ctXu+O/1HSadAxtjoEg2w307Z5iPyLOMM8IRNwjaKrIpNAthYGSOanChbk1kqY6zU5CrpkPHGdAT6jk8dXiMqw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.57.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.57.0.tgz", - "integrity": "sha512-KD6Rg0KSHWDkik+qjIOWoksi1xqSpix8TSPfquIK1DTmd9OTFb5PHmMkzJe16TAPVEuElUW8gvgP59cacFcrMQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-mongoose": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.51.0.tgz", - "integrity": "sha512-gwWaAlhhV2By7XcbyU3DOLMvzsgeaymwP/jktDC+/uPkCmgB61zurwqOQdeiRq9KAf22Y2dtE5ZLXxytJRbEVA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-mysql": { - "version": "0.50.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.50.0.tgz", - "integrity": "sha512-duKAvMRI3vq6u9JwzIipY9zHfikN20bX05sL7GjDeLKr2qV0LQ4ADtKST7KStdGcQ+MTN5wghWbbVdLgNcB3rA==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/mysql": "2.15.27" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.51.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.51.0.tgz", - "integrity": "sha512-zT2Wg22Xn43RyfU3NOUmnFtb5zlDI0fKcijCj9AcK9zuLZ4ModgtLXOyBJSSfO+hsOCZSC1v/Fxwj+nZJFdzLQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@opentelemetry/sql-common": "^0.41.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.57.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.57.0.tgz", - "integrity": "sha512-dWLGE+r5lBgm2A8SaaSYDE3OKJ/kwwy5WLyGyzor8PLhUL9VnJRiY6qhp4njwhnljiLtzeffRtG2Mf/YyWLeTw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.34.0", - "@opentelemetry/sql-common": "^0.41.0", - "@types/pg": "8.15.5", - "@types/pg-pool": "2.0.6" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-redis": { - "version": "0.53.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.53.0.tgz", - "integrity": "sha512-WUHV8fr+8yo5RmzyU7D5BIE1zwiaNQcTyZPwtxlfr7px6NYYx7IIpSihJK7WA60npWynfxxK1T67RAVF0Gdfjg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/redis-common": "^0.38.0", - "@opentelemetry/semantic-conventions": "^1.27.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-tedious": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.23.0.tgz", - "integrity": "sha512-3TMTk/9VtlRonVTaU4tCzbg4YqW+Iq/l5VnN2e5whP6JgEg/PKfrGbqQ+CxQWNLfLaQYIUgEZqAn5gk/inh1uQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/instrumentation": "^0.204.0", - "@opentelemetry/semantic-conventions": "^1.27.0", - "@types/tedious": "^4.0.14" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.3.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.15.0.tgz", - "integrity": "sha512-sNFGA/iCDlVkNjzTzPRcudmI11vT/WAfAguRdZY9IspCw02N4WSC72zTuQhSMheh2a1gdeM9my1imnKRvEEvEg==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/instrumentation": "^0.204.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.7.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/redis-common": { - "version": "0.38.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz", - "integrity": "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==", - "license": "Apache-2.0", - "engines": { - "node": "^18.19.0 || >=20.6.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/resources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.1.0.tgz", - "integrity": "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/sdk-trace-base": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.1.0.tgz", - "integrity": "sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/resources": "2.1.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.37.0.tgz", - "integrity": "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@sentry/node/node_modules/@opentelemetry/sql-common": { - "version": "0.41.2", - "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.41.2.tgz", - "integrity": "sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/node-core": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.18.0.tgz", - "integrity": "sha512-rVPXbuamBbEhmiejq0RlZlMF3yaPlpIX9itz+iuQkgdySvW2jluuw0d6OQ6ZsUkW1xYqSzvGAYibh+U/QQDHiQ==", - "license": "MIT", - "dependencies": { - "@apm-js-collab/tracing-hooks": "^0.3.1", - "@sentry/core": "10.18.0", - "@sentry/opentelemetry": "10.18.0", - "import-in-the-middle": "^1.14.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", - "@opentelemetry/core": "^1.30.1 || ^2.1.0", - "@opentelemetry/instrumentation": ">=0.57.1 <1", - "@opentelemetry/resources": "^1.30.1 || ^2.1.0", - "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", - "@opentelemetry/semantic-conventions": "^1.37.0" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/opentelemetry": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.18.0.tgz", - "integrity": "sha512-aORyzWbDuU0xDHDa4PRqQHxSStn9nuEKI6g4nysO2kSBbV9tnoa0eA94xnvHw+VAK86ti6sKOfe2wUHAk++rcQ==", - "license": "MIT", - "dependencies": { - "@sentry/core": "10.18.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", - "@opentelemetry/core": "^1.30.1 || ^2.1.0", - "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", - "@opentelemetry/semantic-conventions": "^1.37.0" - } - }, - "node_modules/@sentry/node/node_modules/@types/mysql": { - "version": "2.15.27", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.27.tgz", - "integrity": "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@sentry/node/node_modules/@types/pg": { - "version": "8.15.5", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz", - "integrity": "sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - }, - "node_modules/@sentry/react": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.18.0.tgz", - "integrity": "sha512-mLVJzF/+VFTNkqVqApU9QLrTAahASLKLaPreJ5LUXhEbCEiBUTQNZIn8Js+tDisHwbdy9k94XC1/OLxld3Calg==", - "license": "MIT", - "dependencies": { - "@sentry/browser": "10.18.0", - "@sentry/core": "10.18.0", - "hoist-non-react-statics": "^3.3.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "react": "^16.14.0 || 17.x || 18.x || 19.x" - } - }, - "node_modules/@sentry/vercel-edge": { - "version": "10.18.0", - "resolved": "https://registry.npmjs.org/@sentry/vercel-edge/-/vercel-edge-10.18.0.tgz", - "integrity": "sha512-sba6lyAnTAQ3H+iyI6SFPyqEHF9bCFZSgucvINOPP873s0jkKh2hUQzxxSWBkdBgsEEz9qZc6t6nIj+wNUU3wg==", - "license": "MIT", - "dependencies": { - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/resources": "^2.1.0", - "@sentry/core": "10.18.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry/vercel-edge/node_modules/@opentelemetry/core": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", - "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" - } - }, - "node_modules/@sentry/vercel-edge/node_modules/@opentelemetry/resources": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.1.0.tgz", - "integrity": "sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw==", - "license": "Apache-2.0", - "dependencies": { - "@opentelemetry/core": "2.1.0", - "@opentelemetry/semantic-conventions": "^1.29.0" - }, - "engines": { - "node": "^18.19.0 || >=20.6.0" - }, - "peerDependencies": { - "@opentelemetry/api": ">=1.3.0 <1.10.0" - } - }, - "node_modules/@sentry/vercel-edge/node_modules/@opentelemetry/semantic-conventions": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.37.0.tgz", - "integrity": "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "node_modules/@sentry/webpack-plugin": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-4.3.0.tgz", - "integrity": "sha512-K4nU1SheK/tvyakBws2zfd+MN6hzmpW+wPTbSbDWn1+WL9+g9hsPh8hjFFiVe47AhhUoUZ3YgiH2HyeHXjHflA==", - "license": "MIT", - "dependencies": { - "@sentry/bundler-plugin-core": "4.3.0", - "unplugin": "1.0.1", - "uuid": "^9.0.0" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "webpack": ">=4.40.0" - } - }, - "node_modules/@simplewebauthn/browser": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.2.2.tgz", - "integrity": "sha512-FNW1oLQpTJyqG5kkDg5ZsotvWgmBaC6jCHR7Ej0qUNep36Wl9tj2eZu7J5rP+uhXgHaLk+QQ3lqcw2vS5MX1IA==", - "license": "MIT" - }, - "node_modules/@simplewebauthn/server": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/@simplewebauthn/server/-/server-13.2.2.tgz", - "integrity": "sha512-HcWLW28yTMGXpwE9VLx9J+N2KEUaELadLrkPEEI9tpI5la70xNEVEsu/C+m3u7uoq4FulLqZQhgBCzR9IZhFpA==", - "license": "MIT", - "dependencies": { - "@hexagon/base64": "^1.1.27", - "@levischuck/tiny-cbor": "^0.2.2", - "@peculiar/asn1-android": "^2.3.10", - "@peculiar/asn1-ecc": "^2.3.8", - "@peculiar/asn1-rsa": "^2.3.8", - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/asn1-x509": "^2.3.8", - "@peculiar/x509": "^1.13.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@stablelib/base64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz", - "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==", - "license": "MIT" - }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "license": "MIT" - }, - "node_modules/@standard-schema/utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", - "license": "MIT" - }, - "node_modules/@stripe/react-stripe-js": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.10.0.tgz", - "integrity": "sha512-UPqHZwMwDzGSax0ZI7XlxR3tZSpgIiZdk3CiwjbTK978phwR/fFXeAXQcN/h8wTAjR4ZIAzdlI9DbOqJhuJdeg==", - "license": "MIT", - "peer": true, - "dependencies": { - "prop-types": "^15.7.2" - }, - "peerDependencies": { - "@stripe/stripe-js": ">=1.44.1 <8.0.0", - "react": ">=16.8.0 <20.0.0", - "react-dom": ">=16.8.0 <20.0.0" - } - }, - "node_modules/@stripe/stripe-js": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.9.0.tgz", - "integrity": "sha512-ggs5k+/0FUJcIgNY08aZTqpBTtbExkJMYMLSMwyucrhtWexVOEY1KJmhBsxf+E/Q15f5rbwBpj+t0t2AW2oCsQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12.16" - } - }, - "node_modules/@swc/helpers": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", - "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@tailwindcss/node": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.14.tgz", - "integrity": "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "enhanced-resolve": "^5.18.3", - "jiti": "^2.6.0", - "lightningcss": "1.30.1", - "magic-string": "^0.30.19", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.14" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz", - "integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.5.1" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.14", - "@tailwindcss/oxide-darwin-arm64": "4.1.14", - "@tailwindcss/oxide-darwin-x64": "4.1.14", - "@tailwindcss/oxide-freebsd-x64": "4.1.14", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.14", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.14", - "@tailwindcss/oxide-linux-x64-musl": "4.1.14", - "@tailwindcss/oxide-wasm32-wasi": "4.1.14", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.14" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.14.tgz", - "integrity": "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.14.tgz", - "integrity": "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.14.tgz", - "integrity": "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.14.tgz", - "integrity": "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.14.tgz", - "integrity": "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.14.tgz", - "integrity": "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.14.tgz", - "integrity": "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.14.tgz", - "integrity": "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.14.tgz", - "integrity": "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.14.tgz", - "integrity": "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.5.0", - "@emnapi/runtime": "^1.5.0", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.0.5", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz", - "integrity": "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.14.tgz", - "integrity": "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.1.14", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.14.tgz", - "integrity": "sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.14", - "@tailwindcss/oxide": "4.1.14", - "postcss": "^8.4.41", - "tailwindcss": "4.1.14" - } - }, - "node_modules/@tanstack/query-core": { - "version": "5.90.2", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.2.tgz", - "integrity": "sha512-k/TcR3YalnzibscALLwxeiLUub6jN5EDLwKDiO7q5f4ICEoptJ+n9+7vcEFy5/x/i6Q+Lb/tXrsKCggf5uQJXQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-query": { - "version": "5.90.2", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.2.tgz", - "integrity": "sha512-CLABiR+h5PYfOWr/z+vWFt5VsOA2ekQeRQBFSKlcoW6Ndx/f8rfyVmq4LbgOM4GG2qtxAxjLYLOpCNTYm4uKzw==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.90.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" - } - }, - "node_modules/@tanstack/react-table": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.3.tgz", - "integrity": "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==", - "license": "MIT", - "dependencies": { - "@tanstack/table-core": "8.21.3" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/@tanstack/table-core": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.3.tgz", - "integrity": "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@trpc/client": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/@trpc/client/-/client-11.6.0.tgz", - "integrity": "sha512-DyWbYk2hd50BaVrXWVkaUnaSwgAF5g/lfBkXtkF1Aqlk6BtSzGUo3owPkgqQO2I5LwWy1+ra9TsSfBBvIZpTwg==", - "funding": [ - "https://trpc.io/sponsor" - ], - "license": "MIT", - "peerDependencies": { - "@trpc/server": "11.6.0", - "typescript": ">=5.7.2" - } - }, - "node_modules/@trpc/server": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/@trpc/server/-/server-11.6.0.tgz", - "integrity": "sha512-skTso0AWbOZck40jwNeYv++AMZXNWLUWdyk+pB5iVaYmEKTuEeMoPrEudR12VafbEU6tZa8HK3QhBfTYYHDCdg==", - "funding": [ - "https://trpc.io/sponsor" - ], - "license": "MIT", - "peerDependencies": { - "typescript": ">=5.7.2" - } - }, - "node_modules/@trpc/tanstack-react-query": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/@trpc/tanstack-react-query/-/tanstack-react-query-11.6.0.tgz", - "integrity": "sha512-254OpGV2RT9Djl6HRJmokDMT4pZz3beLs+8/T35ySfBxiC5OdEsOeESIJpC302YaZcCGwkOZ+d+FKFXgpy0YtQ==", - "funding": [ - "https://trpc.io/sponsor" - ], - "license": "MIT", - "peerDependencies": { - "@tanstack/react-query": "^5.80.3", - "@trpc/client": "11.6.0", - "@trpc/server": "11.6.0", - "react": ">=18.2.0", - "react-dom": ">=18.2.0", - "typescript": ">=5.7.2" - } - }, - "node_modules/@types/aws-lambda": { - "version": "8.10.147", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.147.tgz", - "integrity": "sha512-nD0Z9fNIZcxYX5Mai2CTmFD7wX7UldCkW2ezCF8D1T5hdiLsnTWDGRpfRYntU6VjTdLQjOvyszru7I1c1oCQew==", - "license": "MIT" - }, - "node_modules/@types/bunyan": { - "version": "1.8.11", - "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.11.tgz", - "integrity": "sha512-758fRH7umIMk5qt5ELmRMff4mLDlN+xyYzC+dkPTdKwbSkJFvz6xwyScrytPU0QIBbRRwbiE8/BIg8bpajerNQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "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-drag": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", - "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", - "license": "MIT", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "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-selection": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", - "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", - "license": "MIT" - }, - "node_modules/@types/d3-shape": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", - "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", - "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/d3-transition": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", - "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", - "license": "MIT", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-zoom": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", - "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", - "license": "MIT", - "dependencies": { - "@types/d3-interpolate": "*", - "@types/d3-selection": "*" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/memcached": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/@types/memcached/-/memcached-2.2.10.tgz", - "integrity": "sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==", - "license": "MIT", - "dependencies": { - "@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/mysql": { - "version": "2.15.26", - "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", - "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "20.19.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.19.tgz", - "integrity": "sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/pg": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", - "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "pg-protocol": "*", - "pg-types": "^2.2.0" - } - }, - "node_modules/@types/pg-pool": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", - "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", - "license": "MIT", - "dependencies": { - "@types/pg": "*" - } - }, - "node_modules/@types/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.0.tgz", - "integrity": "sha512-1LOH8xovvsKsCBq1wnT4ntDUdCJKmnEakhsuoUSy6ExlHCkGP2hqnatagYTgFk6oeL0VU31u7SNjunPN+GchtA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.0.tgz", - "integrity": "sha512-brtBs0MnE9SMx7px208g39lRmC5uHZs96caOJfTjFcYSLHNamvaSMfJNagChVNkup2SdtOxKX1FDBkRSJe1ZAg==", - "devOptional": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@types/shimmer": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", - "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", - "license": "MIT" - }, - "node_modules/@types/tedious": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", - "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/toposort": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/toposort/-/toposort-2.0.7.tgz", - "integrity": "sha512-sQNk65vbC36+UixCkcky+dCr7MlflHcVILg1FVGqlUntsLFv9xd9ToWIVko/gTuin+cVe16t+2YubEFkhnSuPQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vercel/oidc": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.0.1.tgz", - "integrity": "sha512-V/YRVrJDqM6VaMBjRUrd6qRMrTKvZjHdVdEmdXsOZMulTa3iK98ijKTc3wldBmst6W5rHpqMoKllKcBAHgN7GQ==", - "license": "Apache-2.0", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "license": "Apache-2.0", - "peer": true - }, - "node_modules/@xyflow/react": { - "version": "12.8.6", - "resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.8.6.tgz", - "integrity": "sha512-SksAm2m4ySupjChphMmzvm55djtgMDPr+eovPDdTnyGvShf73cvydfoBfWDFllooIQ4IaiUL5yfxHRwU0c37EA==", - "license": "MIT", - "dependencies": { - "@xyflow/system": "0.0.70", - "classcat": "^5.0.3", - "zustand": "^4.4.0" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@xyflow/system": { - "version": "0.0.70", - "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.70.tgz", - "integrity": "sha512-PpC//u9zxdjj0tfTSmZrg3+sRbTz6kop/Amky44U2Dl51sxzDTIUfXMwETOYpmr2dqICWXBIJwXL2a9QWtX2XA==", - "license": "MIT", - "dependencies": { - "@types/d3-drag": "^3.0.7", - "@types/d3-interpolate": "^3.0.4", - "@types/d3-selection": "^3.0.10", - "@types/d3-transition": "^3.0.8", - "@types/d3-zoom": "^3.0.8", - "d3-drag": "^3.0.0", - "d3-interpolate": "^3.0.1", - "d3-selection": "^3.0.0", - "d3-zoom": "^3.0.0" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" - } - }, - "node_modules/adm-zip": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", - "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/ai": { - "version": "5.0.60", - "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.60.tgz", - "integrity": "sha512-80U/3kmdBW6g+JkLXpz/P2EwkyEaWlPlYtuLUpx/JYK9F7WZh9NnkYoh1KvUi1Sbpo0NyurBTvX0a2AG9mmbDA==", - "license": "Apache-2.0", - "dependencies": { - "@ai-sdk/gateway": "1.0.33", - "@ai-sdk/provider": "2.0.0", - "@ai-sdk/provider-utils": "3.0.10", - "@opentelemetry/api": "1.9.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "zod": "^3.25.76 || ^4.1.8" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "license": "MIT", - "peer": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/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/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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/asn1js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.6.tgz", - "integrity": "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==", - "license": "BSD-3-Clause", - "dependencies": { - "pvtsutils": "^1.3.6", - "pvutils": "^1.1.3", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.13.tgz", - "integrity": "sha512-7s16KR8io8nIBWQyCYhmFhd+ebIzb9VKTzki+wOJXHTxTnV6+mFGH3+Jwn1zoKaY9/H9T/0BcKCZnzXljPnpSQ==", - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/better-auth": { - "version": "1.3.26", - "resolved": "https://registry.npmjs.org/better-auth/-/better-auth-1.3.26.tgz", - "integrity": "sha512-umaOGmv29yF4sD6o2zlW6B0Oayko5yD/A8mKJOFDDEIoVP/pR7nJ/2KsqKy+xvBpnDsKdrZseqA8fmczPviUHw==", - "license": "MIT", - "dependencies": { - "@better-auth/core": "1.3.26", - "@better-auth/utils": "0.3.0", - "@better-fetch/fetch": "^1.1.18", - "@noble/ciphers": "^2.0.0", - "@noble/hashes": "^2.0.0", - "@simplewebauthn/browser": "^13.1.2", - "@simplewebauthn/server": "^13.1.2", - "better-call": "1.0.19", - "defu": "^6.1.4", - "jose": "^6.1.0", - "kysely": "^0.28.5", - "nanostores": "^1.0.1", - "zod": "^4.1.5" - }, - "peerDependenciesMeta": { - "@lynx-js/react": { - "optional": true - }, - "@sveltejs/kit": { - "optional": true - }, - "next": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "solid-js": { - "optional": true - }, - "svelte": { - "optional": true - }, - "vue": { - "optional": true - } - } - }, - "node_modules/better-call": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.0.19.tgz", - "integrity": "sha512-sI3GcA1SCVa3H+CDHl8W8qzhlrckwXOTKhqq3OOPXjgn5aTOMIqGY34zLY/pHA6tRRMjTUC3lz5Mi7EbDA24Kw==", - "dependencies": { - "@better-auth/utils": "^0.3.0", - "@better-fetch/fetch": "^1.1.4", - "rou3": "^0.5.1", - "set-cookie-parser": "^2.7.1", - "uncrypto": "^0.1.3" - } - }, - "node_modules/bignumber.js": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", - "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.26.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", - "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", - "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.8.9", - "caniuse-lite": "^1.0.30001746", - "electron-to-chromium": "^1.5.227", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT", - "peer": true - }, - "node_modules/c12": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", - "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.3", - "confbox": "^0.2.2", - "defu": "^6.1.4", - "dotenv": "^16.6.1", - "exsolve": "^1.0.7", - "giget": "^2.0.0", - "jiti": "^2.4.2", - "ohash": "^2.0.11", - "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", - "rc9": "^2.1.2" - }, - "peerDependencies": { - "magicast": "^0.3.5" - }, - "peerDependenciesMeta": { - "magicast": { - "optional": true - } - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001747", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001747.tgz", - "integrity": "sha512-mzFa2DGIhuc5490Nd/G31xN1pnBnYMadtkyTjefPI7wzypqgCEpeWu9bJr0OnDsyKrW75zA9ZAt7pbQFmwLsQg==", - "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/canonicalize": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz", - "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", - "license": "Apache-2.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==", - "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": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "consola": "^3.2.3" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "license": "MIT" - }, - "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/classcat": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", - "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", - "license": "MIT" - }, - "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/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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/cmdk": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", - "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", - "license": "MIT", - "dependencies": { - "@radix-ui/react-compose-refs": "^1.1.1", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-id": "^1.1.0", - "@radix-ui/react-primitive": "^2.0.2" - }, - "peerDependencies": { - "react": "^18 || ^19 || ^19.0.0-rc", - "react-dom": "^18 || ^19 || ^19.0.0-rc" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT", - "peer": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "license": "MIT" - }, - "node_modules/confbox": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", - "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "license": "MIT" - }, - "node_modules/copy-anything": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", - "license": "MIT", - "dependencies": { - "is-what": "^4.1.8" - }, - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/countries-list": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/countries-list/-/countries-list-3.1.1.tgz", - "integrity": "sha512-nPklKJ5qtmY5MdBKw1NiBAoyx5Sa7p2yPpljZyQ7gyCN1m+eMFs9I6CT37Mxt8zvR5L3VzD3DJBE4WQzX3WF4A==", - "license": "MIT" - }, - "node_modules/cross-fetch": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", - "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", - "license": "MIT", - "dependencies": { - "node-fetch": "^2.7.0" - } - }, - "node_modules/cross-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/cryptr": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/cryptr/-/cryptr-6.4.0.tgz", - "integrity": "sha512-9jpMU9HMt1vhMUqNO+MPuGEpbh/f7HHZdxrd6L2DMwTuYGyt9pgUJfQyTS1Ei4/sn7qPM4FkjxUoiW79k0x8sA==", - "license": "MIT" - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "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-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "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.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "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-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "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/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } - }, - "node_modules/date-fns-jalali": { - "version": "4.1.0-0", - "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz", - "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" + "detect-libc": "^2.0.4", + "tar": "^7.5.1" }, "engines": { - "node": ">=6.0" + "node": ">= 10" }, - "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/deepmerge-ts": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", - "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", - "devOptional": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "license": "MIT" - }, - "node_modules/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.1.tgz", - "integrity": "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==", - "devOptional": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.14", + "@tailwindcss/oxide-darwin-arm64": "4.1.14", + "@tailwindcss/oxide-darwin-x64": "4.1.14", + "@tailwindcss/oxide-freebsd-x64": "4.1.14", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.14", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.14", + "@tailwindcss/oxide-linux-x64-musl": "4.1.14", + "@tailwindcss/oxide-wasm32-wasi": "4.1.14", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.14" } }, - "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/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.14.tgz", + "integrity": "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.14.tgz", + "integrity": "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">= 10" } }, - "node_modules/dotenv-cli": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-10.0.0.tgz", - "integrity": "sha512-lnOnttzfrzkRx2echxJHQRB6vOAMSCzzZg79IxpC00tU42wZPuZkQxNNrrwVAxaQZIIh001l4PxVlCrBxngBzA==", + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.14.tgz", + "integrity": "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.6", - "dotenv": "^17.1.0", - "dotenv-expand": "^11.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "dotenv": "cli.js" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/dotenv-cli/node_modules/dotenv": { - "version": "17.2.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", - "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.14.tgz", + "integrity": "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">= 10" } }, - "node_modules/dotenv-expand": { - "version": "11.0.7", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", - "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.14.tgz", + "integrity": "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==", + "cpu": [ + "arm" + ], "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dotenv": "^16.4.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">= 10" } }, - "node_modules/effect": { - "version": "3.16.12", - "resolved": "https://registry.npmjs.org/effect/-/effect-3.16.12.tgz", - "integrity": "sha512-N39iBk0K71F9nb442TLbTkjl24FLUzuvx2i1I2RsEAQsdAdUTuUoW0vlfUXgkMTUOnYqKnWcFfqw4hK4Pw27hg==", - "devOptional": true, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.14.tgz", + "integrity": "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.0.0", - "fast-check": "^3.23.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.232", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.232.tgz", - "integrity": "sha512-ENirSe7wf8WzyPCibqKUG1Cg43cPaxH4wRR7AJsX7MCABCHBIOFqvaYODSLKUuZdraxUTHRE/0A2Aq8BYKEHOg==", - "license": "ISC" - }, - "node_modules/embla-carousel": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", - "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", - "license": "MIT" - }, - "node_modules/embla-carousel-react": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz", - "integrity": "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==", + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.14.tgz", + "integrity": "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "embla-carousel": "8.6.0", - "embla-carousel-reactive-utils": "8.6.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/embla-carousel-reactive-utils": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz", - "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==", + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.14.tgz", + "integrity": "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "peerDependencies": { - "embla-carousel": "8.6.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" } }, - "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==", - "license": "MIT" - }, - "node_modules/empathic": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", - "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", - "devOptional": true, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.14.tgz", + "integrity": "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">= 10" } }, - "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.14.tgz", + "integrity": "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.0.5", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=14.0.0" } }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz", + "integrity": "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "peer": true + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } }, - "node_modules/esbuild": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", - "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.14.tgz", + "integrity": "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==", + "cpu": [ + "x64" + ], "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.10", - "@esbuild/android-arm": "0.25.10", - "@esbuild/android-arm64": "0.25.10", - "@esbuild/android-x64": "0.25.10", - "@esbuild/darwin-arm64": "0.25.10", - "@esbuild/darwin-x64": "0.25.10", - "@esbuild/freebsd-arm64": "0.25.10", - "@esbuild/freebsd-x64": "0.25.10", - "@esbuild/linux-arm": "0.25.10", - "@esbuild/linux-arm64": "0.25.10", - "@esbuild/linux-ia32": "0.25.10", - "@esbuild/linux-loong64": "0.25.10", - "@esbuild/linux-mips64el": "0.25.10", - "@esbuild/linux-ppc64": "0.25.10", - "@esbuild/linux-riscv64": "0.25.10", - "@esbuild/linux-s390x": "0.25.10", - "@esbuild/linux-x64": "0.25.10", - "@esbuild/netbsd-arm64": "0.25.10", - "@esbuild/netbsd-x64": "0.25.10", - "@esbuild/openbsd-arm64": "0.25.10", - "@esbuild/openbsd-x64": "0.25.10", - "@esbuild/openharmony-arm64": "0.25.10", - "@esbuild/sunos-x64": "0.25.10", - "@esbuild/win32-arm64": "0.25.10", - "@esbuild/win32-ia32": "0.25.10", - "@esbuild/win32-x64": "0.25.10" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/@tailwindcss/postcss": { + "version": "4.1.14", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.14.tgz", + "integrity": "sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.14", + "@tailwindcss/oxide": "4.1.14", + "postcss": "^8.4.41", + "tailwindcss": "4.1.14" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" + "node_modules/@tanstack/query-core": { + "version": "5.90.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.2.tgz", + "integrity": "sha512-k/TcR3YalnzibscALLwxeiLUub6jN5EDLwKDiO7q5f4ICEoptJ+n9+7vcEFy5/x/i6Q+Lb/tXrsKCggf5uQJXQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" } }, - "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==", - "license": "BSD-2-Clause", - "peer": true, + "node_modules/@tanstack/react-query": { + "version": "5.90.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.2.tgz", + "integrity": "sha512-CLABiR+h5PYfOWr/z+vWFt5VsOA2ekQeRQBFSKlcoW6Ndx/f8rfyVmq4LbgOM4GG2qtxAxjLYLOpCNTYm4uKzw==", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "@tanstack/query-core": "5.90.2" }, - "engines": { - "node": ">=4.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=4.0" - } + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "license": "BSD-2-Clause", - "peer": true, - "engines": { - "node": ">=4.0" + "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-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "license": "MIT", + "dependencies": { + "@types/d3-selection": "*" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "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/event-source-plus": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/event-source-plus/-/event-source-plus-0.1.12.tgz", - "integrity": "sha512-98wOULBKdZV9BnI2OY0wCb4VCoQmyRyESDtKPYR4l9D8hEXbfLdk0ue6va1zlYW1wqhcJHm2w9kJtUtsl9ZB9A==", + "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": { - "ofetch": "^1.4.1" + "@types/d3-color": "*" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "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/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "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", - "peer": true, - "engines": { - "node": ">=0.8.x" + "dependencies": { + "@types/d3-time": "*" } }, - "node_modules/eventsource-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==", + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", "license": "MIT", - "engines": { - "node": ">=18.0.0" + "dependencies": { + "@types/d3-path": "*" } }, - "node_modules/exsolve": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz", - "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", - "devOptional": true, + "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/extend": { + "node_modules/@types/d3-timer": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", "license": "MIT" }, - "node_modules/fast-check": { - "version": "3.23.2", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz", - "integrity": "sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==", - "devOptional": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", "license": "MIT", "dependencies": { - "pure-rand": "^6.1.0" - }, - "engines": { - "node": ">=8.0.0" + "@types/d3-selection": "*" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", "license": "MIT", - "peer": true + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } }, - "node_modules/fast-equals": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.3.2.tgz", - "integrity": "sha512-6rxyATwPCkaFIL3JLqw8qXqMpIZ942pTX/tbQFkRsDGblS8tNGtlUauA/+mt6RUfqn/4MoEr+WDkYoIQbibWuQ==", + "node_modules/@types/node": { + "version": "20.19.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.19.tgz", + "integrity": "sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=6.0.0" + "dependencies": { + "undici-types": "~6.21.0" } }, - "node_modules/fast-sha256": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz", - "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==", - "license": "Unlicense" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause", - "peer": true - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/@types/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.0.tgz", + "integrity": "sha512-1LOH8xovvsKsCBq1wnT4ntDUdCJKmnEakhsuoUSy6ExlHCkGP2hqnatagYTgFk6oeL0VU31u7SNjunPN+GchtA==", + "devOptional": true, "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "dependencies": { + "csstype": "^3.0.2" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/@types/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-brtBs0MnE9SMx7px208g39lRmC5uHZs96caOJfTjFcYSLHNamvaSMfJNagChVNkup2SdtOxKX1FDBkRSJe1ZAg==", + "devOptional": true, "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/react": "^19.2.0" } }, - "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==", + "node_modules/@xyflow/react": { + "version": "12.8.6", + "resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.8.6.tgz", + "integrity": "sha512-SksAm2m4ySupjChphMmzvm55djtgMDPr+eovPDdTnyGvShf73cvydfoBfWDFllooIQ4IaiUL5yfxHRwU0c37EA==", "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" + "@xyflow/system": "0.0.70", + "classcat": "^5.0.3", + "zustand": "^4.4.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" } }, - "node_modules/forwarded-parse": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", - "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", - "license": "MIT" - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", + "node_modules/@xyflow/system": { + "version": "0.0.70", + "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.70.tgz", + "integrity": "sha512-PpC//u9zxdjj0tfTSmZrg3+sRbTz6kop/Amky44U2Dl51sxzDTIUfXMwETOYpmr2dqICWXBIJwXL2a9QWtX2XA==", + "license": "MIT", "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" + "@types/d3-drag": "^3.0.7", + "@types/d3-interpolate": "^3.0.4", + "@types/d3-selection": "^3.0.10", + "@types/d3-transition": "^3.0.8", + "@types/d3-zoom": "^3.0.8", + "d3-drag": "^3.0.0", + "d3-interpolate": "^3.0.1", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0" } }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", + "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": { - "yallist": "^4.0.0" + "tslib": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "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==", - "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" + "node_modules/caniuse-lite": { + "version": "1.0.30001747", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001747.tgz", + "integrity": "sha512-mzFa2DGIhuc5490Nd/G31xN1pnBnYMadtkyTjefPI7wzypqgCEpeWu9bJr0OnDsyKrW75zA9ZAt7pbQFmwLsQg==", + "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" + } ], - "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" - } + "license": "CC-BY-4.0" }, - "node_modules/gaxios": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", - "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", - "license": "Apache-2.0", - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^7.0.1", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9", - "uuid": "^9.0.1" - }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=14" + "node": ">=18" } }, - "node_modules/gcp-metadata": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", - "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", + "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": { - "gaxios": "^6.1.1", - "google-logging-utils": "^0.0.2", - "json-bigint": "^1.0.0" + "clsx": "^2.1.1" }, - "engines": { - "node": ">=14" + "funding": { + "url": "https://polar.sh/cva" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } + "node_modules/classcat": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", + "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", + "license": "MIT" }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" }, - "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==", + "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/get-tsconfig": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", - "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", - "dev": true, + "node_modules/cmdk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", + "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", "license": "MIT", "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-id": "^1.1.0", + "@radix-ui/react-primitive": "^2.0.2" }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, - "node_modules/giget": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", - "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.0", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.6", - "nypm": "^0.6.0", - "pathe": "^2.0.3" - }, - "bin": { - "giget": "dist/cli.mjs" - } + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" }, - "node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "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": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "internmap": "1 - 2" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/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", - "dependencies": { - "is-glob": "^4.0.1" - }, "engines": { - "node": ">= 6" + "node": ">=12" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "license": "BSD-2-Clause", - "peer": true - }, - "node_modules/glob/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/glob/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/google-logging-utils": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", - "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=14" - } - }, - "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/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "license": "MIT", "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" + "d3-dispatch": "1 - 3", + "d3-selection": "3" }, "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" + "node": ">=12" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", + "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": ">=8" + "node": ">=12" } }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", + "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": { - "function-bind": "^1.1.2" + "d3-color": "1 - 3" }, "engines": { - "node": ">= 0.4" + "node": ">=12" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "license": "BSD-3-Clause", - "dependencies": { - "react-is": "^16.7.0" + "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/hoist-non-react-statics/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/html-entities": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", - "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "license": "MIT", + "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": { - "agent-base": "^7.1.2", - "debug": "4" + "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": ">= 14" + "node": ">=12" } }, - "node_modules/import-in-the-middle": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.14.4.tgz", - "integrity": "sha512-eWjxh735SJLFJJDs5X82JQ2405OdJeAHDBnaoFCfdr5GVc7AWc9xU7KbrF+3Xd5F2ccP1aQFKtY+65X6EfKZ7A==", - "license": "Apache-2.0", - "dependencies": { - "acorn": "^8.14.0", - "acorn-import-attributes": "^1.9.5", - "cjs-module-lexer": "^1.2.2", - "module-details-from-path": "^1.0.3" + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/inngest": { - "version": "3.44.1", - "resolved": "https://registry.npmjs.org/inngest/-/inngest-3.44.1.tgz", - "integrity": "sha512-bmWor6JlqXVR00m4KsbwTFB/QywBeshjl7W3DfSsf6bFfWkalGzq2AaNyTk6tDFJdZoZJGL1b2Plqy5ZGejQfw==", - "license": "Apache-2.0", + "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": { - "@bufbuild/protobuf": "^2.2.3", - "@inngest/ai": "^0.1.3", - "@jpwilliams/waitgroup": "^2.1.1", - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/auto-instrumentations-node": "^0.56.1", - "@opentelemetry/context-async-hooks": "^1.30.1", - "@opentelemetry/exporter-trace-otlp-http": "^0.57.2", - "@opentelemetry/instrumentation": "^0.57.2", - "@opentelemetry/resources": "^1.30.1", - "@opentelemetry/sdk-trace-base": "^1.30.1", - "@standard-schema/spec": "^1.0.0", - "@types/debug": "^4.1.12", - "canonicalize": "^1.0.8", - "chalk": "^4.1.2", - "cross-fetch": "^4.0.0", - "debug": "^4.3.4", - "hash.js": "^1.1.7", - "json-stringify-safe": "^5.0.1", - "ms": "^2.1.3", - "serialize-error-cjs": "^0.1.3", - "strip-ansi": "^5.2.0", - "temporal-polyfill": "^0.2.5", - "zod": "^4.0.17" - }, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "@sveltejs/kit": ">=1.27.3", - "@vercel/node": ">=2.15.9", - "aws-lambda": ">=1.0.7", - "express": ">=4.19.2", - "fastify": ">=4.21.0", - "h3": ">=1.8.1", - "hono": ">=4.2.7", - "koa": ">=2.14.2", - "next": ">=12.0.0", - "typescript": ">=5.8.0", - "zod": ">=3.24.0" + "d3-path": "^3.1.0" }, - "peerDependenciesMeta": { - "@sveltejs/kit": { - "optional": true - }, - "@vercel/node": { - "optional": true - }, - "aws-lambda": { - "optional": true - }, - "express": { - "optional": true - }, - "fastify": { - "optional": true - }, - "h3": { - "optional": true - }, - "hono": { - "optional": true - }, - "koa": { - "optional": true - }, - "next": { - "optional": true - }, - "typescript": { - "optional": true - } + "engines": { + "node": ">=12" } }, - "node_modules/inngest-cli": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/inngest-cli/-/inngest-cli-1.12.1.tgz", - "integrity": "sha512-1Q/bQ1LDjAKFbLiZ6mycjzORyqFSkSaPIIq3FMJekxnenSOz8THn35G9/f61rCEQJXYI+LnWeXExUNUdKdb9eA==", - "dev": true, - "hasInstallScript": true, - "license": "SEE LICENSE IN LICENSE.md", + "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": { - "adm-zip": "^0.5.10", - "debug": "^4.3.4", - "node-fetch": "^2.6.7", - "tar": "^6.2.1" + "d3-array": "2 - 3" }, - "bin": { - "inngest": "bin/inngest", - "inngest-cli": "bin/inngest" - } - }, - "node_modules/inngest-cli/node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/inngest-cli/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, + "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": ">=8" + "node": ">=12" } }, - "node_modules/inngest-cli/node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, + "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": ">= 8" + "node": ">=12" } }, - "node_modules/inngest-cli/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", "license": "ISC", "dependencies": { - "yallist": "^4.0.0" + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" } }, - "node_modules/inngest-cli/node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", "license": "ISC", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/inngest-cli/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/input-otp": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz", - "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==", + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", "license": "MIT", - "peerDependencies": { - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" } }, - "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", + "node_modules/date-fns-jalali": { + "version": "4.1.0-0", + "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz", + "integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==", + "license": "MIT" + }, + "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/detect-libc": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.1.tgz", + "integrity": "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==", + "devOptional": true, + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/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/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": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" } }, - "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==", + "node_modules/embla-carousel": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.6.0.tgz", + "integrity": "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==", + "license": "MIT" + }, + "node_modules/embla-carousel-react": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz", + "integrity": "sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==", "license": "MIT", "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" + "embla-carousel": "8.6.0", + "embla-carousel-reactive-utils": "8.6.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/embla-carousel-reactive-utils": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.6.0.tgz", + "integrity": "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "embla-carousel": "8.6.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/enhanced-resolve": { + "version": "5.18.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", + "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", + "dev": true, "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/esbuild": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", + "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" + "bin": { + "esbuild": "bin/esbuild" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/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-equals": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.3.2.tgz", + "integrity": "sha512-6rxyATwPCkaFIL3JLqw8qXqMpIZ942pTX/tbQFkRsDGblS8tNGtlUauA/+mt6RUfqn/4MoEr+WDkYoIQbibWuQ==", "license": "MIT", "engines": { - "node": ">=0.12.0" + "node": ">=6.0.0" } }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@types/estree": "*" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "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": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/is-what": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12.13" + "dependencies": { + "resolve-pkg-maps": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/mesqueeb" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, "license": "ISC" }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "node_modules/input-otp": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/input-otp/-/input-otp-1.4.2.tgz", + "integrity": "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==", "license": "MIT", - "peer": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "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": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=12" } }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" } }, - "node_modules/jose": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.0.tgz", - "integrity": "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, "node_modules/jotai": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.15.0.tgz", @@ -9568,65 +3756,6 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "license": "MIT", - "dependencies": { - "bignumber.js": "^9.0.0" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "license": "MIT", - "peer": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT", - "peer": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "license": "ISC" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/ky": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/ky/-/ky-1.12.0.tgz", @@ -9639,15 +3768,6 @@ "url": "https://github.com/sindresorhus/ky?sponsor=1" } }, - "node_modules/kysely": { - "version": "0.28.7", - "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.7.tgz", - "integrity": "sha512-u/cAuTL4DRIiO2/g4vNGRgklEKNIj5Q3CG7RoUB5DV5SfEC2hMvPxKi0GWPmnzwL2ryIeud2VTcEEmqzTzEPNw==", - "license": "MIT", - "engines": { - "node": ">=20.0.0" - } - }, "node_modules/lightningcss": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", @@ -9887,49 +4007,12 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "license": "MIT" - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -9942,21 +4025,6 @@ "loose-envify": "cli.js" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lru-cache/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC" - }, "node_modules/lucide-react": { "version": "0.544.0", "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.544.0.tgz", @@ -9970,92 +4038,17 @@ "version": "0.30.19", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/markdown-to-jsx": { - "version": "7.7.15", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.7.15.tgz", - "integrity": "sha512-U5dw5oRajrPTE2oJQWAbLK8RgbCDJ264AjW3fGABq+/rZjQ0E/WGVCLKAHvpKHQFUwoWoK8ZZWVPNLR/biYMhg==", - "license": "MIT", - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "react": ">= 0.14.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT", - "peer": true - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "peer": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "license": "ISC" - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -10074,44 +4067,6 @@ "node": ">= 18" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/module-details-from-path": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", - "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", - "license": "MIT" - }, - "node_modules/mprocs": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/mprocs/-/mprocs-0.7.3.tgz", - "integrity": "sha512-I1Ptja/UnNVVSV5QEnBdiiwW70HMWJlmnMq6nvw4J7fwZ3s8UZGuf/FG+FTAUr6CLfat8kriHj+mWLx7xsLKSw==", - "dev": true, - "license": "MIT", - "bin": { - "mprocs": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -10130,27 +4085,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/nanostores": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nanostores/-/nanostores-1.0.1.tgz", - "integrity": "sha512-kNZ9xnoJYKg/AfxjrVL4SS0fKX++4awQReGqWnwTRHxeHGZ1FJFVgTqr/eMrNQdp0Tz7M7tG/TDaX8QfHDwVCw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "engines": { - "node": "^20.0.0 || >=22.0.0" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "license": "MIT" - }, "node_modules/next": { "version": "15.5.4", "resolved": "https://registry.npmjs.org/next/-/next-15.5.4.tgz", @@ -10241,47 +4175,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch-native": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.23.tgz", - "integrity": "sha512-cCmFDMSm26S6tQSDpBCg/NR8NENrVPhAJSf+XbxBG4rPFaaonlEoE9wHQmun+cls499TQGSb7ZyPBRlzgKfpeg==", - "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/nuqs": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/nuqs/-/nuqs-2.7.1.tgz", @@ -10319,173 +4212,13 @@ } } }, - "node_modules/nypm": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz", - "integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.4.2", - "pathe": "^2.0.3", - "pkg-types": "^2.3.0", - "tinyexec": "^1.0.1" - }, - "bin": { - "nypm": "dist/cli.mjs" - }, - "engines": { - "node": "^14.16.0 || >=16.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/ofetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", - "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", - "license": "MIT", - "dependencies": { - "destr": "^2.0.3", - "node-fetch-native": "^1.6.4", - "ufo": "^1.5.4" - } - }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "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==", - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "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==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/perfect-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", - "devOptional": true, - "license": "MIT" - }, - "node_modules/pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "license": "ISC", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pg-protocol": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", - "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", - "license": "MIT" - }, - "node_modules/pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "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", - "dependencies": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/picocolors": { @@ -10494,30 +4227,6 @@ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-types": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", - "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.2.2", - "exsolve": "^1.0.7", - "pathe": "^2.0.3" - } - }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -10547,80 +4256,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prisma": { - "version": "6.16.3", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-6.16.3.tgz", - "integrity": "sha512-4tJq3KB9WRshH5+QmzOLV54YMkNlKOtLKaSdvraI5kC/axF47HuOw6zDM8xrxJ6s9o2WodY654On4XKkrobQdQ==", - "devOptional": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@prisma/config": "6.16.3", - "@prisma/engines": "6.16.3" - }, - "bin": { - "prisma": "build/index.js" - }, - "engines": { - "node": ">=18.18" - }, - "peerDependencies": { - "typescript": ">=5.1.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -10638,98 +4273,12 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, - "node_modules/protobufjs": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", - "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "devOptional": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/pvtsutils": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", - "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.8.1" - } - }, - "node_modules/pvutils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", - "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/random-word-slugs": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/random-word-slugs/-/random-word-slugs-0.1.7.tgz", "integrity": "sha512-8cyzxOIDeLFvwSPTgCItMXHGT5ZPkjhuFKUTww06Xg1dNMXuGxIKlARvS7upk6JXIm41ZKXmtlKR1iCRWklKmg==", "license": "MIT" }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rc9": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", - "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", - "devOptional": true, - "license": "MIT", - "dependencies": { - "defu": "^6.1.4", - "destr": "^2.0.3" - } - }, "node_modules/react": { "version": "19.1.0", "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", @@ -10916,20 +4465,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "devOptional": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/recharts": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.4.tgz", @@ -10962,65 +4497,6 @@ "decimal.js-light": "^2.4.1" } }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "license": "Apache-2.0" - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "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-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -11031,105 +4507,18 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/rollup": { - "version": "4.52.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.4.tgz", - "integrity": "sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.52.4", - "@rollup/rollup-android-arm64": "4.52.4", - "@rollup/rollup-darwin-arm64": "4.52.4", - "@rollup/rollup-darwin-x64": "4.52.4", - "@rollup/rollup-freebsd-arm64": "4.52.4", - "@rollup/rollup-freebsd-x64": "4.52.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.52.4", - "@rollup/rollup-linux-arm-musleabihf": "4.52.4", - "@rollup/rollup-linux-arm64-gnu": "4.52.4", - "@rollup/rollup-linux-arm64-musl": "4.52.4", - "@rollup/rollup-linux-loong64-gnu": "4.52.4", - "@rollup/rollup-linux-ppc64-gnu": "4.52.4", - "@rollup/rollup-linux-riscv64-gnu": "4.52.4", - "@rollup/rollup-linux-riscv64-musl": "4.52.4", - "@rollup/rollup-linux-s390x-gnu": "4.52.4", - "@rollup/rollup-linux-x64-gnu": "4.52.4", - "@rollup/rollup-linux-x64-musl": "4.52.4", - "@rollup/rollup-openharmony-arm64": "4.52.4", - "@rollup/rollup-win32-arm64-msvc": "4.52.4", - "@rollup/rollup-win32-ia32-msvc": "4.52.4", - "@rollup/rollup-win32-x64-gnu": "4.52.4", - "@rollup/rollup-win32-x64-msvc": "4.52.4", - "fsevents": "~2.3.2" - } - }, - "node_modules/rou3": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/rou3/-/rou3-0.5.1.tgz", - "integrity": "sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==", - "license": "MIT" - }, - "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", - "peer": true - }, "node_modules/scheduler": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", "license": "MIT" }, - "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/semver": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", + "optional": true, "bin": { "semver": "bin/semver.js" }, @@ -11137,38 +4526,6 @@ "node": ">=10" } }, - "node_modules/serialize-error-cjs": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/serialize-error-cjs/-/serialize-error-cjs-0.1.4.tgz", - "integrity": "sha512-6a6dNqipzbCPlTFgztfNP2oG+IGcflMe/01zSzGrQcxGMKbIjOemBBD85pH92klWaJavAUWxAh9Z0aU28zxW6A==", - "deprecated": "Rolling release, please update to 0.2.0", - "license": "MIT-0", - "funding": { - "url": "https://github.com/sponsors/finwo" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/server-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", - "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", - "license": "MIT" - }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, "node_modules/sharp": { "version": "0.34.4", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", @@ -11212,35 +4569,6 @@ "@img/sharp-win32-x64": "0.34.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/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" - }, "node_modules/sonner": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", @@ -11251,102 +4579,13 @@ "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/stacktrace-parser": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", - "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", - "license": "MIT", - "dependencies": { - "type-fest": "^0.7.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/standardwebhooks": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz", - "integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==", - "license": "MIT", - "dependencies": { - "@stablelib/base64": "^1.0.0", - "fast-sha256": "^1.3.0" - } - }, - "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==", - "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/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, "node_modules/styled-jsx": { @@ -11372,42 +4611,6 @@ } } }, - "node_modules/superjson": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", - "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", - "license": "MIT", - "dependencies": { - "copy-anything": "^3.0.2" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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": "3.3.1", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", @@ -11429,6 +4632,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -11455,112 +4659,12 @@ "node": ">=18" } }, - "node_modules/temporal-polyfill": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.2.5.tgz", - "integrity": "sha512-ye47xp8Cb0nDguAhrrDS1JT1SzwEV9e26sSsrWzVu+yPZ7LzceEcH0i2gci9jWfOfSCCgM3Qv5nOYShVUUFUXA==", - "license": "MIT", - "dependencies": { - "temporal-spec": "^0.2.4" - } - }, - "node_modules/temporal-spec": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.2.4.tgz", - "integrity": "sha512-lDMFv4nKQrSjlkHKAlHVqKrBG4DyFfa9F74cmBZ3Iy3ed8yvWnlWSIdi4IKfSqwmazAohBNwiN64qGx4y5Q3IQ==", - "license": "ISC" - }, - "node_modules/terser": { - "version": "5.44.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", - "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, "node_modules/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/tinyexec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", - "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", - "devOptional": true, - "license": "MIT" - }, - "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/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", - "license": "MIT" - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -11587,24 +4691,6 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsyringe": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", - "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", - "license": "MIT", - "dependencies": { - "tslib": "^1.9.3" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/tsyringe/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "license": "0BSD" - }, "node_modules/tw-animate-css": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", @@ -11615,19 +4701,11 @@ "url": "https://github.com/sponsors/Wombosvideo" } }, - "node_modules/type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -11637,127 +4715,13 @@ "node": ">=14.17" } }, - "node_modules/ufo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uncrypto": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", - "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", - "license": "MIT" - }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, "license": "MIT" }, - "node_modules/unplugin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", - "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", - "license": "MIT", - "dependencies": { - "acorn": "^8.8.1", - "chokidar": "^3.5.3", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.5.0" - } - }, - "node_modules/unplugin/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/unplugin/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/unplugin/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/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "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/use-callback-ref": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", @@ -11810,19 +4774,6 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/vaul": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vaul/-/vaul-1.1.2.tgz", @@ -11858,177 +4809,6 @@ "d3-timer": "^3.0.1" } }, - "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", - "license": "MIT", - "peer": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/webpack": { - "version": "5.102.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz", - "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.26.3", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.3", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.4", - "webpack-sources": "^3.3.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-virtual-modules": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", - "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", - "license": "MIT" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "license": "MIT" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "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/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==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/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==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", @@ -12039,45 +4819,6 @@ "node": ">=18" } }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/zod": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz", diff --git a/package.json b/package.json index a3f5a3e..2313e3a 100644 --- a/package.json +++ b/package.json @@ -7,21 +7,11 @@ "build": "next build --turbopack", "start": "next start", "lint": "biome check", - "ngrok:dev": "dotenv -- ngrok http --url=$NGROK_URL 3000", - "format": "biome format --write", - "inngest:dev": "inngest-cli dev", - "dev:all": "dotenv -- mprocs" + "format": "biome format --write" }, "dependencies": { - "@ai-sdk/anthropic": "^2.0.23", - "@ai-sdk/google": "^2.0.17", - "@ai-sdk/openai": "^2.0.44", "@hookform/resolvers": "^5.2.2", - "@inngest/realtime": "^0.4.4", "@paralleldrive/cuid2": "^2.2.2", - "@polar-sh/better-auth": "^1.1.9", - "@polar-sh/sdk": "^0.35.4", - "@prisma/client": "^6.16.3", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-aspect-ratio": "^1.1.7", @@ -48,24 +38,14 @@ "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", - "@sentry/nextjs": "^10.18.0", "@tanstack/react-query": "^5.90.2", - "@trpc/client": "^11.6.0", - "@trpc/server": "^11.6.0", - "@trpc/tanstack-react-query": "^11.6.0", "@xyflow/react": "^12.8.6", - "ai": "^5.0.60", - "better-auth": "^1.3.26", "class-variance-authority": "^0.7.1", "client-only": "^0.0.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", - "cryptr": "^6.4.0", "date-fns": "^4.1.0", "embla-carousel-react": "^8.6.0", - "handlebars": "^4.7.8", - "html-entities": "^2.6.0", - "inngest": "^3.44.1", "input-otp": "^1.4.2", "jotai": "^2.15.0", "ky": "^1.12.0", @@ -81,11 +61,8 @@ "react-hook-form": "^7.64.0", "react-resizable-panels": "^3.0.6", "recharts": "^2.15.4", - "server-only": "^0.0.1", "sonner": "^2.0.7", - "superjson": "^2.2.2", "tailwind-merge": "^3.3.1", - "toposort": "^2.0.2", "vaul": "^1.1.2", "zod": "^4.1.11" }, @@ -95,14 +72,9 @@ "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "@types/toposort": "^2.0.7", - "dotenv-cli": "^10.0.0", - "inngest-cli": "^1.12.1", - "mprocs": "^0.7.3", - "prisma": "^6.16.3", "tailwindcss": "^4", "tsx": "^4.20.6", "tw-animate-css": "^1.4.0", "typescript": "^5" } -} +} \ No newline at end of file diff --git a/prisma/migrations/20251004215101_init/migration.sql b/prisma/migrations/20251004215101_init/migration.sql deleted file mode 100644 index 22d9117..0000000 --- a/prisma/migrations/20251004215101_init/migration.sql +++ /dev/null @@ -1,25 +0,0 @@ --- CreateTable -CREATE TABLE "User" ( - "id" SERIAL NOT NULL, - "email" TEXT NOT NULL, - "name" TEXT, - - CONSTRAINT "User_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Post" ( - "id" SERIAL NOT NULL, - "title" TEXT NOT NULL, - "content" TEXT, - "published" BOOLEAN NOT NULL DEFAULT false, - "authorId" INTEGER NOT NULL, - - CONSTRAINT "Post_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); - --- AddForeignKey -ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20251005141345_better_auth_fields/migration.sql b/prisma/migrations/20251005141345_better_auth_fields/migration.sql deleted file mode 100644 index 4dc051d..0000000 --- a/prisma/migrations/20251005141345_better_auth_fields/migration.sql +++ /dev/null @@ -1,85 +0,0 @@ -/* - Warnings: - - - You are about to drop the `Post` table. If the table is not empty, all the data it contains will be lost. - - You are about to drop the `User` table. If the table is not empty, all the data it contains will be lost. - -*/ --- DropForeignKey -ALTER TABLE "public"."Post" DROP CONSTRAINT "Post_authorId_fkey"; - --- DropTable -DROP TABLE "public"."Post"; - --- DropTable -DROP TABLE "public"."User"; - --- CreateTable -CREATE TABLE "user" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "email" TEXT NOT NULL, - "emailVerified" BOOLEAN NOT NULL DEFAULT false, - "image" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "user_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "session" ( - "id" TEXT NOT NULL, - "expiresAt" TIMESTAMP(3) NOT NULL, - "token" TEXT NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "ipAddress" TEXT, - "userAgent" TEXT, - "userId" TEXT NOT NULL, - - CONSTRAINT "session_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "account" ( - "id" TEXT NOT NULL, - "accountId" TEXT NOT NULL, - "providerId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "accessToken" TEXT, - "refreshToken" TEXT, - "idToken" TEXT, - "accessTokenExpiresAt" TIMESTAMP(3), - "refreshTokenExpiresAt" TIMESTAMP(3), - "scope" TEXT, - "password" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "account_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "verification" ( - "id" TEXT NOT NULL, - "identifier" TEXT NOT NULL, - "value" TEXT NOT NULL, - "expiresAt" TIMESTAMP(3) NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - - CONSTRAINT "verification_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "user_email_key" ON "user"("email"); - --- CreateIndex -CREATE UNIQUE INDEX "session_token_key" ON "session"("token"); - --- AddForeignKey -ALTER TABLE "session" ADD CONSTRAINT "session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "account" ADD CONSTRAINT "account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20251006121458_workflows_table/migration.sql b/prisma/migrations/20251006121458_workflows_table/migration.sql deleted file mode 100644 index f75b101..0000000 --- a/prisma/migrations/20251006121458_workflows_table/migration.sql +++ /dev/null @@ -1,7 +0,0 @@ --- CreateTable -CREATE TABLE "Workflow" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - - CONSTRAINT "Workflow_pkey" PRIMARY KEY ("id") -); diff --git a/prisma/migrations/20251008163512_workflows_update/migration.sql b/prisma/migrations/20251008163512_workflows_update/migration.sql deleted file mode 100644 index 1b353a0..0000000 --- a/prisma/migrations/20251008163512_workflows_update/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ -/* - Warnings: - - - Added the required column `updatedAt` to the `Workflow` table without a default value. This is not possible if the table is not empty. - - Added the required column `userId` to the `Workflow` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "Workflow" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL, -ADD COLUMN "userId" TEXT NOT NULL; - --- AddForeignKey -ALTER TABLE "Workflow" ADD CONSTRAINT "Workflow_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20251011150739_react_flow_tables/migration.sql b/prisma/migrations/20251011150739_react_flow_tables/migration.sql deleted file mode 100644 index d2c92e7..0000000 --- a/prisma/migrations/20251011150739_react_flow_tables/migration.sql +++ /dev/null @@ -1,45 +0,0 @@ --- CreateEnum -CREATE TYPE "NodeType" AS ENUM ('INITIAL'); - --- CreateTable -CREATE TABLE "Node" ( - "id" TEXT NOT NULL, - "workflowId" TEXT NOT NULL, - "name" TEXT NOT NULL, - "type" "NodeType" NOT NULL, - "position" JSONB NOT NULL, - "data" JSONB NOT NULL DEFAULT '{}', - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Node_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "Connection" ( - "id" TEXT NOT NULL, - "workflowId" TEXT NOT NULL, - "fromNodeId" TEXT NOT NULL, - "toNodeId" TEXT NOT NULL, - "fromOutput" TEXT NOT NULL DEFAULT 'main', - "toInput" TEXT NOT NULL DEFAULT 'main', - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "Connection_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "Connection_fromNodeId_toNodeId_fromOutput_toInput_key" ON "Connection"("fromNodeId", "toNodeId", "fromOutput", "toInput"); - --- AddForeignKey -ALTER TABLE "Node" ADD CONSTRAINT "Node_workflowId_fkey" FOREIGN KEY ("workflowId") REFERENCES "Workflow"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Connection" ADD CONSTRAINT "Connection_workflowId_fkey" FOREIGN KEY ("workflowId") REFERENCES "Workflow"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Connection" ADD CONSTRAINT "Connection_fromNodeId_fkey" FOREIGN KEY ("fromNodeId") REFERENCES "Node"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Connection" ADD CONSTRAINT "Connection_toNodeId_fkey" FOREIGN KEY ("toNodeId") REFERENCES "Node"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20251011201738_new_nodes/migration.sql b/prisma/migrations/20251011201738_new_nodes/migration.sql deleted file mode 100644 index 5a00432..0000000 --- a/prisma/migrations/20251011201738_new_nodes/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ --- AlterEnum --- This migration adds more than one value to an enum. --- With PostgreSQL versions 11 and earlier, this is not possible --- in a single migration. This can be worked around by creating --- multiple migrations, each migration adding only one value to --- the enum. - - -ALTER TYPE "NodeType" ADD VALUE 'MANUAL_TRIGGER'; -ALTER TYPE "NodeType" ADD VALUE 'HTTP_REQUEST'; diff --git a/prisma/migrations/20251028194714_google_form_trigger_node/migration.sql b/prisma/migrations/20251028194714_google_form_trigger_node/migration.sql deleted file mode 100644 index 344deed..0000000 --- a/prisma/migrations/20251028194714_google_form_trigger_node/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterEnum -ALTER TYPE "NodeType" ADD VALUE 'GOOGLE_FORM_TRIGGER'; diff --git a/prisma/migrations/20251029133828_stripe_trigger_node/migration.sql b/prisma/migrations/20251029133828_stripe_trigger_node/migration.sql deleted file mode 100644 index cf13256..0000000 --- a/prisma/migrations/20251029133828_stripe_trigger_node/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterEnum -ALTER TYPE "NodeType" ADD VALUE 'STRIPE_TRIGGER'; diff --git a/prisma/migrations/20251030202057_ai_nodes_schema/migration.sql b/prisma/migrations/20251030202057_ai_nodes_schema/migration.sql deleted file mode 100644 index 00f58bc..0000000 --- a/prisma/migrations/20251030202057_ai_nodes_schema/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ --- AlterEnum --- This migration adds more than one value to an enum. --- With PostgreSQL versions 11 and earlier, this is not possible --- in a single migration. This can be worked around by creating --- multiple migrations, each migration adding only one value to --- the enum. - - -ALTER TYPE "NodeType" ADD VALUE 'ANTHROPIC'; -ALTER TYPE "NodeType" ADD VALUE 'GEMINI'; -ALTER TYPE "NodeType" ADD VALUE 'OPENAI'; diff --git a/prisma/migrations/20251031173138_credentials_schema/migration.sql b/prisma/migrations/20251031173138_credentials_schema/migration.sql deleted file mode 100644 index 1387882..0000000 --- a/prisma/migrations/20251031173138_credentials_schema/migration.sql +++ /dev/null @@ -1,24 +0,0 @@ --- CreateEnum -CREATE TYPE "CredentialType" AS ENUM ('OPENAI', 'ANTHROPIC', 'GEMINI'); - --- AlterTable -ALTER TABLE "Node" ADD COLUMN "credentialId" TEXT; - --- CreateTable -CREATE TABLE "Credential" ( - "id" TEXT NOT NULL, - "name" TEXT NOT NULL, - "value" TEXT NOT NULL, - "type" "CredentialType" NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updatedAt" TIMESTAMP(3) NOT NULL, - "userId" TEXT NOT NULL, - - CONSTRAINT "Credential_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "Credential" ADD CONSTRAINT "Credential_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Node" ADD CONSTRAINT "Node_credentialId_fkey" FOREIGN KEY ("credentialId") REFERENCES "Credential"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20251101143353_discord_slack_node/migration.sql b/prisma/migrations/20251101143353_discord_slack_node/migration.sql deleted file mode 100644 index 1d4a019..0000000 --- a/prisma/migrations/20251101143353_discord_slack_node/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ --- AlterEnum --- This migration adds more than one value to an enum. --- With PostgreSQL versions 11 and earlier, this is not possible --- in a single migration. This can be worked around by creating --- multiple migrations, each migration adding only one value to --- the enum. - - -ALTER TYPE "NodeType" ADD VALUE 'DISCORD'; -ALTER TYPE "NodeType" ADD VALUE 'SLACK'; diff --git a/prisma/migrations/20251101231745_executions_schema/migration.sql b/prisma/migrations/20251101231745_executions_schema/migration.sql deleted file mode 100644 index 971b5cd..0000000 --- a/prisma/migrations/20251101231745_executions_schema/migration.sql +++ /dev/null @@ -1,23 +0,0 @@ --- CreateEnum -CREATE TYPE "ExecutionStatus" AS ENUM ('RUNNING', 'SUCCESS', 'FAILED'); - --- CreateTable -CREATE TABLE "Execution" ( - "id" TEXT NOT NULL, - "workflowId" TEXT NOT NULL, - "status" "ExecutionStatus" NOT NULL DEFAULT 'RUNNING', - "error" TEXT, - "errorStack" TEXT, - "startedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "completedAt" TIMESTAMP(3), - "inngestEventId" TEXT NOT NULL, - "output" JSONB, - - CONSTRAINT "Execution_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "Execution_inngestEventId_key" ON "Execution"("inngestEventId"); - --- AddForeignKey -ALTER TABLE "Execution" ADD CONSTRAINT "Execution_workflowId_fkey" FOREIGN KEY ("workflowId") REFERENCES "Workflow"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml deleted file mode 100644 index 044d57c..0000000 --- a/prisma/migrations/migration_lock.toml +++ /dev/null @@ -1,3 +0,0 @@ -# Please do not edit this file manually -# It should be added in your version-control system (e.g., Git) -provider = "postgresql" diff --git a/sentry.edge.config.ts b/sentry.edge.config.ts deleted file mode 100644 index aacae83..0000000 --- a/sentry.edge.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -// This file configures the initialization of Sentry for edge features (middleware, edge routes, and so on). -// The config you add here will be used whenever one of the edge features is loaded. -// Note that this config is unrelated to the Vercel Edge Runtime and is also required when running locally. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -Sentry.init({ - dsn: "https://f1a2853e6bb4b74c72976cd5c3b37dd9@o4507629901053952.ingest.de.sentry.io/4510150041337936", - - integrations: [ - Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }), - ], - - // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. - tracesSampleRate: 1, - - // Enable logs to be sent to Sentry - enableLogs: true, - - // Setting this option to true will print useful information to the console while you're setting up Sentry. - debug: false, -}); diff --git a/sentry.server.config.ts b/sentry.server.config.ts deleted file mode 100644 index f5dd1f4..0000000 --- a/sentry.server.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -// This file configures the initialization of Sentry on the server. -// The config you add here will be used whenever the server handles a request. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -Sentry.init({ - dsn: "https://f1a2853e6bb4b74c72976cd5c3b37dd9@o4507629901053952.ingest.de.sentry.io/4510150041337936", - - integrations: [ - // Add the Vercel AI SDK integration to sentry.server.config.ts - Sentry.vercelAIIntegration({ - recordInputs: true, - recordOutputs: true, - }), - Sentry.consoleLoggingIntegration({ levels: ["log", "warn", "error"] }), - ], - - // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. - tracesSampleRate: 1, - sendDefaultPii: true, - - // Enable logs to be sent to Sentry - enableLogs: true, - - // Setting this option to true will print useful information to the console while you're setting up Sentry. - debug: false, -}); diff --git a/src/api/auth.ts b/src/api/auth.ts new file mode 100644 index 0000000..8d41a68 --- /dev/null +++ b/src/api/auth.ts @@ -0,0 +1,63 @@ +import api from "./client"; + +// ─── Types + +export interface User { + id: string; + name: string; + email: string; + image?: string | null; + created_at?: string; +} + +interface AuthResponse { + success: boolean; + message: string; + data: { + user: User; + }; +} + +interface MeResponse { + success: boolean; + data: { + user: { id: string; email: string }; + }; +} + +// ─── API calls + +export async function registerUser(payload: { + name: string; + email: string; + password: string; +}): Promise { + return api.post("api/auth/register", { json: payload }).json(); +} + +export async function loginUser(payload: { + email: string; + password: string; +}): Promise { + return api.post("api/auth/login", { json: payload }).json(); +} + +export async function logoutUser(): Promise<{ success: boolean; message: string }> { + return api.post("api/auth/logout").json(); +} + +/** + * Check the current session by calling GET /api/auth/me. + * Returns the user if the cookie token is valid, or null on 401. + */ +export async function getMe(): Promise { + try { + const res = await api.get("api/auth/me").json(); + if (res.success && res.data?.user) { + return res.data.user as User; + } + return null; + } catch { + return null; + } +} diff --git a/src/api/client.ts b/src/api/client.ts new file mode 100644 index 0000000..7e624f9 --- /dev/null +++ b/src/api/client.ts @@ -0,0 +1,17 @@ +import ky from "ky"; + +const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000"; + +/** + * Pre-configured ky instance pointing at the backend. + * Sends cookies (credentials: "include") on every request. + */ +const api = ky.create({ + prefixUrl: API_BASE_URL, + credentials: "include", + headers: { + "Content-Type": "application/json", + }, +}); + +export default api; diff --git a/src/api/credentials.ts b/src/api/credentials.ts new file mode 100644 index 0000000..cbc90a6 --- /dev/null +++ b/src/api/credentials.ts @@ -0,0 +1,69 @@ +import api from "./client"; + +// ─── Types ────────────────────────────────────────────────── + +/** Raw credential shape from the backend (snake_case, value excluded). */ +export interface ApiCredential { + id: string; + name: string; + type: string; + created_at: string; + updated_at: string; +} + +interface ApiResponse { + success: boolean; + message?: string; + data: T; +} + +// ─── API Calls ────────────────────────────────────────────── + +/** Fetch paginated credentials for the current user. */ +export async function getCredentials(params: { page?: number; pageSize?: number } = {}) { + const searchParams = new URLSearchParams(); + if (params.page) searchParams.set("page", String(params.page)); + if (params.pageSize) searchParams.set("pageSize", String(params.pageSize)); + + const res = await api + .get("api/credentials", { searchParams }) + .json>(); + return res.data; +} + +/** Fetch a single credential by ID (value is excluded for safety). */ +export async function getCredential(id: string) { + const res = await api + .get(`api/credentials/${id}`) + .json>(); + return res.data.credential; +} + +/** Fetch credentials filtered by type. */ +export async function getCredentialsByType(type: string) { + const res = await api + .get(`api/credentials/type/${type}`) + .json>(); + return res.data.credentials; +} + +/** Create a new credential. */ +export async function createCredential(payload: { name: string; type: string; value: string }) { + const res = await api + .post("api/credentials", { json: payload }) + .json>(); + return res.data.credential; +} + +/** Update a credential (name and/or value). */ +export async function updateCredential(id: string, payload: { name?: string; value?: string }) { + const res = await api + .patch(`api/credentials/${id}`, { json: payload }) + .json>(); + return res.data.credential; +} + +/** Delete a credential. */ +export async function deleteCredential(id: string) { + await api.delete(`api/credentials/${id}`).json(); +} diff --git a/src/api/workflows.ts b/src/api/workflows.ts new file mode 100644 index 0000000..8b7cc8c --- /dev/null +++ b/src/api/workflows.ts @@ -0,0 +1,103 @@ +import api from "./client"; + +// ─── Types ────────────────────────────────────────────────── + +/** Raw workflow shape from the backend (snake_case). */ +export interface ApiWorkflow { + id: string; + name: string; + created_at: string; + updated_at: string; + nodes?: ApiNode[]; + connections?: ApiConnection[]; +} + +export interface ApiNode { + id: string; + name: string; + type: string; + position: { x: number; y: number }; + data: Record; + credential_id: string | null; + created_at: string; + updated_at: string; +} + +export interface ApiConnection { + id: string; + from_node_id: string; + to_node_id: string; + from_output: string; + to_input: string; +} + +interface ApiResponse { + success: boolean; + message?: string; + data: T; +} + +// ─── API Calls ────────────────────────────────────────────── + +/** Fetch paginated workflows for the current user. */ +export async function getWorkflows(params: { page?: number; pageSize?: number } = {}) { + const searchParams = new URLSearchParams(); + if (params.page) searchParams.set("page", String(params.page)); + if (params.pageSize) searchParams.set("pageSize", String(params.pageSize)); + + const res = await api + .get("api/workflows", { searchParams }) + .json>(); + return res.data; +} + +/** Fetch a single workflow with its nodes and connections. */ +export async function getWorkflow(id: string) { + const res = await api + .get(`api/workflows/${id}`) + .json>(); + return res.data.workflow; +} + +/** Create a new workflow. */ +export async function createWorkflow(payload: { name: string }) { + const res = await api + .post("api/workflows", { json: payload }) + .json>(); + return res.data.workflow; +} + +/** Rename a workflow. */ +export async function updateWorkflowName(id: string, name: string) { + const res = await api + .patch(`api/workflows/${id}/name`, { json: { name } }) + .json>(); + return res.data.workflow; +} + +/** Delete a workflow. */ +export async function deleteWorkflow(id: string) { + await api.delete(`api/workflows/${id}`).json(); +} + +/** Trigger a workflow execution (returns the new execution row). */ +export async function executeWorkflow(id: string) { + const res = await api + .post(`api/workflows/${id}/execute`) + .json>(); + return res.data.execution; +} + +/** Save the full workflow graph (nodes + connections). */ +export async function saveWorkflow( + id: string, + payload: { + nodes: { id: string; type: string; name: string; position: { x: number; y: number }; data: Record; credential_id?: string | null }[]; + connections: { id: string; from_node_id: string; to_node_id: string; from_output: string; to_input: string }[]; + }, +) { + const res = await api + .put(`api/workflows/${id}`, { json: payload }) + .json>(); + return res.data.workflow; +} diff --git a/src/app/(dashboard)/(editor)/workflows/[workflowId]/page.tsx b/src/app/(dashboard)/(editor)/workflows/[workflowId]/page.tsx index d883009..b63e5b9 100644 --- a/src/app/(dashboard)/(editor)/workflows/[workflowId]/page.tsx +++ b/src/app/(dashboard)/(editor)/workflows/[workflowId]/page.tsx @@ -1,38 +1,32 @@ -import { - Editor, - EditorError, +import { + Editor, + EditorError, EditorLoading } from "@/features/editor/components/editor"; import { EditorHeader } from "@/features/editor/components/editor-header"; -import { prefetchWorkflow } from "@/features/workflows/server/prefetch"; -import { requireAuth } from "@/lib/auth-utils"; -import { HydrateClient } from "@/trpc/server"; import { Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; interface PageProps { params: Promise<{ workflowId: string; - }> + }>; }; const Page = async ({ params }: PageProps) => { - await requireAuth(); + // await requireAuth(); // TODO: Re-enable when custom backend auth is ready const { workflowId } = await params; - prefetchWorkflow(workflowId); return ( - - }> - }> - -
- -
-
-
-
+ }> + }> + +
+ +
+
+
) }; diff --git a/src/app/(dashboard)/(rest)/credentials/[credentialId]/page.tsx b/src/app/(dashboard)/(rest)/credentials/[credentialId]/page.tsx index b8c99aa..1e84b51 100644 --- a/src/app/(dashboard)/(rest)/credentials/[credentialId]/page.tsx +++ b/src/app/(dashboard)/(rest)/credentials/[credentialId]/page.tsx @@ -1,33 +1,27 @@ import { CredentialView } from "@/features/credentials/components/credential"; import { CredentialsError, CredentialsLoading } from "@/features/credentials/components/credentials"; -import { prefetchCredential } from "@/features/credentials/server/prefetch"; -import { requireAuth } from "@/lib/auth-utils"; -import { HydrateClient } from "@/trpc/server"; import { Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; interface PageProps { params: Promise<{ credentialId: string; - }> + }>; }; const Page = async ({ params }: PageProps) => { - await requireAuth(); + // await requireAuth(); // TODO: Re-enable when custom backend auth is ready const { credentialId } = await params; - prefetchCredential(credentialId); return (
- - }> - }> - - - - + }> + }> + + +
) diff --git a/src/app/(dashboard)/(rest)/credentials/new/page.tsx b/src/app/(dashboard)/(rest)/credentials/new/page.tsx index 9879d36..aa14145 100644 --- a/src/app/(dashboard)/(rest)/credentials/new/page.tsx +++ b/src/app/(dashboard)/(rest)/credentials/new/page.tsx @@ -1,16 +1,16 @@ import { CredentialForm } from "@/features/credentials/components/credential"; -import { requireAuth } from "@/lib/auth-utils"; +// import { requireAuth } from "@/lib/auth-utils"; const Page = async () => { - await requireAuth(); + // await requireAuth(); - return ( + return (
- ); + ); } - + export default Page; diff --git a/src/app/(dashboard)/(rest)/credentials/page.tsx b/src/app/(dashboard)/(rest)/credentials/page.tsx index dac9869..b004456 100644 --- a/src/app/(dashboard)/(rest)/credentials/page.tsx +++ b/src/app/(dashboard)/(rest)/credentials/page.tsx @@ -1,31 +1,22 @@ import { CredentialsContainer, CredentialsError, CredentialsList, CredentialsLoading } from "@/features/credentials/components/credentials"; -import { credentialsParamsLoader } from "@/features/credentials/server/params-loader"; -import { prefetchCredentials } from "@/features/credentials/server/prefetch"; -import { requireAuth } from "@/lib/auth-utils"; -import { HydrateClient } from "@/trpc/server"; -import { SearchParams } from "nuqs"; import { Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; +import type { SearchParams } from "nuqs/server"; type Props = { searchParams: Promise; }; -const Page = async ({ searchParams }: Props) => { - await requireAuth(); - - const params = await credentialsParamsLoader(searchParams); - prefetchCredentials(params); +const Page = async ({ searchParams: _searchParams }: Props) => { + // await requireAuth(); // TODO: Re-enable when custom backend auth is ready return ( - - }> - }> - - - - + }> + }> + + + ); }; diff --git a/src/app/(dashboard)/(rest)/executions/[executionId]/page.tsx b/src/app/(dashboard)/(rest)/executions/[executionId]/page.tsx index 0c4d5c7..5bec952 100644 --- a/src/app/(dashboard)/(rest)/executions/[executionId]/page.tsx +++ b/src/app/(dashboard)/(rest)/executions/[executionId]/page.tsx @@ -1,33 +1,27 @@ import { ExecutionView } from "@/features/executions/components/execution"; import { ExecutionsError, ExecutionsLoading } from "@/features/executions/components/executions"; -import { prefetchExecution } from "@/features/executions/server/prefetch"; -import { requireAuth } from "@/lib/auth-utils"; -import { HydrateClient } from "@/trpc/server"; import { Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; interface PageProps { params: Promise<{ executionId: string; - }> + }>; }; const Page = async ({ params }: PageProps) => { - await requireAuth(); - + // await requireAuth(); // TODO: Re-enable when custom backend auth is ready + const { executionId } = await params; - prefetchExecution(executionId); return (
- - }> - }> - - - - + }> + }> + + +
) diff --git a/src/app/(dashboard)/(rest)/executions/page.tsx b/src/app/(dashboard)/(rest)/executions/page.tsx index c745262..8a02e05 100644 --- a/src/app/(dashboard)/(rest)/executions/page.tsx +++ b/src/app/(dashboard)/(rest)/executions/page.tsx @@ -1,31 +1,22 @@ import { ExecutionsContainer, ExecutionsError, ExecutionsList, ExecutionsLoading } from "@/features/executions/components/executions"; -import { executionsParamsLoader } from "@/features/executions/server/params-loader"; -import { prefetchExecutions } from "@/features/executions/server/prefetch"; -import { requireAuth } from "@/lib/auth-utils"; -import { HydrateClient } from "@/trpc/server"; -import { SearchParams } from "nuqs"; import { Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; +import type { SearchParams } from "nuqs/server"; type Props = { searchParams: Promise; }; -const Page = async ({ searchParams }: Props) => { - await requireAuth(); - - const params = await executionsParamsLoader(searchParams); - prefetchExecutions(params); +const Page = async ({ searchParams: _searchParams }: Props) => { + // await requireAuth(); // TODO: Re-enable when custom backend auth is ready return ( - - }> - }> - - - - + }> + }> + + + ); }; diff --git a/src/app/(dashboard)/(rest)/workflows/page.tsx b/src/app/(dashboard)/(rest)/workflows/page.tsx index 4ef84fe..62b1c6b 100644 --- a/src/app/(dashboard)/(rest)/workflows/page.tsx +++ b/src/app/(dashboard)/(rest)/workflows/page.tsx @@ -1,13 +1,9 @@ -import { - WorkflowsContainer, - WorkflowsList, +import { + WorkflowsContainer, + WorkflowsList, WorkflowsLoading, WorkflowsError, } from "@/features/workflows/components/workflows"; -import { workflowsParamsLoader } from "@/features/workflows/server/params-loader"; -import { prefetchWorkflows } from "@/features/workflows/server/prefetch"; -import { requireAuth } from "@/lib/auth-utils"; -import { HydrateClient } from "@/trpc/server"; import type { SearchParams } from "nuqs/server"; import { Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; @@ -16,21 +12,16 @@ type Props = { searchParams: Promise; } -const Page = async ({ searchParams }: Props) => { - await requireAuth(); - - const params = await workflowsParamsLoader(searchParams); - prefetchWorkflows(params); +const Page = async ({ searchParams: _searchParams }: Props) => { + // await requireAuth(); // TODO: Re-enable when custom backend auth is ready return ( - - }> - }> - - - - + }> + }> + + + ) }; diff --git a/src/app/api/auth/[...all]/route.ts b/src/app/api/auth/[...all]/route.ts deleted file mode 100644 index fcb1ef0..0000000 --- a/src/app/api/auth/[...all]/route.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { auth } from "@/lib/auth"; // path to your auth file -import { toNextJsHandler } from "better-auth/next-js"; - -export const { POST, GET } = toNextJsHandler(auth); diff --git a/src/app/api/inngest/route.ts b/src/app/api/inngest/route.ts deleted file mode 100644 index 2448d78..0000000 --- a/src/app/api/inngest/route.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { serve } from "inngest/next"; -import { inngest } from "@/inngest/client"; -import { executeWorkflow } from "@/inngest/functions"; - -// Create an API that serves zero functions -export const { GET, POST, PUT } = serve({ - client: inngest, - functions: [ - executeWorkflow, - ], -}); diff --git a/src/app/api/sentry-example-api/route.ts b/src/app/api/sentry-example-api/route.ts deleted file mode 100644 index a830cfa..0000000 --- a/src/app/api/sentry-example-api/route.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NextResponse } from "next/server"; - -export const dynamic = "force-dynamic"; -class SentryExampleAPIError extends Error { - constructor(message: string | undefined) { - super(message); - this.name = "SentryExampleAPIError"; - } -} -// A faulty API route to test Sentry's error monitoring -export function GET() { - throw new SentryExampleAPIError("This error is raised on the backend called by the example page."); - return NextResponse.json({ data: "Testing Sentry Error..." }); -} diff --git a/src/app/api/trpc/[trpc]/route.ts b/src/app/api/trpc/[trpc]/route.ts deleted file mode 100644 index 52ae71d..0000000 --- a/src/app/api/trpc/[trpc]/route.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { fetchRequestHandler } from '@trpc/server/adapters/fetch'; -import { createTRPCContext } from '@/trpc/init'; -import { appRouter } from '@/trpc/routers/_app'; -const handler = (req: Request) => - fetchRequestHandler({ - endpoint: '/api/trpc', - req, - router: appRouter, - createContext: createTRPCContext, - }); -export { handler as GET, handler as POST }; diff --git a/src/app/api/webhooks/google-form/route.ts b/src/app/api/webhooks/google-form/route.ts deleted file mode 100644 index c9c9acc..0000000 --- a/src/app/api/webhooks/google-form/route.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { sendWorkflowExecution } from "@/inngest/utils"; -import { type NextRequest, NextResponse } from "next/server"; - -export async function POST(request: NextRequest) { - try { - const url = new URL(request.url); - const workflowId = url.searchParams.get("workflowId"); - - if (!workflowId) { - return NextResponse.json( - { success: false, error: "Missing required query parameter: workflowId" }, - { status: 400 }, - ); - }; - - const body = await request.json(); - - const formData = { - formId: body.formId, - formTitle: body.formTitle, - responseId: body.responseId, - timestamp: body.timestamp, - respondentEmail: body.respondentEmail, - responses: body.responses, - raw: body, - }; - - // Trigger an Inngest job - await sendWorkflowExecution({ - workflowId, - initialData: { - googleForm: formData, - }, - }); - - return NextResponse.json( - { success: true }, - { status: 200 }, - ); - } catch (error) { - console.error("Google form webhook error:" , error); - return NextResponse.json( - { success: false, error: "Failed to process Google Form submission" }, - { status: 500 }, - ); - } -}; diff --git a/src/app/api/webhooks/stripe/route.ts b/src/app/api/webhooks/stripe/route.ts deleted file mode 100644 index e03b5d7..0000000 --- a/src/app/api/webhooks/stripe/route.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { sendWorkflowExecution } from "@/inngest/utils"; -import { type NextRequest, NextResponse } from "next/server"; - -export async function POST(request: NextRequest) { - try { - const url = new URL(request.url); - const workflowId = url.searchParams.get("workflowId"); - - if (!workflowId) { - return NextResponse.json( - { success: false, error: "Missing required query parameter: workflowId" }, - { status: 400 }, - ); - }; - - const body = await request.json(); - - const stripeData = { - // Event metadata - eventId: body.id, - eventType: body.type, - timestamp: body.created, - livemode: body.livemode, - raw: body.data?.object, - }; - - // Trigger an Inngest job - await sendWorkflowExecution({ - workflowId, - initialData: { - stripe: stripeData, - }, - }); - - return NextResponse.json( - { success: true }, - { status: 200 }, - ); - } catch (error) { - console.error("Stripe webhook error:" , error); - return NextResponse.json( - { success: false, error: "Failed to process Stripe event" }, - { status: 500 }, - ); - } -}; diff --git a/src/app/global-error.tsx b/src/app/global-error.tsx index 9bda5fe..45dc391 100644 --- a/src/app/global-error.tsx +++ b/src/app/global-error.tsx @@ -1,21 +1,13 @@ "use client"; -import * as Sentry from "@sentry/nextjs"; import NextError from "next/error"; -import { useEffect } from "react"; export default function GlobalError({ error }: { error: Error & { digest?: string } }) { - useEffect(() => { - Sentry.captureException(error); - }, [error]); + console.error(error); return ( - {/* `NextError` is the default Next.js error page component. Its type - definition requires a `statusCode` prop. However, since the App Router - does not expose status codes for errors, we simply pass 0 to render a - generic error message. */} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ff589d6..20e46c9 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,9 +1,9 @@ import type { Metadata } from "next"; import { Geist, Geist_Mono } from "next/font/google"; -import { Provider } from 'jotai' -import { TRPCReactProvider } from "@/trpc/client"; +import { Provider } from "jotai"; import { Toaster } from "@/components/ui/sonner"; -import { NuqsAdapter } from 'nuqs/adapters/next/app' +import { NuqsAdapter } from "nuqs/adapters/next/app"; +import { AuthProvider } from "@/features/auth/components/auth-provider"; import "./globals.css"; @@ -18,8 +18,8 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Nodebase", + description: "Visual workflow automation", }; export default function RootLayout({ @@ -32,14 +32,12 @@ export default function RootLayout({ - - - - {children} - - - - + + + {children} + + + ); diff --git a/src/app/sentry-example-page/page.tsx b/src/app/sentry-example-page/page.tsx deleted file mode 100644 index 3a8cda4..0000000 --- a/src/app/sentry-example-page/page.tsx +++ /dev/null @@ -1,209 +0,0 @@ -"use client"; - -import Head from "next/head"; -import * as Sentry from "@sentry/nextjs"; -import { useState, useEffect } from "react"; - -class SentryExampleFrontendError extends Error { - constructor(message: string | undefined) { - super(message); - this.name = "SentryExampleFrontendError"; - } -} - -export default function Page() { - const [hasSentError, setHasSentError] = useState(false); - const [isConnected, setIsConnected] = useState(true); - - useEffect(() => { - async function checkConnectivity() { - const result = await Sentry.diagnoseSdkConnectivity(); - setIsConnected(result !== 'sentry-unreachable'); - } - checkConnectivity(); - }, []); - - return ( -
- - sentry-example-page - - - -
-
- - - -

- sentry-example-page -

- -

- Click the button below, and view the sample error on the Sentry Issues Page. - For more details about setting up Sentry, read our docs. -

- - - - {hasSentError ? ( -

- Error sent to Sentry. -

- ) : !isConnected ? ( -
-

It looks like network requests to Sentry are being blocked, which will prevent errors from being captured. Try disabling your ad-blocker to complete the test.

-
- ) : ( -
- )} - -
- -
- - -
- ); -} diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx index 2305050..c605983 100644 --- a/src/components/app-sidebar.tsx +++ b/src/components/app-sidebar.tsx @@ -6,6 +6,7 @@ import { HistoryIcon, KeyIcon, LogOutIcon, + SettingsIcon, StarIcon, } from "lucide-react"; import Image from "next/image"; @@ -22,8 +23,11 @@ import { SidebarMenuButton, SidebarMenuItem, } from "@/components/ui/sidebar"; -import { authClient } from "@/lib/auth-client"; import { useHasActiveSubscription } from "@/features/subscriptions/hooks/use-subscription"; +import { logoutUser } from "@/api/auth"; +import { useSetAtom } from "jotai"; +import { userAtom } from "@/features/auth/store/auth-atoms"; +import { toast } from "sonner"; const menuItems = [ { @@ -44,13 +48,19 @@ const menuItems = [ icon: HistoryIcon, url: "/executions", }, + { + title: "Settings", + icon: SettingsIcon, + url: "/settings", + }, ], - } + }, ]; export const AppSidebar = () => { const router = useRouter(); const pathname = usePathname(); + const setUser = useSetAtom(userAtom); const { hasActiveSubscription, isLoading } = useHasActiveSubscription(); return ( @@ -59,8 +69,13 @@ export const AppSidebar = () => { - Nodebase - Nodebase + Nodebase + Nodebase @@ -99,9 +114,12 @@ export const AppSidebar = () => { {!hasActiveSubscription && !isLoading && ( authClient.checkout({ slug: "pro" })} + onClick={() => { + // TODO: Redirect to billing/checkout from custom backend + toast.info("Billing requires custom backend integration"); + }} > Upgrade to Pro @@ -112,7 +130,12 @@ export const AppSidebar = () => { authClient.customer.portal()} + onClick={() => { + // TODO: Redirect to billing portal from custom backend + toast.info( + "Billing portal requires custom backend integration", + ); + }} > Billing Portal @@ -122,13 +145,15 @@ export const AppSidebar = () => { authClient.signOut({ - fetchOptions: { - onSuccess: () => { - router.push("/login"); - }, - }, - })} + onClick={async () => { + try { + await logoutUser(); + setUser(null); + router.replace("/login"); + } catch { + toast.error("Failed to sign out"); + } + }} > Sign out diff --git a/src/components/node-selector.tsx b/src/components/node-selector.tsx index ae84fef..e8991b4 100644 --- a/src/components/node-selector.tsx +++ b/src/components/node-selector.tsx @@ -2,10 +2,7 @@ import { createId } from "@paralleldrive/cuid2"; import { useReactFlow } from "@xyflow/react"; -import { - GlobeIcon, - MousePointerIcon, -} from "lucide-react"; +import { GlobeIcon, MousePointerIcon } from "lucide-react"; import { useCallback } from "react"; import { toast } from "sonner"; import { @@ -16,7 +13,7 @@ import { SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; -import { NodeType } from "@/generated/prisma"; +import { NodeType } from "@/config/constants"; import { Separator } from "./ui/separator"; export type NodeTypeOption = { @@ -30,7 +27,8 @@ const triggerNodes: NodeTypeOption[] = [ { type: NodeType.MANUAL_TRIGGER, label: "Trigger manually", - description: "Runs the flow on clicking a button. Good for getting started quickly", + description: + "Runs the flow on clicking a button. Good for getting started quickly", icon: MousePointerIcon, }, { @@ -86,77 +84,72 @@ const executionNodes: NodeTypeOption[] = [ }, ]; - interface NodeSelectorProps { open: boolean; onOpenChange: (open: boolean) => void; children: React.ReactNode; -}; +} export function NodeSelector({ open, onOpenChange, - children + children, }: NodeSelectorProps) { const { setNodes, getNodes, screenToFlowPosition } = useReactFlow(); - const handleNodeSelect = useCallback((selection: NodeTypeOption) => { - // Check if trying to add a manual trigger when one already exists - if (selection.type === NodeType.MANUAL_TRIGGER) { - const nodes = getNodes(); - const hasManualTrigger = nodes.some( - (node) => node.type === NodeType.MANUAL_TRIGGER, - ); - - if (hasManualTrigger) { - toast.error("Only one manual trigger is allowed per workflow"); - return; + const handleNodeSelect = useCallback( + (selection: NodeTypeOption) => { + // Check if trying to add a manual trigger when one already exists + if (selection.type === NodeType.MANUAL_TRIGGER) { + const nodes = getNodes(); + const hasManualTrigger = nodes.some( + (node) => node.type === NodeType.MANUAL_TRIGGER, + ); + + if (hasManualTrigger) { + toast.error("Only one manual trigger is allowed per workflow"); + return; + } } - } - setNodes((nodes) => { - const hasInitialTrigger = nodes.some( - (node) => node.type === NodeType.INITIAL, - ); + setNodes((nodes) => { + const hasInitialTrigger = nodes.some( + (node) => node.type === NodeType.INITIAL, + ); - const centerX = window.innerWidth / 2; - const centerY = window.innerHeight / 2; + const centerX = window.innerWidth / 2; + const centerY = window.innerHeight / 2; - const flowPosition = screenToFlowPosition({ - x: centerX + (Math.random() - 0.5) * 200, - y: centerY + (Math.random() - 0.5) * 200, - }); + const flowPosition = screenToFlowPosition({ + x: centerX + (Math.random() - 0.5) * 200, + y: centerY + (Math.random() - 0.5) * 200, + }); - const newNode = { - id: createId(), - data: {}, - position: flowPosition, - type: selection.type, - }; + const newNode = { + id: createId(), + data: {}, + position: flowPosition, + type: selection.type, + }; - if (hasInitialTrigger) { - return [newNode]; - } + if (hasInitialTrigger) { + return [newNode]; + } - return [...nodes, newNode]; - }); + return [...nodes, newNode]; + }); - onOpenChange(false); - }, [ - setNodes, - getNodes, - onOpenChange, - screenToFlowPosition, - ]); + onOpenChange(false); + }, + [setNodes, getNodes, onOpenChange, screenToFlowPosition], + ); return ( {children} - - What triggers this workflow? - + What triggers this workflow? A trigger is a step that starts your workflow. @@ -191,7 +184,7 @@ export function NodeSelector({ - ) + ); })} @@ -225,10 +218,10 @@ export function NodeSelector({ - ) + ); })} ); -}; +} diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx index d9ccec9..3cdfa3c 100644 --- a/src/components/ui/dialog.tsx +++ b/src/components/ui/dialog.tsx @@ -1,33 +1,33 @@ -"use client" +"use client"; -import * as React from "react" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { XIcon } from "lucide-react" +import * as React from "react"; +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { XIcon } from "lucide-react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; function Dialog({ ...props }: React.ComponentProps) { - return + return ; } function DialogTrigger({ ...props }: React.ComponentProps) { - return + return ; } function DialogPortal({ ...props }: React.ComponentProps) { - return + return ; } function DialogClose({ ...props }: React.ComponentProps) { - return + return ; } function DialogOverlay({ @@ -39,11 +39,11 @@ function DialogOverlay({ data-slot="dialog-overlay" className={cn( "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", - className + className, )} {...props} /> - ) + ); } function DialogContent({ @@ -52,7 +52,7 @@ function DialogContent({ showCloseButton = true, ...props }: React.ComponentProps & { - showCloseButton?: boolean + showCloseButton?: boolean; }) { return ( @@ -60,8 +60,8 @@ function DialogContent({ @@ -77,7 +77,7 @@ function DialogContent({ )} - ) + ); } function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { @@ -87,7 +87,7 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { className={cn("flex flex-col gap-2 text-center sm:text-left", className)} {...props} /> - ) + ); } function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { @@ -96,11 +96,11 @@ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { data-slot="dialog-footer" className={cn( "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", - className + className, )} {...props} /> - ) + ); } function DialogTitle({ @@ -113,7 +113,7 @@ function DialogTitle({ className={cn("text-lg leading-none font-semibold", className)} {...props} /> - ) + ); } function DialogDescription({ @@ -126,7 +126,7 @@ function DialogDescription({ className={cn("text-muted-foreground text-sm", className)} {...props} /> - ) + ); } export { @@ -140,4 +140,4 @@ export { DialogPortal, DialogTitle, DialogTrigger, -} +}; diff --git a/src/components/upgrade-modal.tsx b/src/components/upgrade-modal.tsx index ade7cdc..d61ea98 100644 --- a/src/components/upgrade-modal.tsx +++ b/src/components/upgrade-modal.tsx @@ -10,15 +10,15 @@ import { AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; -import { authClient } from "@/lib/auth-client"; +import { toast } from "sonner"; interface UpgradeModalProps { open: boolean; onOpenChange: (open: boolean) => void; }; -export const UpgradeModal = ({ - open, +export const UpgradeModal = ({ + open, onOpenChange }: UpgradeModalProps) => { return ( @@ -34,7 +34,10 @@ export const UpgradeModal = ({ Cancel authClient.checkout({ slug: "pro" })} + onClick={() => { + // TODO: Redirect to billing/checkout page from custom backend + toast.info("Billing requires custom backend integration"); + }} > Upgrade Now diff --git a/src/config/constants.ts b/src/config/constants.ts index a324e3c..197c8f9 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -4,3 +4,22 @@ export const PAGINATION = { MAX_PAGE_SIZE: 100, MIN_PAGE_SIZE: 1, }; + +export enum NodeType { + INITIAL = "INITIAL", + MANUAL_TRIGGER = "MANUAL_TRIGGER", + HTTP_REQUEST = "HTTP_REQUEST", + GOOGLE_FORM_TRIGGER = "GOOGLE_FORM_TRIGGER", + STRIPE_TRIGGER = "STRIPE_TRIGGER", + ANTHROPIC = "ANTHROPIC", + GEMINI = "GEMINI", + OPENAI = "OPENAI", + DISCORD = "DISCORD", + SLACK = "SLACK", +} + +export enum ExecutionStatus { + RUNNING = "RUNNING", + SUCCESS = "SUCCESS", + FAILED = "FAILED", +} diff --git a/src/config/node-components.ts b/src/config/node-components.ts index 07e634c..4cf4f52 100644 --- a/src/config/node-components.ts +++ b/src/config/node-components.ts @@ -1,5 +1,4 @@ import { InitialNode } from "@/components/initial-node"; -import { NodeType } from "@/generated/prisma"; import type { NodeTypes } from "@xyflow/react"; import { HttpRequestNode } from "@/features/executions/components/http-request/node"; @@ -11,6 +10,10 @@ import { OpenAiNode } from "@/features/executions/components/openai/node"; import { AnthropicNode } from "@/features/executions/components/anthropic/node"; import { DiscordNode } from "@/features/executions/components/discord/node"; import { SlackNode } from "@/features/executions/components/slack/node"; +import { NodeType, ExecutionStatus } from "@/config/constants"; + +// Re-export so existing imports still work +export { NodeType, ExecutionStatus }; export const nodeComponents = { [NodeType.INITIAL]: InitialNode, diff --git a/src/features/auth/components/auth-provider.tsx b/src/features/auth/components/auth-provider.tsx new file mode 100644 index 0000000..9aebbbf --- /dev/null +++ b/src/features/auth/components/auth-provider.tsx @@ -0,0 +1,78 @@ +"use client"; + +import { useEffect } from "react"; +import { useAtom } from "jotai"; +import { usePathname, useRouter } from "next/navigation"; +import { getMe } from "@/api/auth"; +import { userAtom, authLoadingAtom } from "@/features/auth/store/auth-atoms"; + +/** + * Public paths that do NOT require authentication. + * Everything else redirects to /login when there is no valid session. + */ +const PUBLIC_PATHS = ["/login", "/signup", "/forgot-password"]; + +function isPublicPath(pathname: string): boolean { + return PUBLIC_PATHS.some( + (p) => pathname === p || pathname.startsWith(`${p}/`), + ); +} + +export function AuthProvider({ children }: { children: React.ReactNode }) { + const [user, setUser] = useAtom(userAtom); + const [loading, setLoading] = useAtom(authLoadingAtom); + const router = useRouter(); + const pathname = usePathname(); + + // On mount, check the session once via the cookie-based /api/auth/me call + useEffect(() => { + let cancelled = false; + + async function checkSession() { + try { + const me = await getMe(); + if (!cancelled) { + setUser(me); + } + } catch { + if (!cancelled) setUser(null); + } finally { + if (!cancelled) setLoading(false); + } + } + + checkSession(); + + return () => { + cancelled = true; + }; + // Only run once on mount + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + // After the session check completes, handle redirects + useEffect(() => { + if (loading) return; + + const onPublicPage = isPublicPath(pathname); + + if (!user && !onPublicPage) { + // Not authenticated → send to login + router.replace("/login"); + } else if (user && onPublicPage) { + // Already authenticated → send away from auth pages + router.replace("/workflows"); + } + }, [loading, user, pathname, router]); + + // While checking session, render nothing (or a spinner) + if (loading) { + return ( +
+
+
+ ); + } + + return <>{children}; +} diff --git a/src/features/auth/components/login-form.tsx b/src/features/auth/components/login-form.tsx index 8a916a3..8ca7ac4 100644 --- a/src/features/auth/components/login-form.tsx +++ b/src/features/auth/components/login-form.tsx @@ -24,7 +24,11 @@ import { FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; -import { authClient } from "@/lib/auth-client"; +import { loginUser } from "@/api/auth"; +import { useSetAtom } from "jotai"; +import { userAtom } from "@/features/auth/store/auth-atoms"; +import { useState } from "react"; +import { EyeIcon, EyeOffIcon } from "lucide-react"; const loginSchema = z.object({ email: z.email("Please enter a valid email address"), @@ -35,6 +39,7 @@ type LoginFormValues = z.infer; export function LoginForm() { const router = useRouter(); + const setUser = useSetAtom(userAtom); const form = useForm({ resolver: zodResolver(loginSchema), @@ -45,58 +50,35 @@ export function LoginForm() { }); const signInGithub = async () => { - await authClient.signIn.social({ - provider: "github", - }, { - onSuccess: () => { - router.push("/"); - }, - onError: () => { - toast.error("Something went wrong"); - }, - }); + // TODO: Replace with custom backend OAuth redirect + toast.info("GitHub login requires custom backend integration"); }; const signInGoogle = async () => { - await authClient.signIn.social({ - provider: "google", - }, { - onSuccess: () => { - router.push("/"); - }, - onError: () => { - toast.error("Something went wrong"); - }, - }); + // TODO: Replace with custom backend OAuth redirect + toast.info("Google login requires custom backend integration"); }; const onSubmit = async (values: LoginFormValues) => { - await authClient.signIn.email({ - email: values.email, - password: values.password, - callbackURL: "/", - }, { - onSuccess: () => { - router.push("/"); - }, - onError: (ctx) => { - toast.error(ctx.error.message); - }, - }); + try { + const res = await loginUser(values); + setUser(res.data.user); + toast.success(res.message || "Login successful"); + router.replace("/workflows"); + } catch (err: unknown) { + toast.error("Login failed. Please try again."); + } }; + const [showPassword, setShowPassword] = useState(false); const isPending = form.formState.isSubmitting; return (
- - Welcome back - - - Login to continue - + Welcome back + Login to continue
@@ -110,7 +92,12 @@ export function LoginForm() { type="button" disabled={isPending} > - GitHub + GitHub Continue with GitHub
@@ -149,11 +141,25 @@ export function LoginForm() { Password - +
+ + +
@@ -176,4 +182,4 @@ export function LoginForm() {
); -}; +} diff --git a/src/features/auth/components/register-form.tsx b/src/features/auth/components/register-form.tsx index 801c114..863244e 100644 --- a/src/features/auth/components/register-form.tsx +++ b/src/features/auth/components/register-form.tsx @@ -24,26 +24,34 @@ import { FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; -import { authClient } from "@/lib/auth-client"; +import { registerUser } from "@/api/auth"; +import { useSetAtom } from "jotai"; +import { userAtom } from "@/features/auth/store/auth-atoms"; +import { useState } from "react"; +import { EyeIcon, EyeOffIcon } from "lucide-react"; -const registerSchema = z.object({ - email: z.email("Please enter a valid email address"), - password: z.string().min(1, "Password is required"), - confirmPassword: z.string(), -}) -.refine((data) => data.password === data.confirmPassword, { - message: "Passwords don't match", - path: ["confirmPassword"] -}); +const registerSchema = z + .object({ + name: z.string().min(1, "Name is required"), + email: z.email("Please enter a valid email address"), + password: z.string().min(8, "Password must be at least 8 characters"), + confirmPassword: z.string(), + }) + .refine((data) => data.password === data.confirmPassword, { + message: "Passwords don't match", + path: ["confirmPassword"], + }); type RegisterFormValues = z.infer; export function RegisterForm() { const router = useRouter(); + const setUser = useSetAtom(userAtom); const form = useForm({ resolver: zodResolver(registerSchema), defaultValues: { + name: "", email: "", password: "", confirmPassword: "", @@ -51,62 +59,44 @@ export function RegisterForm() { }); const signInGithub = async () => { - await authClient.signIn.social({ - provider: "github", - }, { - onSuccess: () => { - router.push("/"); - }, - onError: () => { - toast.error("Something went wrong"); - }, - }); + // TODO: Replace with custom backend OAuth redirect + toast.info("GitHub login requires custom backend integration"); }; const signInGoogle = async () => { - await authClient.signIn.social({ - provider: "google", - }, { - onSuccess: () => { - router.push("/"); - }, - onError: () => { - toast.error("Something went wrong"); - }, - }); + // TODO: Replace with custom backend OAuth redirect + toast.info("Google login requires custom backend integration"); }; const onSubmit = async (values: RegisterFormValues) => { - await authClient.signUp.email( - { - name: values.email, + try { + const res = await registerUser({ + name: values.name, email: values.email, password: values.password, - callbackURL: "/", - }, - { - onSuccess: () => { - router.push("/"); - }, - onError: (ctx) => { - toast.error(ctx.error.message); - } - } - ) + }); + setUser(res.data.user); + toast.success(res.message || "Registration successful"); + router.replace("/workflows"); + } catch (err: unknown) { + const message = + err instanceof Error + ? err.message + : "Registration failed. Please try again."; + toast.error(message); + } }; + const [showPassword, setShowPassword] = useState(false); + const [showConfirm, setShowConfirm] = useState(false); const isPending = form.formState.isSubmitting; return (
- - Get Started - - - Create your account to get started - + Get Started + Create your account to get started @@ -120,7 +110,12 @@ export function RegisterForm() { type="button" disabled={isPending} > - GitHub + GitHub Continue with GitHub
+ ( + + Name + + + + + + )} + /> Password - +
+ + +
@@ -176,11 +207,25 @@ export function RegisterForm() { Confirm Password - +
+ + +
@@ -203,4 +248,4 @@ export function RegisterForm() {
); -}; +} diff --git a/src/features/auth/store/auth-atoms.ts b/src/features/auth/store/auth-atoms.ts new file mode 100644 index 0000000..b5c6c27 --- /dev/null +++ b/src/features/auth/store/auth-atoms.ts @@ -0,0 +1,8 @@ +import { atom } from "jotai"; +import type { User } from "@/api/auth"; + +/** Holds the currently authenticated user, or null when logged out / unknown. */ +export const userAtom = atom(null); + +/** True while the initial session check (getMe) is in-flight. */ +export const authLoadingAtom = atom(true); diff --git a/src/features/credentials/components/credential.tsx b/src/features/credentials/components/credential.tsx index fde7000..bd82ec2 100644 --- a/src/features/credentials/components/credential.tsx +++ b/src/features/credentials/components/credential.tsx @@ -1,10 +1,10 @@ "use client"; -import { CredentialType } from "@/generated/prisma"; +import { CredentialType } from "../hooks/use-credentials"; import Image from "next/image"; import { useRouter } from "next/navigation"; -import { - useCreateCredential, +import { + useCreateCredential, useUpdateCredential, useSuspenseCredential, } from "../hooks/use-credentials"; @@ -36,11 +36,18 @@ import { CardTitle, } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; +import { Skeleton } from "@/components/ui/skeleton"; import Link from "next/link"; +import { useState } from "react"; +import { EyeIcon, EyeOffIcon } from "lucide-react"; const formSchema = z.object({ name: z.string().min(1, "Name is required"), - type: z.enum(CredentialType), + type: z.enum([ + CredentialType.OPENAI, + CredentialType.ANTHROPIC, + CredentialType.GEMINI, + ]), value: z.string().min(1, "API key is required"), }); @@ -71,17 +78,16 @@ interface CredentialFormProps { type: CredentialType; value: string; }; -}; +} -export const CredentialForm = ({ - initialData, -}: CredentialFormProps) => { +export const CredentialForm = ({ initialData }: CredentialFormProps) => { const router = useRouter(); const createCredential = useCreateCredential(); const updateCredential = useUpdateCredential(); const { handleError, modal } = useUpgradeModal(); const isEdit = !!initialData?.id; + const [showKey, setShowKey] = useState(false); const form = useForm({ resolver: zodResolver(formSchema), @@ -97,18 +103,13 @@ export const CredentialForm = ({ await updateCredential.mutateAsync({ id: initialData.id, ...values, - }) + }); } else { - await createCredential.mutateAsync(values, { - onSuccess: (data) => { - router.push(`/credentials/${data.id}`); - }, - onError: (error) => { - handleError(error); - } - }) + await createCredential.mutateAsync(values); + router.push(`/credentials`); + // TODO: Redirect to new credential page when backend returns the created ID } - } + }; return ( <> @@ -126,109 +127,139 @@ export const CredentialForm = ({ - - ( - - Name + + ( + + Name + + + + + + )} + /> + ( + + Type + + + + - - - )} - /> - ( - - Type - - - - )} - /> + + {credentialTypeOptions.map((option) => ( + +
+ {option.label} + {option.label} +
+
+ ))} +
+ + +
+ )} + /> - ( - - API Key - - ( + + API Key + +
+ - - - - )} - /> + +
+
+ +
+ )} + /> -
- - -
- +
+ + +
+
- ) + ); }; -export const CredentialView = ({ - credentialId, -}: { credentialId: string }) => { - const { data: credential } = useSuspenseCredential(credentialId); +/** Skeleton shown while loading credential data for the edit form. */ +const CredentialFormSkeleton = () => ( + + + + + + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+); + +export const CredentialView = ({ credentialId }: { credentialId: string }) => { + const { data: credential, isLoading } = useSuspenseCredential(credentialId); - return + if (isLoading) return ; + if (!credential) return ; + return ; }; diff --git a/src/features/credentials/components/credentials.tsx b/src/features/credentials/components/credentials.tsx index 32b30a6..d49ac05 100644 --- a/src/features/credentials/components/credentials.tsx +++ b/src/features/credentials/components/credentials.tsx @@ -1,24 +1,29 @@ "use client"; import { formatDistanceToNow } from "date-fns"; -import { +import { EmptyView, - EntityContainer, - EntityHeader, - EntityItem, - EntityList, - EntityPagination, + EntityContainer, + EntityHeader, + EntityItem, + EntityList, + EntityPagination, EntitySearch, ErrorView, - LoadingView } from "@/components/entity-components"; -import { useRemoveCredential, useSuspenseCredentials } from "../hooks/use-credentials" +import { + useRemoveCredential, + useSuspenseCredentials, + type Credential, + CredentialType, +} from "../hooks/use-credentials"; import { useRouter } from "next/navigation"; import { useCredentialsParams } from "../hooks/use-credentials-params"; import { useEntitySearch } from "@/hooks/use-entity-search"; -import type { Credential } from "@/generated/prisma"; -import { CredentialType } from "@/generated/prisma"; import Image from "next/image"; +import { Skeleton } from "@/components/ui/skeleton"; +import { Card, CardContent } from "@/components/ui/card"; +import { PAGINATION } from "@/config/constants"; export const CredentialsSearch = () => { const [params, setParams] = useCredentialsParams(); @@ -36,12 +41,38 @@ export const CredentialsSearch = () => { ); }; +/** Skeleton placeholder for a single credential card. */ +const CredentialItemSkeleton = () => ( + + +
+ +
+ + +
+
+
+
+); + +/** Skeleton list shown while credentials are loading. */ +export const CredentialsListSkeleton = () => ( +
+ {Array.from({ length: 3 }).map((_, i) => ( + + ))} +
+); + export const CredentialsList = () => { - const credentials = useSuspenseCredentials(); + const { data, isLoading } = useSuspenseCredentials(); + + if (isLoading) return ; return ( credential.id} renderItem={(credential) => } emptyView={} @@ -62,21 +93,24 @@ export const CredentialsHeader = ({ disabled }: { disabled?: boolean }) => { }; export const CredentialsPagination = () => { - const credentials = useSuspenseCredentials(); + const { data, isLoading } = useSuspenseCredentials(); const [params, setParams] = useCredentialsParams(); + const pageSize = params.pageSize || PAGINATION.DEFAULT_PAGE_SIZE; + const totalPages = Math.max(1, Math.ceil(data.total / pageSize)); + return ( setParams({ ...params, page })} /> ); }; export const CredentialsContainer = ({ - children + children, }: { children: React.ReactNode; }) => { @@ -92,7 +126,7 @@ export const CredentialsContainer = ({ }; export const CredentialsLoading = () => { - return ; + return ; }; export const CredentialsError = () => { @@ -120,11 +154,7 @@ const credentialLogos: Record = { [CredentialType.GEMINI]: "/logos/gemini.svg", }; -export const CredentialItem = ({ - data, -}: { - data: Credential -}) => { +export const CredentialItem = ({ data }: { data: Credential }) => { const removeCredential = useRemoveCredential(); const handleRemove = () => { @@ -152,5 +182,5 @@ export const CredentialItem = ({ onRemove={handleRemove} isRemoving={removeCredential.isPending} /> - ) + ); }; diff --git a/src/features/credentials/hooks/use-credentials.ts b/src/features/credentials/hooks/use-credentials.ts index cfc0efc..e39adf4 100644 --- a/src/features/credentials/hooks/use-credentials.ts +++ b/src/features/credentials/hooks/use-credentials.ts @@ -1,98 +1,244 @@ -import { useTRPC } from "@/trpc/client" -import { useMutation, useQuery, useQueryClient, useSuspenseQuery } from "@tanstack/react-query"; +"use client"; + +import { useCallback, useEffect, useState } from "react"; +import { useAtom } from "jotai"; +import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { useCredentialsParams } from "./use-credentials-params"; -import { CredentialType } from "@/generated/prisma"; +import { + credentialsAtom, + credentialsTotalAtom, + credentialsLoadingAtom, +} from "../store/credential-atoms"; +import * as credentialsApi from "@/api/credentials"; +import type { ApiCredential } from "@/api/credentials"; + +// ─── Types ────────────────────────────────────────────────── + +export enum CredentialType { + OPENAI = "OPENAI", + ANTHROPIC = "ANTHROPIC", + GEMINI = "GEMINI", +} + +export type Credential = { + id: string; + name: string; + type: CredentialType; + value: string; + createdAt: Date; + updatedAt: Date; +}; + +/** Map a backend credential row to the frontend shape. */ +const mapCredential = (c: ApiCredential): Credential => ({ + id: c.id, + name: c.name, + type: c.type as CredentialType, + value: "", // value is never returned from the API for security + createdAt: new Date(c.created_at), + updatedAt: new Date(c.updated_at), +}); + +// ─── List Hook ────────────────────────────────────────────── -/** - * Hook to fetch all credentials using suspense - */ +/** Fetch and cache the paginated credentials list. */ export const useSuspenseCredentials = () => { - const trpc = useTRPC(); const [params] = useCredentialsParams(); - - return useSuspenseQuery(trpc.credentials.getMany.queryOptions(params)); + const [items, setItems] = useAtom(credentialsAtom); + const [total, setTotal] = useAtom(credentialsTotalAtom); + const [isLoading, setIsLoading] = useAtom(credentialsLoadingAtom); + + useEffect(() => { + let cancelled = false; + setIsLoading(true); + + credentialsApi + .getCredentials({ page: params.page, pageSize: params.pageSize }) + .then((res) => { + if (cancelled) return; + setItems(res.credentials.map(mapCredential)); + setTotal(res.total); + }) + .catch(() => { + if (!cancelled) toast.error("Failed to load credentials"); + }) + .finally(() => { + if (!cancelled) setIsLoading(false); + }); + + return () => { cancelled = true; }; + }, [params.page, params.pageSize, setItems, setTotal, setIsLoading]); + + return { data: { items, total }, isLoading }; }; -/** - * Hook to create a new credentials - */ -export const useCreateCredential = () => { - const queryClient = useQueryClient(); - const trpc = useTRPC(); - - return useMutation( - trpc.credentials.create.mutationOptions({ - onSuccess: (data) => { - toast.success(`Credential "${data.name}" created`); - queryClient.invalidateQueries( - trpc.credentials.getMany.queryOptions({}), - ); - }, - onError: (error) => { - toast.error(`Failed to create credential: ${error.message}`); - }, - }), - ); +// ─── Single Credential Hook ──────────────────────────────── + +/** Fetch a single credential by ID. */ +export const useSuspenseCredential = (id: string) => { + const [data, setData] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + let cancelled = false; + setIsLoading(true); + + credentialsApi + .getCredential(id) + .then((raw) => { + if (cancelled) return; + setData(mapCredential(raw)); + }) + .catch(() => { + if (!cancelled) toast.error("Failed to load credential"); + }) + .finally(() => { + if (!cancelled) setIsLoading(false); + }); + + return () => { cancelled = true; }; + }, [id]); + + return { data, isLoading }; }; -/** - * Hook to remove a credential - */ -export const useRemoveCredential = () => { - const trpc = useTRPC(); - const queryClient = useQueryClient(); - - return useMutation( - trpc.credentials.remove.mutationOptions({ - onSuccess: (data) => { - toast.success(`Credential "${data.name}" removed`); - queryClient.invalidateQueries(trpc.credentials.getMany.queryOptions({})); - queryClient.invalidateQueries( - trpc.credentials.getOne.queryFilter({ id: data.id }), - ); +// ─── Credentials by Type Hook ────────────────────────────── + +/** Fetch credentials filtered by provider type. */ +export const useCredentialsByType = (type: CredentialType) => { + const [data, setData] = useState([]); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + let cancelled = false; + setIsLoading(true); + + credentialsApi + .getCredentialsByType(type) + .then((raw) => { + if (cancelled) return; + setData(raw.map(mapCredential)); + }) + .catch(() => { + if (!cancelled) toast.error("Failed to load credentials"); + }) + .finally(() => { + if (!cancelled) setIsLoading(false); + }); + + return () => { cancelled = true; }; + }, [type]); + + return { data, isLoading }; +}; + +// ─── Mutations ────────────────────────────────────────────── + +/** Create a credential and navigate back to the list. */ +export const useCreateCredential = () => { + const [isPending, setIsPending] = useState(false); + const [, setItems] = useAtom(credentialsAtom); + const router = useRouter(); + + const mutateAsync = useCallback( + async (input: { name: string; type: string; value: string }) => { + setIsPending(true); + try { + const raw = await credentialsApi.createCredential(input); + const mapped = mapCredential(raw); + setItems((prev) => [mapped, ...prev]); + toast.success("Credential created"); + router.push("/credentials"); + return mapped; + } catch { + toast.error("Failed to create credential"); + throw new Error("Failed to create credential"); + } finally { + setIsPending(false); } - }) - ) -} + }, + [setItems, router], + ); -/** - * Hook to fetch a single credential using suspense - */ -export const useSuspenseCredential = (id: string) => { - const trpc = useTRPC(); - return useSuspenseQuery(trpc.credentials.getOne.queryOptions({ id })); + const mutate = useCallback( + (input: { name: string; type: string; value: string }) => { mutateAsync(input).catch(() => { }); }, + [mutateAsync], + ); + + return { mutate, mutateAsync, isPending }; }; -/** - * Hook to update a credential - */ +/** Update a credential's name or value. */ export const useUpdateCredential = () => { - const queryClient = useQueryClient(); - const trpc = useTRPC(); - - return useMutation( - trpc.credentials.update.mutationOptions({ - onSuccess: (data) => { - toast.success(`Credential "${data.name}" saved`); - queryClient.invalidateQueries( - trpc.credentials.getMany.queryOptions({}), - ); - queryClient.invalidateQueries( - trpc.credentials.getOne.queryOptions({ id: data.id }), + const [isPending, setIsPending] = useState(false); + const [, setItems] = useAtom(credentialsAtom); + + const mutateAsync = useCallback( + async (input: { id: string; name?: string; value?: string }) => { + setIsPending(true); + try { + const { id, ...payload } = input; + const raw = await credentialsApi.updateCredential(id, payload); + const mapped = mapCredential(raw); + + setItems((prev) => + prev.map((c) => (c.id === id ? { ...c, name: mapped.name, updatedAt: mapped.updatedAt } : c)), ); - }, - onError: (error) => { - toast.error(`Failed to save credential: ${error.message}`); - }, - }), + + toast.success("Credential updated"); + return mapped; + } catch { + toast.error("Failed to update credential"); + throw new Error("Failed to update credential"); + } finally { + setIsPending(false); + } + }, + [setItems], + ); + + const mutate = useCallback( + (input: { id: string; name?: string; value?: string }) => { mutateAsync(input).catch(() => { }); }, + [mutateAsync], ); + + return { mutate, mutateAsync, isPending }; }; -/** - * Hook to fetch credentials by type - */ -export const useCredentialsByType = (type: CredentialType) => { - const trpc = useTRPC(); - return useQuery(trpc.credentials.getByType.queryOptions({ type })); +/** Optimistically remove a credential from the list. */ +export const useRemoveCredential = () => { + const [isPending, setIsPending] = useState(false); + const [, setItems] = useAtom(credentialsAtom); + + const mutateAsync = useCallback( + async (input: { id: string }) => { + setIsPending(true); + let snapshot: Credential[] = []; + + // Optimistic remove + setItems((prev) => { + snapshot = prev; + return prev.filter((c) => c.id !== input.id); + }); + + try { + await credentialsApi.deleteCredential(input.id); + toast.success("Credential deleted"); + } catch { + setItems(snapshot); // rollback + toast.error("Failed to delete credential"); + } finally { + setIsPending(false); + } + }, + [setItems], + ); + + const mutate = useCallback( + (input: { id: string }) => { mutateAsync(input).catch(() => { }); }, + [mutateAsync], + ); + + return { mutate, mutateAsync, isPending }; }; diff --git a/src/features/credentials/server/params-loader.ts b/src/features/credentials/server/params-loader.ts deleted file mode 100644 index 29b7e95..0000000 --- a/src/features/credentials/server/params-loader.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createLoader } from "nuqs/server"; -import { credentialsParams } from "../params"; - -export const credentialsParamsLoader = createLoader(credentialsParams); diff --git a/src/features/credentials/server/prefetch.ts b/src/features/credentials/server/prefetch.ts deleted file mode 100644 index 2febebe..0000000 --- a/src/features/credentials/server/prefetch.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { inferInput } from "@trpc/tanstack-react-query"; -import { prefetch, trpc } from "@/trpc/server"; - -type Input = inferInput; - -/** - * Prefetch all credentials - */ -export const prefetchCredentials = (params: Input) => { - return prefetch(trpc.credentials.getMany.queryOptions(params)); -}; - -/** - * Prefetch a single credential - */ -export const prefetchCredential = (id: string) => { - return prefetch(trpc.credentials.getOne.queryOptions({ id })); -}; diff --git a/src/features/credentials/server/routers.ts b/src/features/credentials/server/routers.ts deleted file mode 100644 index f1b5eeb..0000000 --- a/src/features/credentials/server/routers.ts +++ /dev/null @@ -1,138 +0,0 @@ -import prisma from "@/lib/db"; -import { createTRPCRouter, premiumProcedure, protectedProcedure } from "@/trpc/init"; -import z from "zod"; -import { PAGINATION } from "@/config/constants"; -import { CredentialType } from "@/generated/prisma"; -import { encrypt } from "@/lib/encryption"; - -export const credentialsRouter = createTRPCRouter({ - create: premiumProcedure - .input( - z.object({ - name: z.string().min(1, "Name is required"), - type: z.enum(CredentialType), - value: z.string().min(1, "Value is required") - }) - ) - .mutation(({ ctx, input }) => { - const { name, value, type } = input; - - return prisma.credential.create({ - data: { - name, - userId: ctx.auth.user.id, - type, - value: encrypt(value), - }, - }); - }), - remove: protectedProcedure - .input(z.object({ id: z.string() })) - .mutation(({ ctx, input }) => { - return prisma.credential.delete({ - where: { - id: input.id, - userId: ctx.auth.user.id, - }, - }) - }), - update: protectedProcedure - .input( - z.object({ - id: z.string(), - name: z.string().min(1, "Name is required"), - type: z.enum(CredentialType), - value: z.string().min(1, "Value is required"), - }), - ) - .mutation(({ ctx, input }) => { - const { id, name, type, value } = input; - - return prisma.credential.update({ - where: { id, userId: ctx.auth.user.id }, - data: { - name, - type, - value: encrypt(value), - } - }); - }), - getOne: protectedProcedure - .input(z.object({ id: z.string() })) - .query(({ ctx, input }) => { - return prisma.credential.findUniqueOrThrow({ - where: { id: input.id, userId: ctx.auth.user.id }, - }); - }), - getMany: protectedProcedure - .input( - z.object({ - page: z.number().default(PAGINATION.DEFAULT_PAGE), - pageSize: z - .number() - .min(PAGINATION.MIN_PAGE_SIZE) - .max(PAGINATION.MAX_PAGE_SIZE) - .default(PAGINATION.DEFAULT_PAGE_SIZE), - search: z.string().default(""), - }) - ) - .query(async ({ ctx, input }) => { - const { page, pageSize, search } = input; - - const [items, totalCount] = await Promise.all([ - prisma.credential.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - where: { - userId: ctx.auth.user.id, - name: { - contains: search, - mode: "insensitive", - }, - }, - orderBy: { - updatedAt: "desc", - }, - }), - prisma.credential.count({ - where: { - userId: ctx.auth.user.id, - name: { - contains: search, - mode: "insensitive", - }, - }, - }), - ]); - - const totalPages = Math.ceil(totalCount / pageSize); - const hasNextPage = page < totalPages; - const hasPreviousPage = page > 1; - - return { - items, - page, - pageSize, - totalCount, - totalPages, - hasNextPage, - hasPreviousPage, - }; - }), - getByType: protectedProcedure - .input( - z.object({ - type: z.enum(CredentialType), - }) - ) - .query(({ input, ctx }) => { - const { type } = input; - - return prisma.credential.findMany({ - where: { type, userId: ctx.auth.user.id }, - orderBy: { - updatedAt: "desc", - }, - }); - }), -}); diff --git a/src/features/credentials/store/credential-atoms.ts b/src/features/credentials/store/credential-atoms.ts new file mode 100644 index 0000000..881d23c --- /dev/null +++ b/src/features/credentials/store/credential-atoms.ts @@ -0,0 +1,11 @@ +import { atom } from "jotai"; +import type { Credential } from "../hooks/use-credentials"; + +/** Cached list of credentials for the current page. */ +export const credentialsAtom = atom([]); + +/** Total credential count (for pagination). */ +export const credentialsTotalAtom = atom(0); + +/** Whether credentials are currently being fetched. */ +export const credentialsLoadingAtom = atom(true); diff --git a/src/features/editor/components/editor-header.tsx b/src/features/editor/components/editor-header.tsx index e4a4c23..e44d65b 100644 --- a/src/features/editor/components/editor-header.tsx +++ b/src/features/editor/components/editor-header.tsx @@ -13,9 +13,14 @@ import { import { Input } from "@/components/ui/input"; import { useEffect, useRef, useState } from "react"; import Link from "next/link"; -import { useSuspenseWorkflow, useUpdateWorkflow, useUpdateWorkflowName } from "@/features/workflows/hooks/use-workflows"; +import { + useSuspenseWorkflow, + useUpdateWorkflow, + useUpdateWorkflowName, +} from "@/features/workflows/hooks/use-workflows"; import { useAtomValue } from "jotai"; import { editorAtom } from "../store/atoms"; +import { Skeleton } from "@/components/ui/skeleton"; export const EditorSaveButton = ({ workflowId }: { workflowId: string }) => { const editor = useAtomValue(editorAtom); @@ -34,7 +39,7 @@ export const EditorSaveButton = ({ workflowId }: { workflowId: string }) => { nodes, edges, }); - } + }; return (
@@ -43,23 +48,23 @@ export const EditorSaveButton = ({ workflowId }: { workflowId: string }) => { Save
- ) + ); }; export const EditorNameInput = ({ workflowId }: { workflowId: string }) => { - const { data: workflow } = useSuspenseWorkflow(workflowId); + const { data: workflow, isLoading } = useSuspenseWorkflow(workflowId); const updateWorkflow = useUpdateWorkflowName(); const [isEditing, setIsEditing] = useState(false); - const [name, setName] = useState(workflow.name); + const [name, setName] = useState(workflow?.name ?? ""); const inputRef = useRef(null); useEffect(() => { - if (workflow.name) { + if (workflow?.name) { setName(workflow.name); } - }, [workflow.name]); + }, [workflow?.name]); useEffect(() => { if (isEditing && inputRef.current) { @@ -69,7 +74,7 @@ export const EditorNameInput = ({ workflowId }: { workflowId: string }) => { }, [isEditing]); const handleSave = async () => { - if (name === workflow.name) { + if (name === workflow?.name) { setIsEditing(false); return; } @@ -80,7 +85,7 @@ export const EditorNameInput = ({ workflowId }: { workflowId: string }) => { name, }); } catch { - setName(workflow.name); + setName(workflow?.name ?? ""); } finally { setIsEditing(false); } @@ -90,11 +95,15 @@ export const EditorNameInput = ({ workflowId }: { workflowId: string }) => { if (e.key === "Enter") { handleSave(); } else if (e.key === "Escape") { - setName(workflow.name); + setName(workflow?.name ?? ""); setIsEditing(false); } }; + if (isLoading) { + return ; + } + if (isEditing) { return ( { onKeyDown={handleKeyDown} className="h-7 w-auto min-w-[100px] px-2" /> - ) + ); } return ( - setIsEditing(true)} className="cursor-pointer hover:text-foreground transition-colors"> - {workflow.name} + setIsEditing(true)} + className="cursor-pointer hover:text-foreground transition-colors" + > + {workflow?.name ?? "Untitled"} - ) + ); }; export const EditorBreadcrumbs = ({ workflowId }: { workflowId: string }) => { @@ -131,7 +143,7 @@ export const EditorBreadcrumbs = ({ workflowId }: { workflowId: string }) => { - ) + ); }; export const EditorHeader = ({ workflowId }: { workflowId: string }) => { diff --git a/src/features/editor/components/editor.tsx b/src/features/editor/components/editor.tsx index 265b17f..1170bfa 100644 --- a/src/features/editor/components/editor.tsx +++ b/src/features/editor/components/editor.tsx @@ -1,10 +1,10 @@ "use client"; -import { useState, useCallback, useMemo } from 'react'; -import { - ReactFlow, - applyNodeChanges, - applyEdgeChanges, +import { useState, useCallback, useMemo, useEffect } from "react"; +import { + ReactFlow, + applyNodeChanges, + applyEdgeChanges, addEdge, type Node, type Edge, @@ -15,17 +15,18 @@ import { Controls, MiniMap, Panel, -} from '@xyflow/react'; +} from "@xyflow/react"; import { ErrorView, LoadingView } from "@/components/entity-components"; import { useSuspenseWorkflow } from "@/features/workflows/hooks/use-workflows"; -import '@xyflow/react/dist/style.css'; -import { nodeComponents } from '@/config/node-components'; -import { AddNodeButton } from './add-node-button'; -import { useSetAtom } from 'jotai'; -import { editorAtom } from '../store/atoms'; -import { NodeType } from '@/generated/prisma'; -import { ExecuteWorkflowButton } from './execute-workflow-button'; +import "@xyflow/react/dist/style.css"; +import { nodeComponents } from "@/config/node-components"; +import { AddNodeButton } from "./add-node-button"; +import { useSetAtom } from "jotai"; +import { editorAtom } from "../store/atoms"; +import { NodeType } from "@/config/node-components"; +import { ExecuteWorkflowButton } from "./execute-workflow-button"; +import { useExecutionStream } from "../hooks/use-execution-stream"; export const EditorLoading = () => { return ; @@ -36,25 +37,42 @@ export const EditorError = () => { }; export const Editor = ({ workflowId }: { workflowId: string }) => { - const { - data: workflow - } = useSuspenseWorkflow(workflowId); + const { data: workflow, isLoading } = useSuspenseWorkflow(workflowId); const setEditor = useSetAtom(editorAtom); - const [nodes, setNodes] = useState(workflow.nodes); - const [edges, setEdges] = useState(workflow.edges); + // Subscribe to workflow-level SSE so webhook-triggered executions + // (Google Form, Stripe, etc.) also show real-time node status. + const { subscribeToWorkflow } = useExecutionStream(); + useEffect(() => { + subscribeToWorkflow(workflowId); + }, [workflowId, subscribeToWorkflow]); + + const workflowData = workflow as + | (typeof workflow & { nodes?: Node[]; edges?: Edge[] }) + | null; + const [nodes, setNodes] = useState(workflowData?.nodes ?? []); + const [edges, setEdges] = useState(workflowData?.edges ?? []); + + // Sync fetched workflow data into local state when it arrives + useEffect(() => { + if (workflowData?.nodes) setNodes(workflowData.nodes); + if (workflowData?.edges) setEdges(workflowData.edges); + }, [workflowData]); const onNodesChange = useCallback( - (changes: NodeChange[]) => setNodes((nodesSnapshot) => applyNodeChanges(changes, nodesSnapshot)), + (changes: NodeChange[]) => + setNodes((nodesSnapshot) => applyNodeChanges(changes, nodesSnapshot)), [], ); const onEdgesChange = useCallback( - (changes: EdgeChange[]) => setEdges((edgesSnapshot) => applyEdgeChanges(changes, edgesSnapshot)), + (changes: EdgeChange[]) => + setEdges((edgesSnapshot) => applyEdgeChanges(changes, edgesSnapshot)), [], ); const onConnect = useCallback( - (params: Connection) => setEdges((edgesSnapshot) => addEdge(params, edgesSnapshot)), + (params: Connection) => + setEdges((edgesSnapshot) => addEdge(params, edgesSnapshot)), [], ); @@ -62,8 +80,10 @@ export const Editor = ({ workflowId }: { workflowId: string }) => { return nodes.some((node) => node.type === NodeType.MANUAL_TRIGGER); }, [nodes]); + if (isLoading) return ; + return ( -
+
{ const executeWorkflow = useExecuteWorkflow(); + const { connect } = useExecutionStream(); - const handleExecute = () => { - executeWorkflow.mutate({ id: workflowId }); + const handleExecute = async () => { + const execution = await executeWorkflow.mutateAsync({ id: workflowId }); + if (execution?.id) { + connect(execution.id); + } }; return ( - diff --git a/src/features/editor/hooks/use-execution-stream.ts b/src/features/editor/hooks/use-execution-stream.ts new file mode 100644 index 0000000..e1018ae --- /dev/null +++ b/src/features/editor/hooks/use-execution-stream.ts @@ -0,0 +1,136 @@ +"use client"; + +import { useEffect, useRef, useCallback } from "react"; +import { useSetAtom } from "jotai"; +import { + nodeStatusMapAtom, + activeExecutionIdAtom, +} from "../store/execution-atoms"; +import type { NodeStatus } from "@/components/react-flow/node-status-indicator"; + +const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000"; + +/** + * Subscribe to SSE streams for workflow executions. + * + * - `connect(executionId)` — execution-level stream (node status updates). + * - `subscribeToWorkflow(workflowId)` — workflow-level stream that + * auto-connects to execution-level SSE whenever any execution starts + * (including webhook-triggered ones from Google Form / Stripe). + */ +export const useExecutionStream = () => { + const setNodeStatusMap = useSetAtom(nodeStatusMapAtom); + const setActiveExecutionId = useSetAtom(activeExecutionIdAtom); + const executionEsRef = useRef(null); + const workflowEsRef = useRef(null); + + /** Close the current execution-level SSE connection. */ + const disconnectExecution = useCallback(() => { + if (executionEsRef.current) { + executionEsRef.current.close(); + executionEsRef.current = null; + } + }, []); + + /** Start listening to SSE events for a given execution. */ + const connect = useCallback( + (executionId: string) => { + // Close any previous execution connection + disconnectExecution(); + + setActiveExecutionId(executionId); + setNodeStatusMap({}); + + const url = `${API_BASE_URL}/api/executions/${executionId}/stream`; + const es = new EventSource(url, { withCredentials: true }); + executionEsRef.current = es; + + es.addEventListener("node:start", (e) => { + const { nodeId } = JSON.parse(e.data); + setNodeStatusMap((prev) => ({ + ...prev, + [nodeId]: "loading" as NodeStatus, + })); + }); + + es.addEventListener("node:complete", (e) => { + const { nodeId } = JSON.parse(e.data); + setNodeStatusMap((prev) => ({ + ...prev, + [nodeId]: "success" as NodeStatus, + })); + }); + + es.addEventListener("node:error", (e) => { + const { nodeId } = JSON.parse(e.data); + setNodeStatusMap((prev) => ({ + ...prev, + [nodeId]: "error" as NodeStatus, + })); + }); + + es.addEventListener("execution:complete", () => { + setActiveExecutionId(null); + es.close(); + executionEsRef.current = null; + }); + + es.addEventListener("execution:error", () => { + setActiveExecutionId(null); + es.close(); + executionEsRef.current = null; + }); + + es.onerror = () => { + es.close(); + executionEsRef.current = null; + setActiveExecutionId(null); + }; + }, + [disconnectExecution, setActiveExecutionId, setNodeStatusMap], + ); + + /** + * Subscribe to the workflow-level SSE stream. + * When a new execution starts (e.g. via webhook), this auto-connects + * to the execution-level stream so nodes show live status. + */ + const subscribeToWorkflow = useCallback( + (workflowId: string) => { + // Close any previous workflow subscription + disconnectWorkflow(); + + const url = `${API_BASE_URL}/api/workflows/${workflowId}/stream`; + const ws = new EventSource(url, { withCredentials: true }); + workflowEsRef.current = ws; + + ws.addEventListener("execution:started", (e) => { + const { executionId } = JSON.parse(e.data); + connect(executionId); + }); + + ws.onerror = () => { + // Silently reconnect — EventSource auto-reconnects in most browsers + }; + }, + [connect], + ); + + /** Close the workflow-level SSE subscription. */ + const disconnectWorkflow = useCallback(() => { + if (workflowEsRef.current) { + workflowEsRef.current.close(); + workflowEsRef.current = null; + } + }, []); + + // Clean up on unmount + useEffect(() => { + return () => { + disconnectExecution(); + disconnectWorkflow(); + }; + }, [disconnectExecution, disconnectWorkflow]); + + return { connect, disconnectExecution, subscribeToWorkflow, disconnectWorkflow }; +}; diff --git a/src/features/editor/hooks/use-node-status.ts b/src/features/editor/hooks/use-node-status.ts new file mode 100644 index 0000000..5889ddf --- /dev/null +++ b/src/features/editor/hooks/use-node-status.ts @@ -0,0 +1,11 @@ +"use client"; + +import { useAtomValue } from "jotai"; +import { nodeStatusMapAtom } from "../store/execution-atoms"; +import type { NodeStatus } from "@/components/react-flow/node-status-indicator"; + +/** Read the current execution status for a specific node. */ +export const useNodeExecutionStatus = (nodeId: string): NodeStatus | undefined => { + const statusMap = useAtomValue(nodeStatusMapAtom); + return statusMap[nodeId]; +}; diff --git a/src/features/editor/store/execution-atoms.ts b/src/features/editor/store/execution-atoms.ts new file mode 100644 index 0000000..da1be6f --- /dev/null +++ b/src/features/editor/store/execution-atoms.ts @@ -0,0 +1,8 @@ +import { atom } from "jotai"; +import type { NodeStatus } from "@/components/react-flow/node-status-indicator"; + +/** Map of nodeId → execution status, updated in real-time via SSE. */ +export const nodeStatusMapAtom = atom>({}); + +/** The currently active execution ID (for SSE subscription). */ +export const activeExecutionIdAtom = atom(null); diff --git a/src/features/executions/components/anthropic/actions.ts b/src/features/executions/components/anthropic/actions.ts index 6dc97be..a19108b 100644 --- a/src/features/executions/components/anthropic/actions.ts +++ b/src/features/executions/components/anthropic/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { anthropicChannel } from "@/inngest/channels/anthropic"; -import { inngest } from "@/inngest/client"; - -export type AnthropicToken = Realtime.Token< - typeof anthropicChannel, - ["status"] ->; - -export async function fetchAnthropicRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: anthropicChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/executions/components/anthropic/dialog.tsx b/src/features/executions/components/anthropic/dialog.tsx index e490f3c..45c97c3 100644 --- a/src/features/executions/components/anthropic/dialog.tsx +++ b/src/features/executions/components/anthropic/dialog.tsx @@ -25,7 +25,7 @@ import { useForm } from "react-hook-form"; import { useEffect } from "react"; import { Button } from "@/components/ui/button"; import { useCredentialsByType } from "@/features/credentials/hooks/use-credentials"; -import { CredentialType } from "@/generated/prisma"; +import { CredentialType } from "@/features/credentials/hooks/use-credentials"; import { Select, SelectContent, diff --git a/src/features/executions/components/anthropic/executor.ts b/src/features/executions/components/anthropic/executor.ts index bd1e5e0..3b3bed6 100644 --- a/src/features/executions/components/anthropic/executor.ts +++ b/src/features/executions/components/anthropic/executor.ts @@ -1,140 +1,4 @@ -import Handlebars from "handlebars"; -import { NonRetriableError } from "inngest"; -import { generateText } from "ai"; -import { createAnthropic } from "@ai-sdk/anthropic"; import type { NodeExecutor } from "@/features/executions/types"; -import { anthropicChannel } from "@/inngest/channels/anthropic"; -import prisma from "@/lib/db"; -import { decrypt } from "@/lib/encryption"; -Handlebars.registerHelper("json", (context) => { - const jsonString = JSON.stringify(context, null, 2); - const safeString = new Handlebars.SafeString(jsonString); - - return safeString; -}); - -type AnthropicData = { - variableName?: string; - credentialId?: string; - systemPrompt?: string; - userPrompt?: string; -}; - -export const anthropicExecutor: NodeExecutor = async ({ - data, - nodeId, - userId, - context, - step, - publish, -}) => { - await publish( - anthropicChannel().status({ - nodeId, - status: "loading", - }), - ); - - if (!data.variableName) { - await publish( - anthropicChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("Anthropic node: Variable name is missing"); - } - - if (!data.credentialId) { - await publish( - anthropicChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("Anthropic node: Credential is required"); - } - - if (!data.userPrompt) { - await publish( - anthropicChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("Anthropic node: User prompt is missing"); - } - - const systemPrompt = data.systemPrompt - ? Handlebars.compile(data.systemPrompt)(context) - : "You are a helpful assistant."; - const userPrompt = Handlebars.compile(data.userPrompt)(context); - - const credential = await step.run("get-credential", () => { - return prisma.credential.findUnique({ - where: { - id: data.credentialId, - userId, - }, - }); - }); - - if (!credential) { - await publish( - anthropicChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("Anthropic node: Credential not found"); - } - - const anthropic = createAnthropic({ - apiKey: decrypt(credential.value), - }); - - try { - const { steps } = await step.ai.wrap( - "anthropic-generate-text", - generateText, - { - model: anthropic("claude-sonnet-4-5"), - system: systemPrompt, - prompt: userPrompt, - experimental_telemetry: { - isEnabled: true, - recordInputs: true, - recordOutputs: true, - }, - }, - ); - - const text = - steps[0].content[0].type === "text" - ? steps[0].content[0].text - : ""; - - await publish( - anthropicChannel().status({ - nodeId, - status: "success", - }), - ); - - return { - ...context, - [data.variableName]: { - text, - }, - } - } catch (error) { - await publish( - anthropicChannel().status({ - nodeId, - status: "error", - }), - ); - throw error; - } -}; +// TODO: Implement Anthropic executor via custom backend AI API +export const anthropicExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/executions/components/anthropic/node.tsx b/src/features/executions/components/anthropic/node.tsx index 2cce326..7a994dc 100644 --- a/src/features/executions/components/anthropic/node.tsx +++ b/src/features/executions/components/anthropic/node.tsx @@ -4,9 +4,7 @@ import { useReactFlow, type Node, type NodeProps } from "@xyflow/react"; import { memo, useState } from "react"; import { BaseExecutionNode } from "../base-execution-node"; import { AnthropicDialog, AnthropicFormValues } from "./dialog"; -import { useNodeStatus } from "../../hooks/use-node-status"; -import { fetchAnthropicRealtimeToken } from "./actions"; -import { ANTHROPIC_CHANNEL_NAME } from "@/inngest/channels/anthropic"; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; type AnthropicNodeData = { variableName?: string; @@ -20,29 +18,19 @@ type AnthropicNodeType = Node; export const AnthropicNode = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); const { setNodes } = useReactFlow(); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: ANTHROPIC_CHANNEL_NAME, - topic: "status", - refreshToken: fetchAnthropicRealtimeToken, - }); + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); const handleSubmit = (values: AnthropicFormValues) => { - setNodes((nodes) => nodes.map((node) => { - if (node.id === props.id) { - return { - ...node, - data: { - ...node.data, - ...values, - } + setNodes((nodes) => + nodes.map((node) => { + if (node.id === props.id) { + return { ...node, data: { ...node.data, ...values } }; } - } - return node; - })) + return node; + }), + ); }; const nodeData = props.data; @@ -63,13 +51,13 @@ export const AnthropicNode = memo((props: NodeProps) => { id={props.id} icon="/logos/anthropic.svg" name="Anthropic" - status={nodeStatus} + status={status} description={description} onSettings={handleOpenSettings} onDoubleClick={handleOpenSettings} /> - ) + ); }); AnthropicNode.displayName = "AnthropicNode"; diff --git a/src/features/executions/components/discord/actions.ts b/src/features/executions/components/discord/actions.ts index efb0f5f..a19108b 100644 --- a/src/features/executions/components/discord/actions.ts +++ b/src/features/executions/components/discord/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { discordChannel } from "@/inngest/channels/discord"; -import { inngest } from "@/inngest/client"; - -export type DiscordToken = Realtime.Token< - typeof discordChannel, - ["status"] ->; - -export async function fetchDiscordRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: discordChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/executions/components/discord/executor.ts b/src/features/executions/components/discord/executor.ts index 9b3904c..c469f28 100644 --- a/src/features/executions/components/discord/executor.ts +++ b/src/features/executions/components/discord/executor.ts @@ -1,106 +1,4 @@ -import Handlebars from "handlebars"; -import { decode } from "html-entities"; -import { NonRetriableError } from "inngest"; import type { NodeExecutor } from "@/features/executions/types"; -import { discordChannel } from "@/inngest/channels/discord"; -import ky from "ky"; -Handlebars.registerHelper("json", (context) => { - const jsonString = JSON.stringify(context, null, 2); - const safeString = new Handlebars.SafeString(jsonString); - - return safeString; -}); - -type DiscordData = { - variableName?: string; - webhookUrl?: string; - content?: string; - username?: string; -}; - -export const discordExecutor: NodeExecutor = async ({ - data, - nodeId, - context, - step, - publish, -}) => { - await publish( - discordChannel().status({ - nodeId, - status: "loading", - }), - ); - - if (!data.content) { - await publish( - discordChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("Discord node: Message content is required"); - } - - const rawContent = Handlebars.compile(data.content)(context); - const content = decode(rawContent); - const username = data.username - ? decode(Handlebars.compile(data.username)(context)) - : undefined; - - try { - const result = await step.run("discord-webhook", async () => { - if (!data.webhookUrl) { - await publish( - discordChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("Discord node: Webhook URL is required"); - } - - await ky.post(data.webhookUrl, { - json: { - content: content.slice(0, 2000), // Discord's max message length - username, - }, - }); - - if (!data.variableName) { - await publish( - discordChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("Discord node: Variable name is missing"); - } - - return { - ...context, - [data.variableName]: { - messageContent: content.slice(0, 2000), - }, - }; - }); - - await publish( - discordChannel().status({ - nodeId, - status: "success", - }), - ); - - return result; - } catch (error) { - await publish( - discordChannel().status({ - nodeId, - status: "error", - }), - ); - throw error; - } -}; +// TODO: Implement Discord executor via custom backend API +export const discordExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/executions/components/discord/node.tsx b/src/features/executions/components/discord/node.tsx index bd95ebb..bb53411 100644 --- a/src/features/executions/components/discord/node.tsx +++ b/src/features/executions/components/discord/node.tsx @@ -4,43 +4,25 @@ import { useReactFlow, type Node, type NodeProps } from "@xyflow/react"; import { memo, useState } from "react"; import { BaseExecutionNode } from "../base-execution-node"; import { DiscordDialog, DiscordFormValues } from "./dialog"; -import { useNodeStatus } from "../../hooks/use-node-status"; -import { fetchDiscordRealtimeToken } from "./actions"; -import { DISCORD_CHANNEL_NAME } from "@/inngest/channels/discord"; - -type DiscordNodeData = { - webhookUrl?: string; - content?: string; -}; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; +type DiscordNodeData = { webhookUrl?: string; content?: string }; type DiscordNodeType = Node; export const DiscordNode = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); const { setNodes } = useReactFlow(); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: DISCORD_CHANNEL_NAME, - topic: "status", - refreshToken: fetchDiscordRealtimeToken, - }); + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); - const handleSubmit = (values: DiscordFormValues) => { - setNodes((nodes) => nodes.map((node) => { - if (node.id === props.id) { - return { - ...node, - data: { - ...node.data, - ...values, - } - } - } - return node; - })) + setNodes((nodes) => + nodes.map((node) => + node.id === props.id + ? { ...node, data: { ...node.data, ...values } } + : node, + ), + ); }; const nodeData = props.data; @@ -61,13 +43,12 @@ export const DiscordNode = memo((props: NodeProps) => { id={props.id} icon="/logos/discord.svg" name="Discord" - status={nodeStatus} + status={status} description={description} onSettings={handleOpenSettings} onDoubleClick={handleOpenSettings} /> - ) + ); }); - DiscordNode.displayName = "DiscordNode"; diff --git a/src/features/executions/components/execution.tsx b/src/features/executions/components/execution.tsx index b8af5be..7b5b521 100644 --- a/src/features/executions/components/execution.tsx +++ b/src/features/executions/components/execution.tsx @@ -1,7 +1,12 @@ "use client"; -import { ExecutionStatus } from "@/generated/prisma"; -import { CheckCircle2Icon, ClockIcon, Loader2Icon, XCircleIcon } from "lucide-react"; +import { ExecutionStatus } from "@/config/constants"; +import { + CheckCircle2Icon, + ClockIcon, + Loader2Icon, + XCircleIcon, +} from "lucide-react"; import { formatDistanceToNow } from "date-fns"; import Link from "next/link"; import { useState } from "react"; @@ -20,7 +25,7 @@ import { } from "@/components/ui/collapsible"; import { useSuspenseExecution } from "@/features/executions/hooks/use-executions"; -const getStatusIcon = (status: ExecutionStatus) => { +const getStatusIcon = (status: string) => { switch (status) { case ExecutionStatus.SUCCESS: return ; @@ -31,37 +36,51 @@ const getStatusIcon = (status: ExecutionStatus) => { default: return ; } -} +}; -const formatStatus = (status: ExecutionStatus) => { +const formatStatus = (status: string) => { return status.charAt(0) + status.slice(1).toLowerCase(); }; -export const ExecutionView = ({ - executionId -}: { - executionId: string -}) => { +export const ExecutionView = ({ executionId }: { executionId: string }) => { const { data: execution } = useSuspenseExecution(executionId); const [showStackTrace, setShowStackTrace] = useState(false); + if (!execution) { + return ( + + + Execution not found + No execution data available + + + ); + } + const duration = execution.completedAt ? Math.round( - (new Date(execution.completedAt).getTime() - new Date(execution.startedAt).getTime()) / 1000, - ) + (new Date(execution.completedAt).getTime() - + new Date(execution.startedAt).getTime()) / + 1000, + ) : null; + // Cast output to access fields from the real API when connected + const exec = execution as typeof execution & { + workflow?: { name: string }; + inngestEventId?: string; + errorStack?: string; + }; + return (
{getStatusIcon(execution.status)}
- - {formatStatus(execution.status)} - + {formatStatus(execution.status)} - Execution for {execution.workflow.name} + Execution for workflow {execution.workflowId}
@@ -72,12 +91,12 @@ export const ExecutionView = ({

Workflow

- - {execution.workflow.name} + {exec.workflow?.name ?? execution.workflowId}
@@ -88,74 +107,85 @@ export const ExecutionView = ({

Started

-

{formatDistanceToNow(execution.startedAt, { addSuffix: true })}

+

+ {formatDistanceToNow(execution.startedAt, { addSuffix: true })} +

{execution.completedAt ? (
-

Completed

-

{formatDistanceToNow(execution.completedAt, { addSuffix: true })}

+

+ Completed +

+

+ {formatDistanceToNow(execution.completedAt, { + addSuffix: true, + })} +

) : null} {duration !== null ? (
-

Duration

+

+ Duration +

{duration}s

) : null} -
-

Event ID

-

{execution.inngestEventId}

-
-
- {execution.error && ( -
-
-

- Error -

-

- {execution.error} -

-
- - {execution.errorStack && ( - - - - - -
-                      {execution.errorStack}
-                    
-
-
- )} + {exec.inngestEventId && ( +
+

+ Event ID +

+

{exec.inngestEventId}

)} +
- {execution.output && ( -
-

Output

-
-                {JSON.stringify(execution.output, null, 2)}
-              
+ {execution.error && ( +
+
+

Error

+

+ {execution.error} +

- )} + + {exec.errorStack && ( + + + + + +
+                    {exec.errorStack}
+                  
+
+
+ )} +
+ )} + + {execution.output !== null && execution.output !== undefined && ( +
+

Output

+
+              {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
+              {String(JSON.stringify(execution.output as any, null, 2))}
+            
+
+ )} ); diff --git a/src/features/executions/components/executions.tsx b/src/features/executions/components/executions.tsx index 5820310..4db37ab 100644 --- a/src/features/executions/components/executions.tsx +++ b/src/features/executions/components/executions.tsx @@ -1,21 +1,26 @@ "use client"; import { formatDistanceToNow } from "date-fns"; -import { +import { EmptyView, - EntityContainer, - EntityHeader, - EntityItem, - EntityList, - EntityPagination, + EntityContainer, + EntityHeader, + EntityItem, + EntityList, + EntityPagination, ErrorView, - LoadingView + LoadingView, } from "@/components/entity-components"; -import { useSuspenseExecutions } from "../hooks/use-executions" +import { useSuspenseExecutions } from "../hooks/use-executions"; import { useExecutionsParams } from "../hooks/use-executions-params"; -import type { Execution } from "@/generated/prisma"; -import { ExecutionStatus } from "@/generated/prisma"; -import { CheckCircle2Icon, ClockIcon, Loader2Icon, XCircleIcon } from "lucide-react"; +import type { Execution } from "../hooks/use-executions"; +import { ExecutionStatus } from "@/config/constants"; +import { + CheckCircle2Icon, + ClockIcon, + Loader2Icon, + XCircleIcon, +} from "lucide-react"; export const ExecutionsList = () => { const executions = useSuspenseExecutions(); @@ -45,16 +50,16 @@ export const ExecutionsPagination = () => { return ( setParams({ ...params, page })} /> ); }; export const ExecutionsContainer = ({ - children + children, }: { children: React.ReactNode; }) => { @@ -78,48 +83,45 @@ export const ExecutionsError = () => { export const ExecutionsEmpty = () => { return ( - + ); }; -const getStatusIcon = (status: ExecutionStatus) => { +const getStatusIcon = (status: string) => { switch (status) { - case ExecutionStatus.SUCCESS: + case "SUCCESS": return ; - case ExecutionStatus.FAILED: + case "FAILED": return ; - case ExecutionStatus.RUNNING: + case "RUNNING": return ; default: return ; } -} +}; -const formatStatus = (status: ExecutionStatus) => { +const formatStatus = (status: string) => { return status.charAt(0) + status.slice(1).toLowerCase(); }; export const ExecutionItem = ({ data, -}: { +}: { data: Execution & { - workflow: { - id: string; - name: string; - }; + workflow?: { id: string; name: string }; }; }) => { const duration = data.completedAt ? Math.round( - (new Date(data.completedAt).getTime() - new Date(data.startedAt).getTime()) / 1000, - ) + (new Date(data.completedAt).getTime() - + new Date(data.startedAt).getTime()) / + 1000, + ) : null; const subtitle = ( <> - {data.workflow.name} • Started{" "} + {data.workflow?.name ?? data.workflowId} • Started{" "} {formatDistanceToNow(data.startedAt, { addSuffix: true })} {duration !== null && <> • Took {duration}s } @@ -136,5 +138,5 @@ export const ExecutionItem = ({
} /> - ) + ); }; diff --git a/src/features/executions/components/gemini/actions.ts b/src/features/executions/components/gemini/actions.ts index 3f7976a..a19108b 100644 --- a/src/features/executions/components/gemini/actions.ts +++ b/src/features/executions/components/gemini/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { geminiChannel } from "@/inngest/channels/gemini"; -import { inngest } from "@/inngest/client"; - -export type GeminiToken = Realtime.Token< - typeof geminiChannel, - ["status"] ->; - -export async function fetchGeminiRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: geminiChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/executions/components/gemini/dialog.tsx b/src/features/executions/components/gemini/dialog.tsx index caff5a2..208a6f1 100644 --- a/src/features/executions/components/gemini/dialog.tsx +++ b/src/features/executions/components/gemini/dialog.tsx @@ -25,7 +25,7 @@ import { useForm } from "react-hook-form"; import { useEffect } from "react"; import { Button } from "@/components/ui/button"; import { useCredentialsByType } from "@/features/credentials/hooks/use-credentials"; -import { CredentialType } from "@/generated/prisma"; +import { CredentialType } from "@/features/credentials/hooks/use-credentials"; import { Select, SelectContent, diff --git a/src/features/executions/components/gemini/executor.ts b/src/features/executions/components/gemini/executor.ts index 92e1c21..76621db 100644 --- a/src/features/executions/components/gemini/executor.ts +++ b/src/features/executions/components/gemini/executor.ts @@ -1,140 +1,4 @@ -import Handlebars from "handlebars"; -import { NonRetriableError } from "inngest"; -import { generateText } from "ai"; -import { createGoogleGenerativeAI } from "@ai-sdk/google"; import type { NodeExecutor } from "@/features/executions/types"; -import { geminiChannel } from "@/inngest/channels/gemini"; -import prisma from "@/lib/db"; -import { decrypt } from "@/lib/encryption"; -Handlebars.registerHelper("json", (context) => { - const jsonString = JSON.stringify(context, null, 2); - const safeString = new Handlebars.SafeString(jsonString); - - return safeString; -}); - -type GeminiData = { - variableName?: string; - credentialId?: string; - systemPrompt?: string; - userPrompt?: string; -}; - -export const geminiExecutor: NodeExecutor = async ({ - data, - nodeId, - userId, - context, - step, - publish, -}) => { - await publish( - geminiChannel().status({ - nodeId, - status: "loading", - }), - ); - - if (!data.variableName) { - await publish( - geminiChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("Gemini node: Variable name is missing"); - } - - if (!data.credentialId) { - await publish( - geminiChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("Gemini node: Credential is required"); - } - - if (!data.userPrompt) { - await publish( - geminiChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("Gemini node: User prompt is missing"); - } - - const systemPrompt = data.systemPrompt - ? Handlebars.compile(data.systemPrompt)(context) - : "You are a helpful assistant."; - const userPrompt = Handlebars.compile(data.userPrompt)(context); - - const credential = await step.run("get-credential", () => { - return prisma.credential.findUnique({ - where: { - id: data.credentialId, - userId, - }, - }); - }); - - if (!credential) { - await publish( - geminiChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("Gemini node: Credential not found"); - } - - const google = createGoogleGenerativeAI({ - apiKey: decrypt(credential.value), - }); - - try { - const { steps } = await step.ai.wrap( - "gemini-generate-text", - generateText, - { - model: google("gemini-2.0-flash"), - system: systemPrompt, - prompt: userPrompt, - experimental_telemetry: { - isEnabled: true, - recordInputs: true, - recordOutputs: true, - }, - }, - ); - - const text = - steps[0].content[0].type === "text" - ? steps[0].content[0].text - : ""; - - await publish( - geminiChannel().status({ - nodeId, - status: "success", - }), - ); - - return { - ...context, - [data.variableName]: { - text, - }, - } - } catch (error) { - await publish( - geminiChannel().status({ - nodeId, - status: "error", - }), - ); - throw error; - } -}; +// TODO: Implement Gemini executor via custom backend AI API +export const geminiExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/executions/components/gemini/node.tsx b/src/features/executions/components/gemini/node.tsx index 40bf60e..3365aea 100644 --- a/src/features/executions/components/gemini/node.tsx +++ b/src/features/executions/components/gemini/node.tsx @@ -4,9 +4,7 @@ import { useReactFlow, type Node, type NodeProps } from "@xyflow/react"; import { memo, useState } from "react"; import { BaseExecutionNode } from "../base-execution-node"; import { GeminiDialog, GeminiFormValues } from "./dialog"; -import { useNodeStatus } from "../../hooks/use-node-status"; -import { fetchGeminiRealtimeToken } from "./actions"; -import { GEMINI_CHANNEL_NAME } from "@/inngest/channels/gemini"; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; type GeminiNodeData = { variableName?: string; @@ -14,42 +12,26 @@ type GeminiNodeData = { systemPrompt?: string; userPrompt?: string; }; - type GeminiNodeType = Node; export const GeminiNode = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); const { setNodes } = useReactFlow(); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: GEMINI_CHANNEL_NAME, - topic: "status", - refreshToken: fetchGeminiRealtimeToken, - }); - + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); - const handleSubmit = (values: GeminiFormValues) => { - setNodes((nodes) => nodes.map((node) => { - if (node.id === props.id) { - return { - ...node, - data: { - ...node.data, - ...values, - } - } - } - return node; - })) + setNodes((nodes) => + nodes.map((node) => + node.id === props.id + ? { ...node, data: { ...node.data, ...values } } + : node, + ), + ); }; - const nodeData = props.data; const description = nodeData?.userPrompt - ? `gemini-2.0-flash: ${nodeData.userPrompt.slice(0, 50)}...` + ? `gemini-2.5-flash: ${nodeData.userPrompt.slice(0, 50)}...` : "Not configured"; - return ( <> ) => { id={props.id} icon="/logos/gemini.svg" name="Gemini" - status={nodeStatus} + status={status} description={description} onSettings={handleOpenSettings} onDoubleClick={handleOpenSettings} /> - ) + ); }); - GeminiNode.displayName = "GeminiNode"; diff --git a/src/features/executions/components/http-request/actions.ts b/src/features/executions/components/http-request/actions.ts index d489c23..a19108b 100644 --- a/src/features/executions/components/http-request/actions.ts +++ b/src/features/executions/components/http-request/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { httpRequestChannel } from "@/inngest/channels/http-request"; -import { inngest } from "@/inngest/client"; - -export type HttpRequestToken = Realtime.Token< - typeof httpRequestChannel, - ["status"] ->; - -export async function fetchHttpRequestRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: httpRequestChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/executions/components/http-request/executor.ts b/src/features/executions/components/http-request/executor.ts index dfddedf..806e626 100644 --- a/src/features/executions/components/http-request/executor.ts +++ b/src/features/executions/components/http-request/executor.ts @@ -1,118 +1,4 @@ -import Handlebars from "handlebars"; -import { NonRetriableError } from "inngest"; -import ky, { type Options as KyOptions } from "ky"; import type { NodeExecutor } from "@/features/executions/types"; -import { httpRequestChannel } from "@/inngest/channels/http-request"; -Handlebars.registerHelper("json", (context) => { - const jsonString = JSON.stringify(context, null, 2); - const safeString = new Handlebars.SafeString(jsonString); - - return safeString; -}); - -type HttpRequestData = { - variableName?: string; - endpoint?: string; - method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; - body?: string; -}; - -export const httpRequestExecutor: NodeExecutor = async ({ - data, - nodeId, - context, - step, - publish, -}) => { - await publish( - httpRequestChannel().status({ - nodeId, - status: "loading", - }), - ); - - try { - const result = await step.run("http-request", async () => { - if (!data.endpoint) { - await publish( - httpRequestChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("HTTP Request node: No endpoint configured"); - } - - if (!data.variableName) { - await publish( - httpRequestChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("HTTP Request node: Variable name not configured"); - } - - if (!data.method) { - await publish( - httpRequestChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("HTTP Request node: Method not configured"); - } - - const endpoint = Handlebars.compile(data.endpoint)(context); - const method = data.method; - - const options: KyOptions = { method }; - - if (["POST", "PUT", "PATCH"].includes(method)) { - const resolved = Handlebars.compile(data.body || "{}")(context); - JSON.parse(resolved); - options.body = resolved; - options.headers = { - "Content-Type": "application/json", - }; - } - - const response = await ky(endpoint, options); - const contentType = response.headers.get("content-type"); - const responseData = contentType?.includes("application/json") - ? await response.json() - : await response.text(); - - const responsePayload = { - httpResponse: { - status: response.status, - statusText: response.statusText, - data: responseData, - }, - }; - - return { - ...context, - [data.variableName]: responsePayload, - } - }); - - await publish( - httpRequestChannel().status({ - nodeId, - status: "success", - }), - ); - - return result; - } catch (error) { - await publish( - httpRequestChannel().status({ - nodeId, - status: "error", - }), - ); - throw error; - } -}; +// TODO: Implement HTTP request executor via custom backend +export const httpRequestExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/executions/components/http-request/node.tsx b/src/features/executions/components/http-request/node.tsx index 5f41b77..d6a70c7 100644 --- a/src/features/executions/components/http-request/node.tsx +++ b/src/features/executions/components/http-request/node.tsx @@ -5,9 +5,7 @@ import { GlobeIcon } from "lucide-react"; import { memo, useState } from "react"; import { BaseExecutionNode } from "../base-execution-node"; import { HttpRequestFormValues, HttpRequestDialog } from "./dialog"; -import { useNodeStatus } from "../../hooks/use-node-status"; -import { HTTP_REQUEST_CHANNEL_NAME } from "@/inngest/channels/http-request"; -import { fetchHttpRequestRealtimeToken } from "./actions"; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; type HttpRequestNodeData = { variableName?: string; @@ -15,42 +13,26 @@ type HttpRequestNodeData = { method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; body?: string; }; - type HttpRequestNodeType = Node; export const HttpRequestNode = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); const { setNodes } = useReactFlow(); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: HTTP_REQUEST_CHANNEL_NAME, - topic: "status", - refreshToken: fetchHttpRequestRealtimeToken, - }); - + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); - const handleSubmit = (values: HttpRequestFormValues) => { - setNodes((nodes) => nodes.map((node) => { - if (node.id === props.id) { - return { - ...node, - data: { - ...node.data, - ...values, - } - } - } - return node; - })) + setNodes((nodes) => + nodes.map((node) => + node.id === props.id + ? { ...node, data: { ...node.data, ...values } } + : node, + ), + ); }; - const nodeData = props.data; const description = nodeData?.endpoint ? `${nodeData.method || "GET"}: ${nodeData.endpoint}` : "Not configured"; - return ( <> ) => { id={props.id} icon={GlobeIcon} name="HTTP Request" - status={nodeStatus} + status={status} description={description} onSettings={handleOpenSettings} onDoubleClick={handleOpenSettings} /> - ) + ); }); - HttpRequestNode.displayName = "HttpRequestNode"; diff --git a/src/features/executions/components/openai/actions.ts b/src/features/executions/components/openai/actions.ts index a80a421..a19108b 100644 --- a/src/features/executions/components/openai/actions.ts +++ b/src/features/executions/components/openai/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { openAiChannel } from "@/inngest/channels/openai"; -import { inngest } from "@/inngest/client"; - -export type OpenAiToken = Realtime.Token< - typeof openAiChannel, - ["status"] ->; - -export async function fetchOpenAiRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: openAiChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/executions/components/openai/dialog.tsx b/src/features/executions/components/openai/dialog.tsx index cc1ab53..12cc425 100644 --- a/src/features/executions/components/openai/dialog.tsx +++ b/src/features/executions/components/openai/dialog.tsx @@ -25,7 +25,7 @@ import { useForm } from "react-hook-form"; import { useEffect } from "react"; import { Button } from "@/components/ui/button"; import { useCredentialsByType } from "@/features/credentials/hooks/use-credentials"; -import { CredentialType } from "@/generated/prisma"; +import { CredentialType } from "@/features/credentials/hooks/use-credentials"; import { Select, SelectContent, diff --git a/src/features/executions/components/openai/executor.ts b/src/features/executions/components/openai/executor.ts index c91648c..4086171 100644 --- a/src/features/executions/components/openai/executor.ts +++ b/src/features/executions/components/openai/executor.ts @@ -1,140 +1,4 @@ -import Handlebars from "handlebars"; -import { NonRetriableError } from "inngest"; -import { generateText } from "ai"; -import { createOpenAI } from "@ai-sdk/openai"; import type { NodeExecutor } from "@/features/executions/types"; -import { openAiChannel } from "@/inngest/channels/openai"; -import prisma from "@/lib/db"; -import { decrypt } from "@/lib/encryption"; -Handlebars.registerHelper("json", (context) => { - const jsonString = JSON.stringify(context, null, 2); - const safeString = new Handlebars.SafeString(jsonString); - - return safeString; -}); - -type OpenAiData = { - variableName?: string; - credentialId?: string; - systemPrompt?: string; - userPrompt?: string; -}; - -export const openAiExecutor: NodeExecutor = async ({ - data, - nodeId, - userId, - context, - step, - publish, -}) => { - await publish( - openAiChannel().status({ - nodeId, - status: "loading", - }), - ); - - if (!data.variableName) { - await publish( - openAiChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("OpenAi node: Variable name is missing"); - } - - if (!data.credentialId) { - await publish( - openAiChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("OpenAi node: Credential is required"); - } - - if (!data.userPrompt) { - await publish( - openAiChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("OpenAi node: User prompt is missing"); - } - - const systemPrompt = data.systemPrompt - ? Handlebars.compile(data.systemPrompt)(context) - : "You are a helpful assistant."; - const userPrompt = Handlebars.compile(data.userPrompt)(context); - - const credential = await step.run("get-credential", () => { - return prisma.credential.findUnique({ - where: { - id: data.credentialId, - userId, - }, - }); - }); - - if (!credential) { - await publish( - openAiChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("OpenAI node: Credential not found"); - } - - const openai = createOpenAI({ - apiKey: decrypt(credential.value), - }); - - try { - const { steps } = await step.ai.wrap( - "openai-generate-text", - generateText, - { - model: openai("gpt-4"), - system: systemPrompt, - prompt: userPrompt, - experimental_telemetry: { - isEnabled: true, - recordInputs: true, - recordOutputs: true, - }, - }, - ); - - const text = - steps[0].content[0].type === "text" - ? steps[0].content[0].text - : ""; - - await publish( - openAiChannel().status({ - nodeId, - status: "success", - }), - ); - - return { - ...context, - [data.variableName]: { - text, - }, - } - } catch (error) { - await publish( - openAiChannel().status({ - nodeId, - status: "error", - }), - ); - throw error; - } -}; +// TODO: Implement OpenAI executor via custom backend AI API +export const openAiExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/executions/components/openai/node.tsx b/src/features/executions/components/openai/node.tsx index b80ef08..24c8ab0 100644 --- a/src/features/executions/components/openai/node.tsx +++ b/src/features/executions/components/openai/node.tsx @@ -4,9 +4,7 @@ import { useReactFlow, type Node, type NodeProps } from "@xyflow/react"; import { memo, useState } from "react"; import { BaseExecutionNode } from "../base-execution-node"; import { OpenAiDialog, OpenAiFormValues } from "./dialog"; -import { useNodeStatus } from "../../hooks/use-node-status"; -import { fetchOpenAiRealtimeToken } from "./actions"; -import { OPENAI_CHANNEL_NAME } from "@/inngest/channels/openai"; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; type OpenAiNodeData = { variableName?: string; @@ -14,42 +12,26 @@ type OpenAiNodeData = { systemPrompt?: string; userPrompt?: string; }; - type OpenAiNodeType = Node; export const OpenAiNode = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); const { setNodes } = useReactFlow(); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: OPENAI_CHANNEL_NAME, - topic: "status", - refreshToken: fetchOpenAiRealtimeToken, - }); - + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); - const handleSubmit = (values: OpenAiFormValues) => { - setNodes((nodes) => nodes.map((node) => { - if (node.id === props.id) { - return { - ...node, - data: { - ...node.data, - ...values, - } - } - } - return node; - })) + setNodes((nodes) => + nodes.map((node) => + node.id === props.id + ? { ...node, data: { ...node.data, ...values } } + : node, + ), + ); }; - const nodeData = props.data; const description = nodeData?.userPrompt ? `gpt-4: ${nodeData.userPrompt.slice(0, 50)}...` : "Not configured"; - return ( <> ) => { id={props.id} icon="/logos/openai.svg" name="OpenAi" - status={nodeStatus} + status={status} description={description} onSettings={handleOpenSettings} onDoubleClick={handleOpenSettings} /> - ) + ); }); - OpenAiNode.displayName = "OpenAiNode"; diff --git a/src/features/executions/components/slack/actions.ts b/src/features/executions/components/slack/actions.ts index eed6053..a19108b 100644 --- a/src/features/executions/components/slack/actions.ts +++ b/src/features/executions/components/slack/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { slackChannel } from "@/inngest/channels/slack"; -import { inngest } from "@/inngest/client"; - -export type SlackToken = Realtime.Token< - typeof slackChannel, - ["status"] ->; - -export async function fetchSlackRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: slackChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/executions/components/slack/executor.ts b/src/features/executions/components/slack/executor.ts index ce573c2..b5edda9 100644 --- a/src/features/executions/components/slack/executor.ts +++ b/src/features/executions/components/slack/executor.ts @@ -1,101 +1,4 @@ -import Handlebars from "handlebars"; -import { decode } from "html-entities"; -import { NonRetriableError } from "inngest"; import type { NodeExecutor } from "@/features/executions/types"; -import { slackChannel } from "@/inngest/channels/slack"; -import ky from "ky"; -Handlebars.registerHelper("json", (context) => { - const jsonString = JSON.stringify(context, null, 2); - const safeString = new Handlebars.SafeString(jsonString); - - return safeString; -}); - -type SlackData = { - variableName?: string; - webhookUrl?: string; - content?: string; -}; - -export const slackExecutor: NodeExecutor = async ({ - data, - nodeId, - context, - step, - publish, -}) => { - await publish( - slackChannel().status({ - nodeId, - status: "loading", - }), - ); - - if (!data.content) { - await publish( - slackChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("Slack node: Message content is required"); - } - - const rawContent = Handlebars.compile(data.content)(context); - const content = decode(rawContent); - - try { - const result = await step.run("slack-webhook", async () => { - if (!data.webhookUrl) { - await publish( - slackChannel().status({ - nodeId, - status: "error", - }), - ); - throw new NonRetriableError("Slack node: Webhook URL is required"); - } - - await ky.post(data.webhookUrl, { - json: { - content: content, // The key depends on workflow config - }, - }); - - if (!data.variableName) { - await publish( - slackChannel().status({ - nodeId, - status: "error", - }) - ); - throw new NonRetriableError("Slack node: Variable name is missing"); - } - - return { - ...context, - [data.variableName]: { - messageContent: content.slice(0, 2000), - }, - }; - }); - - await publish( - slackChannel().status({ - nodeId, - status: "success", - }), - ); - - return result; - } catch (error) { - await publish( - slackChannel().status({ - nodeId, - status: "error", - }), - ); - throw error; - } -}; +// TODO: Implement Slack executor via custom backend API +export const slackExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/executions/components/slack/node.tsx b/src/features/executions/components/slack/node.tsx index 99a34b4..6d54647 100644 --- a/src/features/executions/components/slack/node.tsx +++ b/src/features/executions/components/slack/node.tsx @@ -4,51 +4,33 @@ import { useReactFlow, type Node, type NodeProps } from "@xyflow/react"; import { memo, useState } from "react"; import { BaseExecutionNode } from "../base-execution-node"; import { SlackDialog, SlackFormValues } from "./dialog"; -import { useNodeStatus } from "../../hooks/use-node-status"; -import { fetchSlackRealtimeToken } from "./actions"; -import { SLACK_CHANNEL_NAME } from "@/inngest/channels/slack"; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; type SlackNodeData = { webhookUrl?: string; content?: string; username?: string; }; - type SlackNodeType = Node; export const SlackNode = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); const { setNodes } = useReactFlow(); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: SLACK_CHANNEL_NAME, - topic: "status", - refreshToken: fetchSlackRealtimeToken, - }); - + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); - const handleSubmit = (values: SlackFormValues) => { - setNodes((nodes) => nodes.map((node) => { - if (node.id === props.id) { - return { - ...node, - data: { - ...node.data, - ...values, - } - } - } - return node; - })) + setNodes((nodes) => + nodes.map((node) => + node.id === props.id + ? { ...node, data: { ...node.data, ...values } } + : node, + ), + ); }; - const nodeData = props.data; const description = nodeData?.content ? `Send: ${nodeData.content.slice(0, 50)}...` : "Not configured"; - return ( <> ) => { id={props.id} icon="/logos/slack.svg" name="Slack" - status={nodeStatus} + status={status} description={description} onSettings={handleOpenSettings} onDoubleClick={handleOpenSettings} /> - ) + ); }); - SlackNode.displayName = "SlackNode"; diff --git a/src/features/executions/hooks/use-executions.ts b/src/features/executions/hooks/use-executions.ts index b4c73f0..cf98e96 100644 --- a/src/features/executions/hooks/use-executions.ts +++ b/src/features/executions/hooks/use-executions.ts @@ -1,22 +1,23 @@ -import { useTRPC } from "@/trpc/client" -import { useSuspenseQuery } from "@tanstack/react-query"; import { useExecutionsParams } from "./use-executions-params"; -/** - * Hook to fetch all executions using suspense - */ -export const useSuspenseExecutions = () => { - const trpc = useTRPC(); - const [params] = useExecutionsParams(); - - return useSuspenseQuery(trpc.executions.getMany.queryOptions(params)); +// Stubbed types matching the original API shape +// TODO: Replace with real API calls when custom backend is ready +export type Execution = { + id: string; + workflowId: string; + status: "RUNNING" | "SUCCESS" | "FAILED"; + startedAt: Date; + completedAt: Date | null; + error: string | null; + output: unknown; }; -/** - * Hook to fetch a single execution using suspense - */ -export const useSuspenseExecution = (id: string) => { - const trpc = useTRPC(); - return useSuspenseQuery(trpc.executions.getOne.queryOptions({ id })); +export const useSuspenseExecutions = () => { + const [params] = useExecutionsParams(); + void params; + return { data: { items: [] as Execution[], total: 0 } }; }; +export const useSuspenseExecution = (_id: string) => ({ + data: null as Execution | null, +}); diff --git a/src/features/executions/hooks/use-node-status.ts b/src/features/executions/hooks/use-node-status.ts index 6b184b3..7c4f25b 100644 --- a/src/features/executions/hooks/use-node-status.ts +++ b/src/features/executions/hooks/use-node-status.ts @@ -1,55 +1,13 @@ -import type { Realtime } from "@inngest/realtime"; -import { useInngestSubscription } from "@inngest/realtime/hooks"; -import { useEffect, useState } from "react"; -import type { NodeStatus } from "@/components/react-flow/node-status-indicator"; +// Stub use-node-status hook — inngest/realtime removed +// TODO: Replace with custom backend SSE/WebSocket when implementing execution status streaming -interface UseNodeStatusOptions { - nodeId: string; - channel: string; - topic: string; - refreshToken: () => Promise; -}; - -export function useNodeStatus({ - nodeId, - channel, - topic, - refreshToken, -}: UseNodeStatusOptions) { - const [status, setStatus] = useState("initial"); - - const { data } = useInngestSubscription({ - refreshToken, - enabled: true, - }); +export type NodeStatus = "idle" | "loading" | "success" | "error"; - useEffect(() => { - if (!data?.length) { - return; - } - - // Find the latest message for this node - const latestMessage = data - .filter( - (msg) => - msg.kind === "data" && - msg.channel === channel && - msg.topic === topic && - msg.data.nodeId === nodeId, - ) - .sort((a, b) => { - if (a.kind === "data" && b.kind === "data") { - return ( - new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() - ); - } - return 0; - })[0]; - - if (latestMessage?.kind === "data") { - setStatus(latestMessage.data.status as NodeStatus); - } - }, [data, nodeId, channel, topic]); - - return status; +export const useNodeStatus = (_params: { + nodeId: string; + channel?: string; + topic?: string; +}): NodeStatus => { + // Real-time status tracking will be re-implemented with custom backend SSE or WebSocket + return "idle"; }; diff --git a/src/features/executions/lib/executor-registry.ts b/src/features/executions/lib/executor-registry.ts index 4575e55..66ef157 100644 --- a/src/features/executions/lib/executor-registry.ts +++ b/src/features/executions/lib/executor-registry.ts @@ -1,4 +1,4 @@ -import { NodeType } from "@/generated/prisma"; +import { NodeType } from "@/config/constants"; import { NodeExecutor } from "../types"; import { manualTriggerExecutor } from "@/features/triggers/components/manual-trigger/executor"; import { httpRequestExecutor } from "../components/http-request/executor"; diff --git a/src/features/executions/server/params-loader.ts b/src/features/executions/server/params-loader.ts deleted file mode 100644 index a2fc40e..0000000 --- a/src/features/executions/server/params-loader.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createLoader } from "nuqs/server"; -import { executionsParams } from "../params"; - -export const executionsParamsLoader = createLoader(executionsParams); diff --git a/src/features/executions/server/prefetch.ts b/src/features/executions/server/prefetch.ts deleted file mode 100644 index 1f97eaf..0000000 --- a/src/features/executions/server/prefetch.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { inferInput } from "@trpc/tanstack-react-query"; -import { prefetch, trpc } from "@/trpc/server"; - -type Input = inferInput; - -/** - * Prefetch all executions - */ -export const prefetchExecutions = (params: Input) => { - return prefetch(trpc.executions.getMany.queryOptions(params)); -}; - -/** - * Prefetch a single execution - */ -export const prefetchExecution = (id: string) => { - return prefetch(trpc.executions.getOne.queryOptions({ id })); -}; diff --git a/src/features/executions/server/routers.ts b/src/features/executions/server/routers.ts deleted file mode 100644 index 42a540a..0000000 --- a/src/features/executions/server/routers.ts +++ /dev/null @@ -1,85 +0,0 @@ -import prisma from "@/lib/db"; -import { createTRPCRouter, protectedProcedure } from "@/trpc/init"; -import z from "zod"; -import { PAGINATION } from "@/config/constants"; - -export const executionsRouter = createTRPCRouter({ - getOne: protectedProcedure - .input(z.object({ id: z.string() })) - .query(({ ctx, input }) => { - return prisma.execution.findUniqueOrThrow({ - where: { - id: input.id, - workflow: { - userId: ctx.auth.user.id - } - }, - include: { - workflow: { - select: { - id: true, - name: true, - }, - }, - } - }); - }), - getMany: protectedProcedure - .input( - z.object({ - page: z.number().default(PAGINATION.DEFAULT_PAGE), - pageSize: z - .number() - .min(PAGINATION.MIN_PAGE_SIZE) - .max(PAGINATION.MAX_PAGE_SIZE) - .default(PAGINATION.DEFAULT_PAGE_SIZE), - }) - ) - .query(async ({ ctx, input }) => { - const { page, pageSize } = input; - - const [items, totalCount] = await Promise.all([ - prisma.execution.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - where: { - workflow: { - userId: ctx.auth.user.id, - }, - }, - orderBy: { - startedAt: "desc", - }, - include: { - workflow: { - select: { - id: true, - name: true, - }, - }, - }, - }), - prisma.execution.count({ - where: { - workflow: { - userId: ctx.auth.user.id, - }, - }, - }), - ]); - - const totalPages = Math.ceil(totalCount / pageSize); - const hasNextPage = page < totalPages; - const hasPreviousPage = page > 1; - - return { - items, - page, - pageSize, - totalCount, - totalPages, - hasNextPage, - hasPreviousPage, - }; - }), -}); diff --git a/src/features/executions/types.ts b/src/features/executions/types.ts index 47572cb..eef4bb2 100644 --- a/src/features/executions/types.ts +++ b/src/features/executions/types.ts @@ -1,17 +1,14 @@ -import type { Realtime } from "@inngest/realtime"; -import type { GetStepTools, Inngest } from "inngest"; - +// Stubbed types — inngest/realtime removed +// TODO: Replace with custom backend realtime types when implementing execution status streaming export type WorkflowContext = Record; -export type StepTools = GetStepTools; - +// Simplified NodeExecutor type without inngest step/publish parameters export interface NodeExecutorParams> { data: TData; nodeId: string; - userId: string; + userId?: string; context: WorkflowContext; - step: StepTools; - publish: Realtime.PublishFn; + // step and publish removed — re-add when custom backend realtime is integrated }; export type NodeExecutor> = ( diff --git a/src/features/subscriptions/hooks/use-subscription.ts b/src/features/subscriptions/hooks/use-subscription.ts index aa30f2c..779e9a8 100644 --- a/src/features/subscriptions/hooks/use-subscription.ts +++ b/src/features/subscriptions/hooks/use-subscription.ts @@ -1,28 +1,13 @@ -import { useQuery } from "@tanstack/react-query"; -import { authClient } from "@/lib/auth-client"; - -export const useSubscription = () => { - return useQuery({ - queryKey: ["subscription"], - queryFn: async () => { - const { data } = await authClient.customer.state(); - return data; - }, - }); -}; - -export const useHasActiveSubscription = () => { - const { data: customerState, isLoading, ...rest } = - useSubscription(); - - const hasActiveSubscription = - customerState?.activeSubscriptions && - customerState.activeSubscriptions.length > 0; - - return { - hasActiveSubscription, - subscription: customerState?.activeSubscriptions?.[0], - isLoading, - ...rest, - }; -}; +// Stubbed subscription hook — returns no active subscription +// TODO: Replace with real call to custom backend billing API +export const useSubscription = () => ({ + data: null, + isLoading: false, + error: null, +}); + +export const useHasActiveSubscription = () => ({ + hasActiveSubscription: false, + subscription: undefined, + isLoading: false, +}); diff --git a/src/features/triggers/components/google-form-trigger/actions.ts b/src/features/triggers/components/google-form-trigger/actions.ts index 1fe20d6..a19108b 100644 --- a/src/features/triggers/components/google-form-trigger/actions.ts +++ b/src/features/triggers/components/google-form-trigger/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { googleFormTriggerChannel } from "@/inngest/channels/google-form-trigger"; -import { inngest } from "@/inngest/client"; - -export type GoogleFormTriggerToken = Realtime.Token< - typeof googleFormTriggerChannel, - ["status"] ->; - -export async function fetchGoogleFormTriggerRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: googleFormTriggerChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/triggers/components/google-form-trigger/dialog.tsx b/src/features/triggers/components/google-form-trigger/dialog.tsx index 72ff80c..d92efb8 100644 --- a/src/features/triggers/components/google-form-trigger/dialog.tsx +++ b/src/features/triggers/components/google-form-trigger/dialog.tsx @@ -18,19 +18,18 @@ import { generateGoogleFormScript } from "./utils"; interface Props { open: boolean; onOpenChange: (open: boolean) => void; -}; +} -export const GoogleFormTriggerDialog = ({ - open, - onOpenChange -}: Props) => { +export const GoogleFormTriggerDialog = ({ open, onOpenChange }: Props) => { const params = useParams(); const workflowId = params.workflowId as string; - // Construct the webhook URL - const baseUrl = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000" - const webhookUrl = - `${baseUrl}/api/webhooks/google-form?workflowId=${workflowId}`; + // Construct the webhook URL (points to the backend, via public tunnel in dev) + const baseUrl = + process.env.NEXT_PUBLIC_WEBHOOK_URL || + process.env.NEXT_PUBLIC_API_URL || + "http://localhost:4000"; + const webhookUrl = `${baseUrl}/api/webhooks/google-form?workflowId=${workflowId}`; const copyToClipboard = async () => { try { @@ -53,9 +52,7 @@ export const GoogleFormTriggerDialog = ({
- +
; - -export const googleFormTriggerExecutor: NodeExecutor = async ({ - nodeId, - context, - step, - publish, -}) => { - await publish( - googleFormTriggerChannel().status({ - nodeId, - status: "loading", - }), - ); - - const result = await step.run("google-form-trigger", async () => context); - - await publish( - googleFormTriggerChannel().status({ - nodeId, - status: "success", - }), - ); - - return result; -}; +// TODO: Implement Google Form trigger via custom backend webhook +export const googleFormTriggerExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/triggers/components/google-form-trigger/node.tsx b/src/features/triggers/components/google-form-trigger/node.tsx index 53e6da6..8010bec 100644 --- a/src/features/triggers/components/google-form-trigger/node.tsx +++ b/src/features/triggers/components/google-form-trigger/node.tsx @@ -1,38 +1,27 @@ +"use client"; + import { NodeProps } from "@xyflow/react"; import { memo, useState } from "react"; import { BaseTriggerNode } from "../base-trigger-node"; import { GoogleFormTriggerDialog } from "./dialog"; -import { useNodeStatus } from "@/features/executions/hooks/use-node-status"; -import { fetchGoogleFormTriggerRealtimeToken } from "./actions"; -import { GOOGLE_FORM_TRIGGER_CHANNEL_NAME } from "@/inngest/channels/google-form-trigger"; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; export const GoogleFormTrigger = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: GOOGLE_FORM_TRIGGER_CHANNEL_NAME, - topic: "status", - refreshToken: fetchGoogleFormTriggerRealtimeToken, - }); - + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); - return ( <> - + - ) + ); }); diff --git a/src/features/triggers/components/manual-trigger/actions.ts b/src/features/triggers/components/manual-trigger/actions.ts index d3d4606..a19108b 100644 --- a/src/features/triggers/components/manual-trigger/actions.ts +++ b/src/features/triggers/components/manual-trigger/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { manualTriggerChannel } from "@/inngest/channels/manual-trigger"; -import { inngest } from "@/inngest/client"; - -export type ManualTriggerToken = Realtime.Token< - typeof manualTriggerChannel, - ["status"] ->; - -export async function fetchManualTriggerRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: manualTriggerChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/triggers/components/manual-trigger/executor.ts b/src/features/triggers/components/manual-trigger/executor.ts index 25e3524..b60de89 100644 --- a/src/features/triggers/components/manual-trigger/executor.ts +++ b/src/features/triggers/components/manual-trigger/executor.ts @@ -1,29 +1,4 @@ import type { NodeExecutor } from "@/features/executions/types"; -import { manualTriggerChannel } from "@/inngest/channels/manual-trigger"; -type ManualTriggerData = Record; - -export const manualTriggerExecutor: NodeExecutor = async ({ - nodeId, - context, - step, - publish, -}) => { - await publish( - manualTriggerChannel().status({ - nodeId, - status: "loading", - }), - ); - - const result = await step.run("manual-trigger", async () => context); - - await publish( - manualTriggerChannel().status({ - nodeId, - status: "success", - }), - ); - - return result; -}; +// TODO: Implement manual trigger via custom backend websocket/SSE +export const manualTriggerExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/triggers/components/manual-trigger/node.tsx b/src/features/triggers/components/manual-trigger/node.tsx index 29ebb7b..7c65f32 100644 --- a/src/features/triggers/components/manual-trigger/node.tsx +++ b/src/features/triggers/components/manual-trigger/node.tsx @@ -1,38 +1,28 @@ +"use client"; + import { NodeProps } from "@xyflow/react"; import { memo, useState } from "react"; import { BaseTriggerNode } from "../base-trigger-node"; import { MousePointerIcon } from "lucide-react"; import { ManualTriggerDialog } from "./dialog"; -import { useNodeStatus } from "@/features/executions/hooks/use-node-status"; -import { MANUAL_TRIGGER_CHANNEL_NAME } from "@/inngest/channels/manual-trigger"; -import { fetchManualTriggerRealtimeToken } from "./actions"; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; export const ManualTriggerNode = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: MANUAL_TRIGGER_CHANNEL_NAME, - topic: "status", - refreshToken: fetchManualTriggerRealtimeToken, - }); - + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); return ( <> - + - ) + ); }); diff --git a/src/features/triggers/components/stripe-trigger/actions.ts b/src/features/triggers/components/stripe-trigger/actions.ts index ee14a54..a19108b 100644 --- a/src/features/triggers/components/stripe-trigger/actions.ts +++ b/src/features/triggers/components/stripe-trigger/actions.ts @@ -1,19 +1,5 @@ -"use server"; - -import { getSubscriptionToken, type Realtime } from "@inngest/realtime"; -import { stripeTriggerChannel } from "@/inngest/channels/stripe-trigger"; -import { inngest } from "@/inngest/client"; - -export type StripeTriggerToken = Realtime.Token< - typeof stripeTriggerChannel, - ["status"] ->; - -export async function fetchStripeTriggerRealtimeToken(): Promise { - const token = await getSubscriptionToken(inngest, { - channel: stripeTriggerChannel(), - topics: ["status"], - }); - - return token; -}; +// Server actions removed — inngest/realtime integration pending custom backend +// TODO: Replace with REST API calls to custom backend when ready +export async function fetchRealtimeToken() { + return null; +} diff --git a/src/features/triggers/components/stripe-trigger/dialog.tsx b/src/features/triggers/components/stripe-trigger/dialog.tsx index a772d5a..cf33c7a 100644 --- a/src/features/triggers/components/stripe-trigger/dialog.tsx +++ b/src/features/triggers/components/stripe-trigger/dialog.tsx @@ -17,19 +17,18 @@ import { toast } from "sonner"; interface Props { open: boolean; onOpenChange: (open: boolean) => void; -}; +} -export const StripeTriggerDialog = ({ - open, - onOpenChange -}: Props) => { +export const StripeTriggerDialog = ({ open, onOpenChange }: Props) => { const params = useParams(); const workflowId = params.workflowId as string; - // Construct the webhook URL - const baseUrl = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000" - const webhookUrl = - `${baseUrl}/api/webhooks/stripe?workflowId=${workflowId}`; + // Construct the webhook URL (points to the backend, via public tunnel in dev) + const baseUrl = + process.env.NEXT_PUBLIC_WEBHOOK_URL || + process.env.NEXT_PUBLIC_API_URL || + "http://localhost:4000"; + const webhookUrl = `${baseUrl}/api/webhooks/stripe?workflowId=${workflowId}`; const copyToClipboard = async () => { try { @@ -46,14 +45,13 @@ export const StripeTriggerDialog = ({ Stripe Trigger Configuration - Configure this webhook URL in your Stripe Dashboard to trigger this workflow on payment events. + Configure this webhook URL in your Stripe Dashboard to trigger this + workflow on payment events.
- +
Go to Developers → Webhooks
  • Click "Add endpoint"
  • Paste the webhook URL above
  • -
  • Select events to listen for (e.g., payment_intent.succeeded)
  • +
  • + Select events to listen for (e.g., payment_intent.succeeded) +
  • Save and copy the signing secret
  • @@ -87,11 +87,36 @@ export const StripeTriggerDialog = ({

    Available Variables

      -
    • {"{{stripe.amount}}"} - Payment amount
    • -
    • {"{{stripe.currency}}"} - Currency code
    • -
    • {"{{stripe.customerId}}"} - Customer ID
    • -
    • {"{{json stripe}}"} - Full event data as JSON
    • -
    • {"{{stripe.eventType}}"} - Event type (e.g., payment_intent.succeeded)
    • +
    • + + {"{{stripe.amount}}"} + {" "} + - Payment amount +
    • +
    • + + {"{{stripe.currency}}"} + {" "} + - Currency code +
    • +
    • + + {"{{stripe.customerId}}"} + {" "} + - Customer ID +
    • +
    • + + {"{{json stripe}}"} + {" "} + - Full event data as JSON +
    • +
    • + + {"{{stripe.eventType}}"} + {" "} + - Event type (e.g., payment_intent.succeeded) +
    diff --git a/src/features/triggers/components/stripe-trigger/executor.ts b/src/features/triggers/components/stripe-trigger/executor.ts index dee2263..b51a4a8 100644 --- a/src/features/triggers/components/stripe-trigger/executor.ts +++ b/src/features/triggers/components/stripe-trigger/executor.ts @@ -1,29 +1,4 @@ import type { NodeExecutor } from "@/features/executions/types"; -import { stripeTriggerChannel } from "@/inngest/channels/stripe-trigger"; -type StripeTriggerData = Record; - -export const stripeTriggerExecutor: NodeExecutor = async ({ - nodeId, - context, - step, - publish, -}) => { - await publish( - stripeTriggerChannel().status({ - nodeId, - status: "loading", - }), - ); - - const result = await step.run("stripe-trigger", async () => context); - - await publish( - stripeTriggerChannel().status({ - nodeId, - status: "success", - }), - ); - - return result; -}; +// TODO: Implement Stripe trigger via custom backend webhook +export const stripeTriggerExecutor: NodeExecutor = async ({ context }) => context; diff --git a/src/features/triggers/components/stripe-trigger/node.tsx b/src/features/triggers/components/stripe-trigger/node.tsx index 494786d..1b85e22 100644 --- a/src/features/triggers/components/stripe-trigger/node.tsx +++ b/src/features/triggers/components/stripe-trigger/node.tsx @@ -1,38 +1,27 @@ +"use client"; + import { NodeProps } from "@xyflow/react"; import { memo, useState } from "react"; import { BaseTriggerNode } from "../base-trigger-node"; import { StripeTriggerDialog } from "./dialog"; -import { useNodeStatus } from "@/features/executions/hooks/use-node-status"; -import { fetchStripeTriggerRealtimeToken } from "./actions"; -import { STRIPE_TRIGGER_CHANNEL_NAME } from "@/inngest/channels/stripe-trigger"; +import { useNodeExecutionStatus } from "@/features/editor/hooks/use-node-status"; export const StripeTriggerNode = memo((props: NodeProps) => { const [dialogOpen, setDialogOpen] = useState(false); - - const nodeStatus = useNodeStatus({ - nodeId: props.id, - channel: STRIPE_TRIGGER_CHANNEL_NAME, - topic: "status", - refreshToken: fetchStripeTriggerRealtimeToken, - }); - + const status = useNodeExecutionStatus(props.id); const handleOpenSettings = () => setDialogOpen(true); - return ( <> - + - ) + ); }); diff --git a/src/features/workflows/components/workflows.tsx b/src/features/workflows/components/workflows.tsx index 99a7f65..63fc93c 100644 --- a/src/features/workflows/components/workflows.tsx +++ b/src/features/workflows/components/workflows.tsx @@ -1,24 +1,30 @@ "use client"; import { formatDistanceToNow } from "date-fns"; -import { +import { EmptyView, - EntityContainer, - EntityHeader, - EntityItem, - EntityList, - EntityPagination, + EntityContainer, + EntityHeader, + EntityItem, + EntityList, + EntityPagination, EntitySearch, ErrorView, - LoadingView } from "@/components/entity-components"; -import { useCreateWorkflow, useRemoveWorkflow, useSuspenseWorkflows } from "../hooks/use-workflows" +import { + useCreateWorkflow, + useRemoveWorkflow, + useSuspenseWorkflows, +} from "../hooks/use-workflows"; import { useUpgradeModal } from "@/hooks/use-upgrade-modal"; import { useRouter } from "next/navigation"; import { useWorkflowsParams } from "../hooks/use-workflows-params"; import { useEntitySearch } from "@/hooks/use-entity-search"; -import type { Workflow } from "@/generated/prisma"; +import type { Workflow } from "../hooks/use-workflows"; import { WorkflowIcon } from "lucide-react"; +import { Skeleton } from "@/components/ui/skeleton"; +import { Card, CardContent } from "@/components/ui/card"; +import { PAGINATION } from "@/config/constants"; export const WorkflowsSearch = () => { const [params, setParams] = useWorkflowsParams(); @@ -36,17 +42,43 @@ export const WorkflowsSearch = () => { ); }; +/** Skeleton placeholder for a single workflow card. */ +const WorkflowItemSkeleton = () => ( + + +
    + +
    + + +
    +
    +
    +
    +); + +/** Skeleton list shown while workflows are loading. */ +export const WorkflowsListSkeleton = () => ( +
    + {Array.from({ length: 3 }).map((_, i) => ( + + ))} +
    +); + export const WorkflowsList = () => { - const workflows = useSuspenseWorkflows(); + const { data, isLoading } = useSuspenseWorkflows(); + + if (isLoading) return ; return ( workflow.id} renderItem={(workflow) => } emptyView={} /> - ) + ); }; export const WorkflowsHeader = ({ disabled }: { disabled?: boolean }) => { @@ -55,15 +87,9 @@ export const WorkflowsHeader = ({ disabled }: { disabled?: boolean }) => { const { handleError, modal } = useUpgradeModal(); const handleCreate = () => { - createWorkflow.mutate(undefined, { - onSuccess: (data) => { - router.push(`/workflows/${data.id}`); - }, - onError: (error) => { - handleError(error); - }, - }); - } + createWorkflow.mutate({ name: "Untitled Workflow" }); + // TODO: Redirect to new workflow when backend returns created ID + }; return ( <> @@ -81,21 +107,24 @@ export const WorkflowsHeader = ({ disabled }: { disabled?: boolean }) => { }; export const WorkflowsPagination = () => { - const workflows = useSuspenseWorkflows(); + const { data, isLoading } = useSuspenseWorkflows(); const [params, setParams] = useWorkflowsParams(); + const pageSize = params.pageSize || PAGINATION.DEFAULT_PAGE_SIZE; + const totalPages = Math.max(1, Math.ceil(data.total / pageSize)); + return ( setParams({ ...params, page })} /> ); }; export const WorkflowsContainer = ({ - children + children, }: { children: React.ReactNode; }) => { @@ -111,7 +140,7 @@ export const WorkflowsContainer = ({ }; export const WorkflowsLoading = () => { - return ; + return ; }; export const WorkflowsError = () => { @@ -124,14 +153,8 @@ export const WorkflowsEmpty = () => { const { handleError, modal } = useUpgradeModal(); const handleCreate = () => { - createWorkflow.mutate(undefined, { - onError: (error) => { - handleError(error); - }, - onSuccess: (data) => { - router.push(`/workflows/${data.id}`); - } - }); + createWorkflow.mutate({ name: "Untitled Workflow" }); + // TODO: Redirect to new workflow when backend returns created ID }; return ( @@ -145,16 +168,12 @@ export const WorkflowsEmpty = () => { ); }; -export const WorkflowItem = ({ - data, -}: { - data: Workflow -}) => { +export const WorkflowItem = ({ data }: { data: Workflow }) => { const removeWorkflow = useRemoveWorkflow(); const handleRemove = () => { removeWorkflow.mutate({ id: data.id }); - } + }; return ( - ) -} \ No newline at end of file + ); +}; diff --git a/src/features/workflows/hooks/use-workflows.ts b/src/features/workflows/hooks/use-workflows.ts index fffe677..200601e 100644 --- a/src/features/workflows/hooks/use-workflows.ts +++ b/src/features/workflows/hooks/use-workflows.ts @@ -1,132 +1,307 @@ -import { useTRPC } from "@/trpc/client" -import { useMutation, useQueryClient, useSuspenseQuery } from "@tanstack/react-query"; +"use client"; + +import { useCallback, useEffect, useState } from "react"; +import { useAtom } from "jotai"; +import { useRouter } from "next/navigation"; import { toast } from "sonner"; import { useWorkflowsParams } from "./use-workflows-params"; +import { + workflowsAtom, + workflowsTotalAtom, + workflowsLoadingAtom, +} from "../store/workflow-atoms"; +import * as workflowsApi from "@/api/workflows"; +import type { ApiWorkflow, ApiNode, ApiConnection } from "@/api/workflows"; +import type { Node, Edge } from "@xyflow/react"; + +// ─── Types ────────────────────────────────────────────────── + +export type Workflow = { + id: string; + name: string; + createdAt: Date; + updatedAt: Date; + nodes?: Node[]; + connections?: ApiConnection[]; +}; + +/** Map a backend workflow row to the frontend shape. */ +const mapWorkflow = (w: ApiWorkflow): Workflow => ({ + id: w.id, + name: w.name, + createdAt: new Date(w.created_at), + updatedAt: new Date(w.updated_at), + nodes: w.nodes?.map(mapNodeToReactFlow), + connections: w.connections, +}); + +/** Map a backend node row to a React Flow Node. */ +const mapNodeToReactFlow = (n: ApiNode): Node => ({ + id: n.id, + type: n.type, + position: n.position ?? { x: 0, y: 0 }, + data: { ...n.data, name: n.name, credentialId: n.credential_id }, +}); + +/** Map backend connections to React Flow edges. */ +const mapConnectionsToEdges = (conns: ApiConnection[]): Edge[] => + conns.map((c) => ({ + id: c.id, + source: c.from_node_id, + target: c.to_node_id, + sourceHandle: c.from_output || undefined, + targetHandle: c.to_input || undefined, + })); -/** - * Hook to fetch all workflows using suspense - */ +// ─── List Hook ────────────────────────────────────────────── + +/** Fetch and cache the paginated workflows list. */ export const useSuspenseWorkflows = () => { - const trpc = useTRPC(); const [params] = useWorkflowsParams(); - - return useSuspenseQuery(trpc.workflows.getMany.queryOptions(params)); + const [items, setItems] = useAtom(workflowsAtom); + const [total, setTotal] = useAtom(workflowsTotalAtom); + const [isLoading, setIsLoading] = useAtom(workflowsLoadingAtom); + + useEffect(() => { + let cancelled = false; + setIsLoading(true); + + workflowsApi + .getWorkflows({ page: params.page, pageSize: params.pageSize }) + .then((res) => { + if (cancelled) return; + setItems(res.workflows.map(mapWorkflow)); + setTotal(res.total); + }) + .catch(() => { + if (!cancelled) toast.error("Failed to load workflows"); + }) + .finally(() => { + if (!cancelled) setIsLoading(false); + }); + + return () => { cancelled = true; }; + }, [params.page, params.pageSize, setItems, setTotal, setIsLoading]); + + return { data: { items, total }, isLoading }; }; -/** - * Hook to create a new workflow - */ +// ─── Single Workflow Hook ─────────────────────────────────── + +/** Fetch a single workflow by ID (with nodes + connections). */ +export const useSuspenseWorkflow = (id: string) => { + const [data, setData] = useState<(Workflow & { edges?: Edge[] }) | null>(null); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + let cancelled = false; + setIsLoading(true); + + workflowsApi + .getWorkflow(id) + .then((raw) => { + if (cancelled) return; + const mapped = mapWorkflow(raw); + setData({ + ...mapped, + edges: raw.connections ? mapConnectionsToEdges(raw.connections) : [], + }); + }) + .catch(() => { + if (!cancelled) toast.error("Failed to load workflow"); + }) + .finally(() => { + if (!cancelled) setIsLoading(false); + }); + + return () => { cancelled = true; }; + }, [id]); + + return { data, isLoading }; +}; + +// ─── Mutations ────────────────────────────────────────────── + +/** Create a workflow and navigate to the editor. */ export const useCreateWorkflow = () => { - const queryClient = useQueryClient(); - const trpc = useTRPC(); - - return useMutation( - trpc.workflows.create.mutationOptions({ - onSuccess: (data) => { - toast.success(`Workflow "${data.name}" created`); - queryClient.invalidateQueries( - trpc.workflows.getMany.queryOptions({}), - ); - }, - onError: (error) => { - toast.error(`Failed to create workflow: ${error.message}`); - }, - }), + const [isPending, setIsPending] = useState(false); + const [, setItems] = useAtom(workflowsAtom); + const router = useRouter(); + + const mutateAsync = useCallback( + async (input: { name: string }) => { + setIsPending(true); + try { + const raw = await workflowsApi.createWorkflow(input); + const mapped = mapWorkflow(raw); + setItems((prev) => [mapped, ...prev]); + toast.success("Workflow created"); + router.push(`/workflows/${mapped.id}`); + return mapped; + } catch { + toast.error("Failed to create workflow"); + throw new Error("Failed to create workflow"); + } finally { + setIsPending(false); + } + }, + [setItems, router], ); + + const mutate = useCallback( + (input: { name: string }) => { mutateAsync(input).catch(() => { }); }, + [mutateAsync], + ); + + return { mutate, mutateAsync, isPending }; }; -/** - * Hook to remove a workflow - */ +/** Optimistically remove a workflow from the list. */ export const useRemoveWorkflow = () => { - const trpc = useTRPC(); - const queryClient = useQueryClient(); - - return useMutation( - trpc.workflows.remove.mutationOptions({ - onSuccess: (data) => { - toast.success(`Workflow "${data.name}" removed`); - queryClient.invalidateQueries(trpc.workflows.getMany.queryOptions({})); - queryClient.invalidateQueries( - trpc.workflows.getOne.queryFilter({ id: data.id }), - ); + const [isPending, setIsPending] = useState(false); + const [, setItems] = useAtom(workflowsAtom); + + const mutateAsync = useCallback( + async (input: { id: string }) => { + setIsPending(true); + let snapshot: Workflow[] = []; + + // Optimistic remove + setItems((prev) => { + snapshot = prev; + return prev.filter((w) => w.id !== input.id); + }); + + try { + await workflowsApi.deleteWorkflow(input.id); + toast.success("Workflow deleted"); + } catch { + setItems(snapshot); // rollback + toast.error("Failed to delete workflow"); + } finally { + setIsPending(false); } - }) - ) -} + }, + [setItems], + ); -/** - * Hook to fetch a single workflow using suspense - */ -export const useSuspenseWorkflow = (id: string) => { - const trpc = useTRPC(); - return useSuspenseQuery(trpc.workflows.getOne.queryOptions({ id })); + const mutate = useCallback( + (input: { id: string }) => { mutateAsync(input).catch(() => { }); }, + [mutateAsync], + ); + + return { mutate, mutateAsync, isPending }; }; -/** - * Hook to update a workflow name - */ +/** Rename a workflow. */ export const useUpdateWorkflowName = () => { - const queryClient = useQueryClient(); - const trpc = useTRPC(); - - return useMutation( - trpc.workflows.updateName.mutationOptions({ - onSuccess: (data) => { - toast.success(`Workflow "${data.name}" updated`); - queryClient.invalidateQueries( - trpc.workflows.getMany.queryOptions({}), - ); - queryClient.invalidateQueries( - trpc.workflows.getOne.queryOptions({ id: data.id }), + const [isPending, setIsPending] = useState(false); + const [, setItems] = useAtom(workflowsAtom); + + const mutateAsync = useCallback( + async (input: { id: string; name: string }) => { + setIsPending(true); + try { + const raw = await workflowsApi.updateWorkflowName(input.id, input.name); + const mapped = mapWorkflow(raw); + + // Update the item in the list cache + setItems((prev) => + prev.map((w) => (w.id === input.id ? { ...w, name: mapped.name, updatedAt: mapped.updatedAt } : w)), ); - }, - onError: (error) => { - toast.error(`Failed to update workflow: ${error.message}`); - }, - }), + + toast.success("Workflow renamed"); + return mapped; + } catch { + toast.error("Failed to rename workflow"); + throw new Error("Failed to rename workflow"); + } finally { + setIsPending(false); + } + }, + [setItems], ); + + const mutate = useCallback( + (input: { id: string; name: string }) => { mutateAsync(input).catch(() => { }); }, + [mutateAsync], + ); + + return { mutate, mutateAsync, isPending }; }; -/** - * Hook to update a workflow - */ +/** Save the workflow graph (nodes + edges) to the backend. */ export const useUpdateWorkflow = () => { - const queryClient = useQueryClient(); - const trpc = useTRPC(); - - return useMutation( - trpc.workflows.update.mutationOptions({ - onSuccess: (data) => { - toast.success(`Workflow "${data.name}" saved`); - queryClient.invalidateQueries( - trpc.workflows.getMany.queryOptions({}), - ); - queryClient.invalidateQueries( - trpc.workflows.getOne.queryOptions({ id: data.id }), - ); - }, - onError: (error) => { - toast.error(`Failed to save workflow: ${error.message}`); - }, - }), + const [isPending, setIsPending] = useState(false); + + const mutateAsync = useCallback( + async (input: { id: string; nodes: Node[]; edges: Edge[] }) => { + setIsPending(true); + try { + const payload = { + nodes: input.nodes + .filter((n) => n.type !== "INITIAL") + .map((n) => ({ + id: n.id, + type: n.type ?? "", + name: (n.data as Record)?.name as string ?? "", + position: n.position, + data: n.data as Record, + credential_id: + ((n.data as Record)?.credentialId as string) ?? null, + })), + connections: input.edges.map((e) => ({ + id: e.id, + from_node_id: e.source, + to_node_id: e.target, + from_output: e.sourceHandle ?? "main", + to_input: e.targetHandle ?? "main", + })), + }; + + const saved = await workflowsApi.saveWorkflow(input.id, payload); + toast.success("Workflow saved"); + return mapWorkflow(saved); + } catch { + toast.error("Failed to save workflow"); + } finally { + setIsPending(false); + } + }, + [], ); + + const mutate = useCallback( + (input: { id: string; nodes: Node[]; edges: Edge[] }) => { + mutateAsync(input).catch(() => { }); + }, + [mutateAsync], + ); + + return { mutate, mutateAsync, isPending }; }; -/** - * Hook to execute a workflow - */ +/** Trigger a workflow execution. */ export const useExecuteWorkflow = () => { - const trpc = useTRPC(); - - return useMutation( - trpc.workflows.execute.mutationOptions({ - onSuccess: (data) => { - toast.success(`Workflow "${data.name}" executed`); - }, - onError: (error) => { - toast.error(`Failed to execute workflow: ${error.message}`); - }, - }), + const [isPending, setIsPending] = useState(false); + + const mutateAsync = useCallback(async (input: { id: string }) => { + setIsPending(true); + try { + const execution = await workflowsApi.executeWorkflow(input.id); + toast.success("Workflow execution started"); + return execution; + } catch { + toast.error("Failed to execute workflow"); + } finally { + setIsPending(false); + } + }, []); + + const mutate = useCallback( + (input: { id: string }) => { mutateAsync(input).catch(() => { }); }, + [mutateAsync], ); + + return { mutate, mutateAsync, isPending }; }; diff --git a/src/features/workflows/server/params-loader.ts b/src/features/workflows/server/params-loader.ts deleted file mode 100644 index c436c79..0000000 --- a/src/features/workflows/server/params-loader.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createLoader } from "nuqs/server"; -import { workflowsParams } from "../params"; - -export const workflowsParamsLoader = createLoader(workflowsParams); diff --git a/src/features/workflows/server/prefetch.ts b/src/features/workflows/server/prefetch.ts deleted file mode 100644 index 7a7fd49..0000000 --- a/src/features/workflows/server/prefetch.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { inferInput } from "@trpc/tanstack-react-query"; -import { prefetch, trpc } from "@/trpc/server"; - -type Input = inferInput; - -/** - * Prefetch all workflows - */ -export const prefetchWorkflows = (params: Input) => { - return prefetch(trpc.workflows.getMany.queryOptions(params)); -}; - -/** - * Prefetch a single workflow - */ -export const prefetchWorkflow = (id: string) => { - return prefetch(trpc.workflows.getOne.queryOptions({ id })); -}; diff --git a/src/features/workflows/server/routers.ts b/src/features/workflows/server/routers.ts deleted file mode 100644 index bef7821..0000000 --- a/src/features/workflows/server/routers.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { generateSlug } from "random-word-slugs"; -import prisma from "@/lib/db"; -import type { Node, Edge } from "@xyflow/react"; -import { createTRPCRouter, premiumProcedure, protectedProcedure } from "@/trpc/init"; -import z from "zod"; -import { PAGINATION } from "@/config/constants"; -import { NodeType } from "@/generated/prisma"; -import { inngest } from "@/inngest/client"; -import { sendWorkflowExecution } from "@/inngest/utils"; - -export const workflowsRouter = createTRPCRouter({ - execute: protectedProcedure - .input(z.object({ id: z.string() })) - .mutation(async ({ input, ctx }) => { - const workflow = await prisma.workflow.findUniqueOrThrow({ - where: { - id: input.id, - userId: ctx.auth.user.id, - }, - }); - - await sendWorkflowExecution({ - workflowId: input.id, - }); - - return workflow; - }), - create: premiumProcedure.mutation(({ ctx }) => { - return prisma.workflow.create({ - data: { - name: generateSlug(3), - userId: ctx.auth.user.id, - nodes: { - create: { - type: NodeType.INITIAL, - position: { x: 0, y: 0 }, - name: NodeType.INITIAL, - }, - }, - }, - }); - }), - remove: protectedProcedure - .input(z.object({ id: z.string() })) - .mutation(({ ctx, input }) => { - return prisma.workflow.delete({ - where: { - id: input.id, - userId: ctx.auth.user.id, - }, - }) - }), - update: protectedProcedure - .input( - z.object({ - id: z.string(), - nodes: z.array( - z.object({ - id: z.string(), - type: z.string().nullish(), - position: z.object({ x: z.number(), y: z.number() }), - data: z.record(z.string(), z.any()).optional(), - }), - ), - edges: z.array( - z.object({ - source: z.string(), - target: z.string(), - sourceHandle: z.string().nullish(), - targetHandle: z.string().nullish(), - }), - ), - }), - ) - .mutation(async ({ ctx, input }) => { - const { id, nodes, edges } = input; - - const workflow = await prisma.workflow.findUniqueOrThrow({ - where: { id, userId: ctx.auth.user.id }, - }); - - // Transaction to ensure consistency - return await prisma.$transaction(async (tx) => { - // Delete existing nodes and connections (cascade deletes connections) - await tx.node.deleteMany({ - where: { workflowId: id }, - }); - - // Create nodes - await tx.node.createMany({ - data: nodes.map((node) => ({ - id: node.id, - workflowId: id, - name: node.type || "unknown", - type: node.type as NodeType, - position: node.position, - data: node.data || {}, - })), - }); - - // Create connections - await tx.connection.createMany({ - data: edges.map((edge) => ({ - workflowId: id, - fromNodeId: edge.source, - toNodeId: edge.target, - fromOutput: edge.sourceHandle || "main", - toInput: edge.targetHandle || "main", - })), - }); - - // Update workflow's updateAt timestamp - await tx.workflow.update({ - where: { id }, - data: { updatedAt: new Date() }, - }); - - return workflow; - }); - }), - updateName: protectedProcedure - .input(z.object({ id: z.string(), name: z.string().min(1) })) - .mutation(({ ctx, input }) => { - return prisma.workflow.update({ - where: { id: input.id, userId: ctx.auth.user.id }, - data: { name: input.name }, - }); - }), - getOne: protectedProcedure - .input(z.object({ id: z.string() })) - .query(async ({ ctx, input }) => { - const workflow = await prisma.workflow.findUniqueOrThrow({ - where: { id: input.id, userId: ctx.auth.user.id }, - include: { nodes: true, connections: true }, - }); - - // Transform server nodes to react-flow compatible nodes - const nodes: Node[] = workflow.nodes.map((node) => ({ - id: node.id, - type: node.type, - position: node.position as { x: number, y: number }, - data: (node.data as Record) || {}, - })); - - // Transform server connections to react-flow compatible edges - const edges: Edge[] = workflow.connections.map((connection) => ({ - id: connection.id, - source: connection.fromNodeId, - target: connection.toNodeId, - sourceHandle: connection.fromOutput, - targetHandle: connection.toInput, - })); - - return { - id: workflow.id, - name: workflow.name, - nodes, - edges, - }; - }), - getMany: protectedProcedure - .input( - z.object({ - page: z.number().default(PAGINATION.DEFAULT_PAGE), - pageSize: z - .number() - .min(PAGINATION.MIN_PAGE_SIZE) - .max(PAGINATION.MAX_PAGE_SIZE) - .default(PAGINATION.DEFAULT_PAGE_SIZE), - search: z.string().default(""), - }) - ) - .query(async ({ ctx, input }) => { - const { page, pageSize, search } = input; - - const [items, totalCount] = await Promise.all([ - prisma.workflow.findMany({ - skip: (page - 1) * pageSize, - take: pageSize, - where: { - userId: ctx.auth.user.id, - name: { - contains: search, - mode: "insensitive", - }, - }, - orderBy: { - updatedAt: "desc", - }, - }), - prisma.workflow.count({ - where: { - userId: ctx.auth.user.id, - name: { - contains: search, - mode: "insensitive", - }, - }, - }), - ]); - - const totalPages = Math.ceil(totalCount / pageSize); - const hasNextPage = page < totalPages; - const hasPreviousPage = page > 1; - - return { - items, - page, - pageSize, - totalCount, - totalPages, - hasNextPage, - hasPreviousPage, - }; - }), -}); diff --git a/src/features/workflows/store/workflow-atoms.ts b/src/features/workflows/store/workflow-atoms.ts new file mode 100644 index 0000000..6e201f0 --- /dev/null +++ b/src/features/workflows/store/workflow-atoms.ts @@ -0,0 +1,11 @@ +import { atom } from "jotai"; +import type { Workflow } from "../hooks/use-workflows"; + +/** Cached list of workflows for the current page. */ +export const workflowsAtom = atom([]); + +/** Total workflow count (for pagination). */ +export const workflowsTotalAtom = atom(0); + +/** Whether workflows are currently being fetched. */ +export const workflowsLoadingAtom = atom(true); \ No newline at end of file diff --git a/src/hooks/use-upgrade-modal.tsx b/src/hooks/use-upgrade-modal.tsx index 97ab84c..5b5cdb7 100644 --- a/src/hooks/use-upgrade-modal.tsx +++ b/src/hooks/use-upgrade-modal.tsx @@ -1,16 +1,21 @@ -import { TRPCClientError } from "@trpc/client"; import { useState } from "react"; import { UpgradeModal } from "@/components/upgrade-modal"; +// NOTE: TRPCClientError replaced — handleError now uses a generic billing error check +// TODO: Update error code detection once custom backend error format is established export const useUpgradeModal = () => { const [open, setOpen] = useState(false); const handleError = (error: unknown) => { - if (error instanceof TRPCClientError) { - if (error.data?.code === "FORBIDDEN") { - setOpen(true); - return true; - } + // Generic check for billing/forbidden errors from custom backend + if ( + error instanceof Error && + ("code" in error || "status" in error) && + ((error as { code?: string }).code === "FORBIDDEN" || + (error as { status?: number }).status === 403) + ) { + setOpen(true); + return true; } return false; }; diff --git a/src/inngest/channels/anthropic.ts b/src/inngest/channels/anthropic.ts deleted file mode 100644 index 07ee246..0000000 --- a/src/inngest/channels/anthropic.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const ANTHROPIC_CHANNEL_NAME = "anthropic-execution"; - -export const anthropicChannel = channel(ANTHROPIC_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/channels/discord.ts b/src/inngest/channels/discord.ts deleted file mode 100644 index 5bc0f92..0000000 --- a/src/inngest/channels/discord.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const DISCORD_CHANNEL_NAME = "discord-execution"; - -export const discordChannel = channel(DISCORD_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/channels/gemini.ts b/src/inngest/channels/gemini.ts deleted file mode 100644 index ece0fd1..0000000 --- a/src/inngest/channels/gemini.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const GEMINI_CHANNEL_NAME = "gemini-execution"; - -export const geminiChannel = channel(GEMINI_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/channels/google-form-trigger.ts b/src/inngest/channels/google-form-trigger.ts deleted file mode 100644 index dffdd28..0000000 --- a/src/inngest/channels/google-form-trigger.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const GOOGLE_FORM_TRIGGER_CHANNEL_NAME = "google-form-trigger-execution"; - -export const googleFormTriggerChannel = channel(GOOGLE_FORM_TRIGGER_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/channels/http-request.ts b/src/inngest/channels/http-request.ts deleted file mode 100644 index 78cf18c..0000000 --- a/src/inngest/channels/http-request.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const HTTP_REQUEST_CHANNEL_NAME = "http-request-execution"; - -export const httpRequestChannel = channel(HTTP_REQUEST_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/channels/manual-trigger.ts b/src/inngest/channels/manual-trigger.ts deleted file mode 100644 index 58e0f36..0000000 --- a/src/inngest/channels/manual-trigger.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const MANUAL_TRIGGER_CHANNEL_NAME = "manual-trigger-execution"; - -export const manualTriggerChannel = channel(MANUAL_TRIGGER_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/channels/openai.ts b/src/inngest/channels/openai.ts deleted file mode 100644 index d70a298..0000000 --- a/src/inngest/channels/openai.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const OPENAI_CHANNEL_NAME = "openai-execution"; - -export const openAiChannel = channel(OPENAI_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/channels/slack.ts b/src/inngest/channels/slack.ts deleted file mode 100644 index cdbd484..0000000 --- a/src/inngest/channels/slack.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const SLACK_CHANNEL_NAME = "slack-execution"; - -export const slackChannel = channel(SLACK_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/channels/stripe-trigger.ts b/src/inngest/channels/stripe-trigger.ts deleted file mode 100644 index 086ed4c..0000000 --- a/src/inngest/channels/stripe-trigger.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { channel, topic } from "@inngest/realtime"; - -export const STRIPE_TRIGGER_CHANNEL_NAME = "stripe-trigger-execution"; - -export const stripeTriggerChannel = channel(STRIPE_TRIGGER_CHANNEL_NAME) - .addTopic( - topic("status").type<{ - nodeId: string; - status: "loading" | "success" | "error"; - }>(), - ); diff --git a/src/inngest/client.ts b/src/inngest/client.ts deleted file mode 100644 index bb8aaa4..0000000 --- a/src/inngest/client.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { realtimeMiddleware } from "@inngest/realtime/middleware"; -import { Inngest } from "inngest"; - -export const inngest = new Inngest({ - id: "nodebase", - middleware: [realtimeMiddleware()], -}); diff --git a/src/inngest/functions.ts b/src/inngest/functions.ts deleted file mode 100644 index 1552332..0000000 --- a/src/inngest/functions.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { NonRetriableError } from "inngest"; -import { inngest } from "./client"; -import prisma from "@/lib/db"; -import { topologicalSort } from "./utils"; -import { ExecutionStatus, NodeType } from "@/generated/prisma"; -import { getExecutor } from "@/features/executions/lib/executor-registry"; -import { httpRequestChannel } from "./channels/http-request"; -import { manualTriggerChannel } from "./channels/manual-trigger"; -import { googleFormTriggerChannel } from "./channels/google-form-trigger"; -import { stripeTriggerChannel } from "./channels/stripe-trigger"; -import { geminiChannel } from "./channels/gemini"; -import { openAiChannel } from "./channels/openai"; -import { anthropicChannel } from "./channels/anthropic"; -import { discordChannel } from "./channels/discord"; -import { slackChannel } from "./channels/slack"; - -export const executeWorkflow = inngest.createFunction( - { - id: "execute-workflow", - retries: process.env.NODE_ENV === "production" ? 3 : 0, - onFailure: async ({ event, step }) => { - return prisma.execution.update({ - where: { inngestEventId: event.data.event.id }, - data: { - status: ExecutionStatus.FAILED, - error: event.data.error.message, - errorStack: event.data.error.stack, - }, - }); - }, - }, - { - event: "workflows/execute.workflow", - channels: [ - httpRequestChannel(), - manualTriggerChannel(), - googleFormTriggerChannel(), - stripeTriggerChannel(), - geminiChannel(), - openAiChannel(), - anthropicChannel(), - discordChannel(), - slackChannel(), - ], - }, - async ({ event, step, publish }) => { - const inngestEventId = event.id; - const workflowId = event.data.workflowId; - - if (!inngestEventId || !workflowId) { - throw new NonRetriableError("Event ID or workflow ID is missing"); - } - - await step.run("create-execution", async () => { - return prisma.execution.create({ - data: { - workflowId, - inngestEventId, - }, - }); - }); - - const sortedNodes = await step.run("prepare-workflow", async () => { - const workflow = await prisma.workflow.findUniqueOrThrow({ - where: { id: workflowId }, - include: { - nodes: true, - connections: true, - }, - }); - - return topologicalSort(workflow.nodes, workflow.connections); - }); - - const userId = await step.run("find-user-id", async () => { - const workflow = await prisma.workflow.findUniqueOrThrow({ - where: { id: workflowId }, - select: { - userId: true, - }, - }); - - return workflow.userId; - }); - - // Initialize context with any initial data from the trigger - let context = event.data.initialData || {}; - - // Execute each node - for (const node of sortedNodes) { - const executor = getExecutor(node.type as NodeType); - context = await executor({ - data: node.data as Record, - nodeId: node.id, - userId, - context, - step, - publish, - }); - } - - await step.run("update-execution", async () => { - return prisma.execution.update({ - where: { inngestEventId, workflowId }, - data: { - status: ExecutionStatus.SUCCESS, - completedAt: new Date(), - output: context, - }, - }) - }); - - return { - workflowId, - result: context, - }; - }, -); diff --git a/src/inngest/utils.ts b/src/inngest/utils.ts deleted file mode 100644 index fab2e2e..0000000 --- a/src/inngest/utils.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Connection, Node } from "@/generated/prisma"; -import toposort from "toposort"; -import { inngest } from "./client"; -import { createId } from "@paralleldrive/cuid2"; - -export const topologicalSort = ( - nodes: Node[], - connections: Connection[], -): Node[] => { - // If no connections, return node as-is (they're all independent) - if (connections.length === 0) { - return nodes; - } - - // Create edges array for toposort - const edges: [string, string][] = connections.map((conn) => [ - conn.fromNodeId, - conn.toNodeId, - ]); - - // Add nodes with no connections as self-edges to ensure they're included - const connectedNodeIds = new Set(); - for (const conn of connections) { - connectedNodeIds.add(conn.fromNodeId); - connectedNodeIds.add(conn.toNodeId); - } - - for (const node of nodes) { - if (!connectedNodeIds.has(node.id)) { - edges.push([node.id, node.id]); - } - } - - // Perform topological sort - let sortedNodeIds: string[]; - try { - sortedNodeIds = toposort(edges); - // Remove duplicates (from self-edges) - sortedNodeIds = [...new Set(sortedNodeIds)]; - } catch (error) { - if (error instanceof Error && error.message.includes("Cyclic")) { - throw new Error("Workflow contains a cycle"); - } - throw error; - } - - // Map sorted IDs back to node objects - const nodeMap = new Map(nodes.map((n) => [n.id, n])); - return sortedNodeIds.map((id) => nodeMap.get(id)!).filter(Boolean); -}; - -export const sendWorkflowExecution = async (data: { - workflowId: string; - [key: string]: any; -}) => { - return inngest.send({ - name: "workflows/execute.workflow", - data, - id: createId(), - }); -}; diff --git a/src/instrumentation-client.ts b/src/instrumentation-client.ts deleted file mode 100644 index 16fbb9c..0000000 --- a/src/instrumentation-client.ts +++ /dev/null @@ -1,32 +0,0 @@ -// This file configures the initialization of Sentry on the client. -// The added config here will be used whenever a users loads a page in their browser. -// https://docs.sentry.io/platforms/javascript/guides/nextjs/ - -import * as Sentry from "@sentry/nextjs"; - -Sentry.init({ - dsn: "https://f1a2853e6bb4b74c72976cd5c3b37dd9@o4507629901053952.ingest.de.sentry.io/4510150041337936", - - // Add optional integrations for additional features - integrations: [ - Sentry.replayIntegration(), - ], - - // Define how likely traces are sampled. Adjust this value in production, or use tracesSampler for greater control. - tracesSampleRate: 1, - // Enable logs to be sent to Sentry - enableLogs: true, - - // Define how likely Replay events are sampled. - // This sets the sample rate to be 10%. You may want this to be 100% while - // in development and sample at a lower rate in production - replaysSessionSampleRate: 0.1, - - // Define how likely Replay events are sampled when an error occurs. - replaysOnErrorSampleRate: 1.0, - - // Setting this option to true will print useful information to the console while you're setting up Sentry. - debug: false, -}); - -export const onRouterTransitionStart = Sentry.captureRouterTransitionStart; \ No newline at end of file diff --git a/src/instrumentation.ts b/src/instrumentation.ts deleted file mode 100644 index 8aff09f..0000000 --- a/src/instrumentation.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as Sentry from '@sentry/nextjs'; - -export async function register() { - if (process.env.NEXT_RUNTIME === 'nodejs') { - await import('../sentry.server.config'); - } - - if (process.env.NEXT_RUNTIME === 'edge') { - await import('../sentry.edge.config'); - } -} - -export const onRequestError = Sentry.captureRequestError; diff --git a/src/lib/auth-client.ts b/src/lib/auth-client.ts deleted file mode 100644 index ec89ddc..0000000 --- a/src/lib/auth-client.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { polarClient } from "@polar-sh/better-auth"; -import { createAuthClient } from "better-auth/react" - -export const authClient = createAuthClient({ - plugins: [polarClient()], -}); diff --git a/src/lib/auth-utils.ts b/src/lib/auth-utils.ts index 399f67f..e5e39c2 100644 --- a/src/lib/auth-utils.ts +++ b/src/lib/auth-utils.ts @@ -1,25 +1,12 @@ -import { headers } from "next/headers"; -import { redirect } from "next/navigation"; -import { auth } from "./auth"; - -export const requireAuth = async () => { - const session = await auth.api.getSession({ - headers: await headers(), - }); - - if (!session) { - redirect("/login"); - } - - return session; -}; - -export const requireUnauth = async () => { - const session = await auth.api.getSession({ - headers: await headers(), - }); - - if (session) { - redirect("/"); - } -}; +/** + * Auth checks are now handled client-side by the AuthProvider. + * These stubs remain so that existing server-component page files + * continue to compile without changes. + */ +export async function requireAuth() { + // Handled by AuthProvider — no server-side check needed +} + +export async function requireUnauth() { + // Handled by AuthProvider — no server-side check needed +} diff --git a/src/lib/auth.ts b/src/lib/auth.ts deleted file mode 100644 index c3648c3..0000000 --- a/src/lib/auth.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { checkout, polar, portal } from "@polar-sh/better-auth"; -import { betterAuth } from "better-auth"; -import { prismaAdapter } from "better-auth/adapters/prisma"; -import prisma from "@/lib/db"; -import { polarClient } from "./polar"; - -export const auth = betterAuth({ - database: prismaAdapter(prisma, { - provider: "postgresql", - }), - emailAndPassword: { - enabled: true, - autoSignIn: true, - }, - socialProviders: { - github: { - clientId: process.env.GITHUB_CLIENT_ID as string, - clientSecret: process.env.GITHUB_CLIENT_SECRET as string, - }, - google: { - clientId: process.env.GOOGLE_CLIENT_ID as string, - clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, - }, - }, - plugins: [ - polar({ - client: polarClient, - createCustomerOnSignUp: true, - use: [ - checkout({ - products: [ - { - productId: "f81be8a8-45e1-4e45-a1e9-b9d3fd79f814", - slug: "pro", - } - ], - successUrl: process.env.POLAR_SUCCESS_URL, - authenticatedUsersOnly: true, - }), - portal(), - ], - }) - ] -}); diff --git a/src/lib/db.ts b/src/lib/db.ts deleted file mode 100644 index 1947470..0000000 --- a/src/lib/db.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { PrismaClient } from "@/generated/prisma"; - -const globalForPrisma = global as unknown as { - prisma: PrismaClient; -}; - -const prisma = globalForPrisma.prisma || new PrismaClient(); - -if (process.env.NODE_ENV !== "production") { - globalForPrisma.prisma = prisma; -} - -export default prisma; diff --git a/src/lib/encryption.ts b/src/lib/encryption.ts deleted file mode 100644 index 961ed0d..0000000 --- a/src/lib/encryption.ts +++ /dev/null @@ -1,6 +0,0 @@ -import Cryptr from "cryptr"; - -const cryptr = new Cryptr(process.env.ENCRYPTION_KEY!); - -export const encrypt = (text: string) => cryptr.encrypt(text); -export const decrypt = (text: string) => cryptr.decrypt(text); diff --git a/src/lib/polar.ts b/src/lib/polar.ts deleted file mode 100644 index 112de9d..0000000 --- a/src/lib/polar.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Polar } from "@polar-sh/sdk"; - -export const polarClient = new Polar({ - accessToken: process.env.POLAR_ACCESS_TOKEN, - server: "sandbox" -}); diff --git a/src/trpc/client.tsx b/src/trpc/client.tsx deleted file mode 100644 index 9c0d4cb..0000000 --- a/src/trpc/client.tsx +++ /dev/null @@ -1,60 +0,0 @@ -'use client'; -// ^-- to make sure we can mount the Provider from a server component -import type { QueryClient } from '@tanstack/react-query'; -import { QueryClientProvider } from '@tanstack/react-query'; -import { createTRPCClient, httpBatchLink } from '@trpc/client'; -import { createTRPCContext } from '@trpc/tanstack-react-query'; -import { useState } from 'react'; -import { makeQueryClient } from './query-client'; -import type { AppRouter } from './routers/_app'; -import superjson from "superjson"; -export const { TRPCProvider, useTRPC } = createTRPCContext(); -let browserQueryClient: QueryClient; -function getQueryClient() { - if (typeof window === 'undefined') { - // Server: always make a new query client - return makeQueryClient(); - } - // Browser: make a new query client if we don't already have one - // This is very important, so we don't re-make a new client if React - // suspends during the initial render. This may not be needed if we - // have a suspense boundary BELOW the creation of the query client - if (!browserQueryClient) browserQueryClient = makeQueryClient(); - return browserQueryClient; -} -function getUrl() { - const base = (() => { - if (typeof window !== 'undefined') return ''; - if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; - return 'http://localhost:3000'; - })(); - return `${base}/api/trpc`; -} -export function TRPCReactProvider( - props: Readonly<{ - children: React.ReactNode; - }>, -) { - // NOTE: Avoid useState when initializing the query client if you don't - // have a suspense boundary between this and the code that may - // suspend because React will throw away the client on the initial - // render if it suspends and there is no boundary - const queryClient = getQueryClient(); - const [trpcClient] = useState(() => - createTRPCClient({ - links: [ - httpBatchLink({ - transformer: superjson, - url: getUrl(), - }), - ], - }), - ); - return ( - - - {props.children} - - - ); -} diff --git a/src/trpc/init.ts b/src/trpc/init.ts deleted file mode 100644 index 9a6f991..0000000 --- a/src/trpc/init.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { auth } from '@/lib/auth'; -import { polarClient } from '@/lib/polar'; -import { initTRPC, TRPCError } from '@trpc/server'; -import { headers } from 'next/headers'; -import { cache } from 'react'; -import superjson from "superjson" -export const createTRPCContext = cache(async () => { - /** - * @see: https://trpc.io/docs/server/context - */ - return { userId: 'user_123' }; -}); -// Avoid exporting the entire t-object -// since it's not very descriptive. -// For instance, the use of a t variable -// is common in i18n libraries. -const t = initTRPC.create({ - /** - * @see https://trpc.io/docs/server/data-transformers - */ - transformer: superjson, -}); -// Base router and procedure helpers -export const createTRPCRouter = t.router; -export const createCallerFactory = t.createCallerFactory; -export const baseProcedure = t.procedure; -export const protectedProcedure = baseProcedure.use(async ({ ctx, next }) => { - const session = await auth.api.getSession({ - headers: await headers(), - }); - - if (!session) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "Unathorized", - }); - } - - return next({ ctx: { ...ctx, auth: session } }); -}); -export const premiumProcedure = protectedProcedure.use( - async ({ ctx, next }) => { - const customer = await polarClient.customers.getStateExternal({ - externalId: ctx.auth.user.id, - }); - - if ( - !customer.activeSubscriptions || - customer.activeSubscriptions.length === 0 - ) { - throw new TRPCError({ - code: "FORBIDDEN", - message: "Active subscription required", - }); - } - - return next({ ctx: { ...ctx, customer } }); - }, -); diff --git a/src/trpc/query-client.ts b/src/trpc/query-client.ts deleted file mode 100644 index c7fc8ad..0000000 --- a/src/trpc/query-client.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { - defaultShouldDehydrateQuery, - QueryClient, -} from '@tanstack/react-query'; -import superjson from 'superjson'; -export function makeQueryClient() { - return new QueryClient({ - defaultOptions: { - queries: { - staleTime: 30 * 1000, - }, - dehydrate: { - serializeData: superjson.serialize, - shouldDehydrateQuery: (query) => - defaultShouldDehydrateQuery(query) || - query.state.status === 'pending', - }, - hydrate: { - deserializeData: superjson.deserialize, - }, - }, - }); -} \ No newline at end of file diff --git a/src/trpc/routers/_app.ts b/src/trpc/routers/_app.ts deleted file mode 100644 index 6b28d57..0000000 --- a/src/trpc/routers/_app.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createTRPCRouter } from '../init'; -import { workflowsRouter } from '@/features/workflows/server/routers'; -import { credentialsRouter } from '@/features/credentials/server/routers'; -import { executionsRouter } from '@/features/executions/server/routers'; - -export const appRouter = createTRPCRouter({ - workflows: workflowsRouter, - credentials: credentialsRouter, - executions: executionsRouter, -}); -// export type definition of API -export type AppRouter = typeof appRouter; diff --git a/src/trpc/server.tsx b/src/trpc/server.tsx deleted file mode 100644 index 7ed5a23..0000000 --- a/src/trpc/server.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import 'server-only'; // <-- ensure this file cannot be imported from the client -import { createTRPCOptionsProxy, TRPCQueryOptions } from '@trpc/tanstack-react-query'; -import { cache } from 'react'; -import { createTRPCContext } from './init'; -import { makeQueryClient } from './query-client'; -import { appRouter } from './routers/_app'; -import { dehydrate, HydrationBoundary } from '@tanstack/react-query'; -// IMPORTANT: Create a stable getter for the query client that -// will return the same client during the same request. -export const getQueryClient = cache(makeQueryClient); -export const trpc = createTRPCOptionsProxy({ - ctx: createTRPCContext, - router: appRouter, - queryClient: getQueryClient, -}); -// ... -export const caller = appRouter.createCaller(createTRPCContext); - -export function prefetch>>( - queryOptions: T, -) { - const queryClient = getQueryClient(); - if (queryOptions.queryKey[1]?.type === 'infinite') { - void queryClient.prefetchInfiniteQuery(queryOptions as any); - } else { - void queryClient.prefetchQuery(queryOptions); - } -} - -export function HydrateClient(props: { children: React.ReactNode }) { - const queryClient = getQueryClient(); - return ( - - {props.children} - - ); -}