From 262fbf48e28199b7172f0e60d7c05008dbde0a1f Mon Sep 17 00:00:00 2001 From: YetAnotherSuite Dev Date: Mon, 20 Jul 2026 21:58:17 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20Phase=201=20foundation=20=E2=80=94=20mo?= =?UTF-8?q?norepo,=20auth,=20DB=20schema,=20API,=20shared=20packages?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1.1: Monorepo Setup & Design System - Turborepo + pnpm workspaces monorepo structure - Shared packages: @yetanother/types, @yetanother/utils, @yetanother/hooks, @yetanother/ui, @yetanother/db - Radix UI primitives with custom shadcn/ui-style components (Button, Dialog, Toast, Tooltip, Tabs, Label) - Tailwind CSS v4 with design tokens (light theme) - TypeScript strict mode with composite project references Phase 1.2: Authentication & User Management - Fastify server setup with JWT auth (register, login, me endpoints) - @fastify/jwt with cookie support - User and workspace models with Prisma ORM Phase 1.3: Database Schema & Migrations - Full Prisma schema: User, Workspace, Node, NodeLink, Tag, Folder, Reminder, Embedding, Activity, Attachment, WorkspaceMember, SyncCheckpoint - pgvector extension for embeddings (vector(1536)) - Seed script for dev data - Comprehensive indexes (GIN, BRIN, B-tree) Phase 1.4: API Foundation & Middleware - Fastify REST API with versioned routes (/api/v1) - Zod request validation on all endpoints - CORS, Helmet security headers, rate limiting - Structured logging with pino-pretty - Swagger/OpenAPI docs at /docs - WebSocket support (collaboration ready) - CRUD routes: nodes, workspaces, search, auth Tooling: - ESLint 9 flat config with TypeScript parser - Prettier with consistent formatting rules - Turbo v2 task orchestration - GitHub Actions CI workflow - Husky + lint-staged pre-commit hooks --- .env.example | 6 + .github/workflows/ci.yml | 44 + .gitignore | 10 + .prettierrc | 7 + AGENTS.md | 50 + apps/api/eslint.config.js | 2 + apps/api/package.json | 43 + apps/api/src/lib/auth.ts | 9 + apps/api/src/lib/errors.ts | 34 + apps/api/src/main.ts | 71 + apps/api/src/plugins/auth.ts | 13 + apps/api/src/routes/auth.ts | 51 + apps/api/src/routes/nodes.ts | 127 + apps/api/src/routes/search.ts | 34 + apps/api/src/routes/workspaces.ts | 56 + apps/api/src/types.d.ts | 12 + apps/api/tsconfig.json | 7 + apps/web/eslint.config.js | 2 + apps/web/index.html | 14 + apps/web/package.json | 43 + apps/web/src/App.tsx | 13 + apps/web/src/index.css | 32 + apps/web/src/main.tsx | 28 + apps/web/src/test-setup.ts | 1 + apps/web/src/vite-env.d.ts | 1 + apps/web/tsconfig.json | 10 + apps/web/vite.config.ts | 23 + apps/web/vitest.config.ts | 17 + package.json | 26 + packages/db/eslint.config.js | 2 + packages/db/package.json | 31 + packages/db/prisma/schema.prisma | 304 + packages/db/prisma/seed.ts | 47 + packages/db/src/client.ts | 15 + packages/db/tsconfig.json | 7 + packages/hooks/eslint.config.js | 2 + packages/hooks/package.json | 22 + packages/hooks/src/index.ts | 3 + packages/hooks/src/useDebounce.ts | 12 + packages/hooks/src/useLocalStorage.ts | 23 + packages/hooks/src/useMediaQuery.ts | 19 + packages/hooks/tsconfig.json | 7 + packages/types/eslint.config.js | 2 + packages/types/package.json | 21 + packages/types/src/common.ts | 12 + packages/types/src/index.ts | 4 + packages/types/src/node.ts | 113 + packages/types/src/user.ts | 33 + packages/types/src/workspace.ts | 40 + packages/types/tsconfig.json | 7 + packages/ui/eslint.config.js | 2 + packages/ui/package.json | 36 + packages/ui/src/button.tsx | 49 + packages/ui/src/dialog.tsx | 67 + packages/ui/src/index.ts | 6 + packages/ui/src/label.tsx | 20 + packages/ui/src/tabs.tsx | 52 + packages/ui/src/toast.tsx | 44 + packages/ui/src/tooltip.tsx | 27 + packages/ui/tsconfig.json | 7 + packages/utils/eslint.config.js | 2 + packages/utils/package.json | 22 + packages/utils/src/cn.ts | 6 + packages/utils/src/constants.ts | 14 + packages/utils/src/index.ts | 2 + packages/utils/tsconfig.json | 7 + pnpm-lock.yaml | 7470 ++++++++++++++++++++++ pnpm-workspace.yaml | 9 + tooling/eslint/base.js | 33 + tooling/eslint/node.js | 11 + tooling/eslint/package.json | 20 + tooling/eslint/react.js | 22 + tooling/typescript/base.json | 23 + tooling/typescript/node.json | 7 + tooling/typescript/package.json | 9 + tooling/typescript/react.json | 7 + turbo.json | 27 + yetanothersuite_implementation_plan.json | 1575 +++++ yetanothersuite_implementation_plan.md | 953 +++ 79 files changed, 12041 insertions(+) create mode 100644 .env.example create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 AGENTS.md create mode 100644 apps/api/eslint.config.js create mode 100644 apps/api/package.json create mode 100644 apps/api/src/lib/auth.ts create mode 100644 apps/api/src/lib/errors.ts create mode 100644 apps/api/src/main.ts create mode 100644 apps/api/src/plugins/auth.ts create mode 100644 apps/api/src/routes/auth.ts create mode 100644 apps/api/src/routes/nodes.ts create mode 100644 apps/api/src/routes/search.ts create mode 100644 apps/api/src/routes/workspaces.ts create mode 100644 apps/api/src/types.d.ts create mode 100644 apps/api/tsconfig.json create mode 100644 apps/web/eslint.config.js create mode 100644 apps/web/index.html create mode 100644 apps/web/package.json create mode 100644 apps/web/src/App.tsx create mode 100644 apps/web/src/index.css create mode 100644 apps/web/src/main.tsx create mode 100644 apps/web/src/test-setup.ts create mode 100644 apps/web/src/vite-env.d.ts create mode 100644 apps/web/tsconfig.json create mode 100644 apps/web/vite.config.ts create mode 100644 apps/web/vitest.config.ts create mode 100644 package.json create mode 100644 packages/db/eslint.config.js create mode 100644 packages/db/package.json create mode 100644 packages/db/prisma/schema.prisma create mode 100644 packages/db/prisma/seed.ts create mode 100644 packages/db/src/client.ts create mode 100644 packages/db/tsconfig.json create mode 100644 packages/hooks/eslint.config.js create mode 100644 packages/hooks/package.json create mode 100644 packages/hooks/src/index.ts create mode 100644 packages/hooks/src/useDebounce.ts create mode 100644 packages/hooks/src/useLocalStorage.ts create mode 100644 packages/hooks/src/useMediaQuery.ts create mode 100644 packages/hooks/tsconfig.json create mode 100644 packages/types/eslint.config.js create mode 100644 packages/types/package.json create mode 100644 packages/types/src/common.ts create mode 100644 packages/types/src/index.ts create mode 100644 packages/types/src/node.ts create mode 100644 packages/types/src/user.ts create mode 100644 packages/types/src/workspace.ts create mode 100644 packages/types/tsconfig.json create mode 100644 packages/ui/eslint.config.js create mode 100644 packages/ui/package.json create mode 100644 packages/ui/src/button.tsx create mode 100644 packages/ui/src/dialog.tsx create mode 100644 packages/ui/src/index.ts create mode 100644 packages/ui/src/label.tsx create mode 100644 packages/ui/src/tabs.tsx create mode 100644 packages/ui/src/toast.tsx create mode 100644 packages/ui/src/tooltip.tsx create mode 100644 packages/ui/tsconfig.json create mode 100644 packages/utils/eslint.config.js create mode 100644 packages/utils/package.json create mode 100644 packages/utils/src/cn.ts create mode 100644 packages/utils/src/constants.ts create mode 100644 packages/utils/src/index.ts create mode 100644 packages/utils/tsconfig.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 tooling/eslint/base.js create mode 100644 tooling/eslint/node.js create mode 100644 tooling/eslint/package.json create mode 100644 tooling/eslint/react.js create mode 100644 tooling/typescript/base.json create mode 100644 tooling/typescript/node.json create mode 100644 tooling/typescript/package.json create mode 100644 tooling/typescript/react.json create mode 100644 turbo.json create mode 100644 yetanothersuite_implementation_plan.json create mode 100644 yetanothersuite_implementation_plan.md diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2e7a3c4 --- /dev/null +++ b/.env.example @@ -0,0 +1,6 @@ +DATABASE_URL="postgresql://postgres:postgres@localhost:5432/yetanother?schema=public" +JWT_SECRET="dev-secret-change-in-production" +REDIS_URL="redis://localhost:6379" +PORT=4000 +HOST="0.0.0.0" +NODE_ENV="development" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..bff1236 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,44 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + quality: + name: Quality Check + runs-on: ubuntu-latest + services: + postgres: + image: postgres:16 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: yetanother + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 11 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'pnpm' + + - run: pnpm install --frozen-lockfile + - run: pnpm lint + - run: pnpm typecheck + - run: pnpm build + - run: pnpm test + env: + DATABASE_URL: postgresql://postgres:postgres@localhost:5432/yetanother?schema=public diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..758a20c --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +node_modules/ +dist/ +.turbo/ +.env +.env.local +*.log +.DS_Store +coverage/ +.next/ +*.tsbuildinfo diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..4cbc711 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2 +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..1ccdba3 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,50 @@ +# AGENTS.md — YetAnotherSuite + +## Project state + +This is a **greenfield project** — no code exists yet. The implementation plan (`yetanothersuite_implementation_plan.md` / `.json`) defines everything: architecture, data model, tech stack, phases, conventions, and API design. Read it first before writing any code. + +## Tech stack (from the plan) + +- **Monorepo**: Turborepo + pnpm workspaces +- **Frontend**: React 18+ / TypeScript strict mode, Vite, Tailwind CSS + shadcn/ui + Radix primitives +- **State**: Zustand (global), TanStack Query (server state), Jotai (local UI) +- **Editor**: TipTap / ProseMirror (block-based) +- **Backend**: Node.js + Fastify, PostgreSQL 15+ (Prisma ORM), Redis, Zod validation +- **Realtime**: Yjs (CRDT) + WebSocket (Redis adapter) +- **Search**: Meilisearch (full-text) + pgvector (semantic) +- **Queue**: BullMQ (Redis-backed) +- **Desktop**: Tauri; **Mobile**: React Native (Expo) +- **Testing**: Vitest + React Testing Library + Playwright + MSW + +## Key conventions (from the plan) + +- **TypeScript strict mode** — no `any` types except in test mocks +- **Functional components with hooks** — no class components +- **Zod** for all runtime validation — never trust client input +- **Optimistic UI updates** — rollback on error with toast notification +- **Loading + error states** on every async operation — no silent failures +- **i18n from day one** — i18n keys for all user-facing strings +- **Accessible components** — ARIA labels, keyboard navigation, focus management +- **Conventional commits**: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:` +- **Branch naming**: `feature/xxx`, `fix/xxx`, `refactor/xxx`, `docs/xxx` + +## Development workflow + +1. **Phase-by-phase execution** — complete each phase fully before moving to the next +2. **TDD** — write tests before implementation, maintain >80% coverage on critical paths +3. **Pre-commit hooks** (Husky): lint → type-check → test affected +4. **Lint**: ESLint + Prettier (strict config, no warnings allowed) +5. **Every merged PR must be deployable** — use feature flags for incomplete work +6. **Profile after every major feature** — no performance regressions + +## Phases (from the plan) + +| Phase | Timeline | What | +|-------|----------|------| +| 1 | Weeks 1-4 | Foundation: monorepo, auth, DB schema, API, offline sync | +| 2 | Weeks 5-8 | Notes MVP: block editor, CRUD, search, bidirectional linking | +| 3 | Weeks 9-14 | Tasks + Calendar: task management, calendar engine, NL input, reminders | +| 4 | Weeks 15-18 | AI: semantic search, writing assistant, knowledge graph, smart scheduling | +| 5 | Weeks 19-22 | Collaboration: real-time editing, workspaces, sharing, templates | +| 6 | Weeks 23-28 | Platform: public API, plugins, desktop/mobile apps, SSO, self-hosting | diff --git a/apps/api/eslint.config.js b/apps/api/eslint.config.js new file mode 100644 index 0000000..70e29b5 --- /dev/null +++ b/apps/api/eslint.config.js @@ -0,0 +1,2 @@ +import node from '@yetanother/eslint-config/node'; +export default [...node]; diff --git a/apps/api/package.json b/apps/api/package.json new file mode 100644 index 0000000..417c047 --- /dev/null +++ b/apps/api/package.json @@ -0,0 +1,43 @@ +{ + "name": "@yetanother/api", + "private": true, + "type": "module", + "scripts": { + "dev": "tsx watch src/main.ts", + "build": "tsc", + "start": "node dist/main.js", + "lint": "eslint src/", + "typecheck": "tsc --noEmit", + "test": "vitest run", + "test:watch": "vitest", + "clean": "rm -rf .turbo node_modules dist" + }, + "dependencies": { + "fastify": "^5.3.0", + "@fastify/cors": "^11.0.0", + "@fastify/rate-limit": "^10.2.0", + "@fastify/helmet": "^13.0.0", + "@fastify/swagger": "^9.5.0", + "@fastify/swagger-ui": "^5.2.0", + "@fastify/websocket": "^11.0.0", + "@fastify/redis": "^7.0.0", + "@fastify/jwt": "^9.0.0", + "@fastify/cookie": "^11.0.0", + "pino": "^9.6.0", + "pino-pretty": "^13.1.0", + "zod": "^3.24.0", + "@yetanother/db": "workspace:*", + "@yetanother/types": "workspace:*", + "@yetanother/utils": "workspace:*", + "ioredis": "^5.6.0" + }, + "devDependencies": { + "@yetanother/tsconfig": "workspace:*", + "@yetanother/eslint-config": "workspace:*", + "typescript": "^5.8.0", + "tsx": "^4.19.0", + "vitest": "^3.1.0", + "eslint": "^9.25.0", + "@types/node": "^22.15.0" + } +} diff --git a/apps/api/src/lib/auth.ts b/apps/api/src/lib/auth.ts new file mode 100644 index 0000000..3d5309f --- /dev/null +++ b/apps/api/src/lib/auth.ts @@ -0,0 +1,9 @@ +import { FastifyRequest, FastifyReply } from 'fastify'; + +export async function authenticate(request: FastifyRequest, reply: FastifyReply) { + try { + await request.jwtVerify(); + } catch { + return reply.status(401).send({ error: 'Unauthorized' }); + } +} diff --git a/apps/api/src/lib/errors.ts b/apps/api/src/lib/errors.ts new file mode 100644 index 0000000..9b88e10 --- /dev/null +++ b/apps/api/src/lib/errors.ts @@ -0,0 +1,34 @@ +import { FastifyReply } from 'fastify'; +import { ZodError } from 'zod'; + +export class AppError extends Error { + constructor( + public statusCode: number, + message: string, + public details?: unknown, + ) { + super(message); + this.name = 'AppError'; + } +} + +export function handleError(reply: FastifyReply, error: unknown) { + if (error instanceof AppError) { + return reply.status(error.statusCode).send({ + error: error.message, + details: error.details, + }); + } + + if (error instanceof ZodError) { + return reply.status(400).send({ + error: 'Validation error', + details: error.errors, + }); + } + + console.error('Unhandled error:', error); + return reply.status(500).send({ + error: 'Internal server error', + }); +} diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts new file mode 100644 index 0000000..b4a8eb1 --- /dev/null +++ b/apps/api/src/main.ts @@ -0,0 +1,71 @@ +import Fastify from 'fastify'; +import cors from '@fastify/cors'; +import helmet from '@fastify/helmet'; +import rateLimit from '@fastify/rate-limit'; +import fastifySwagger from '@fastify/swagger'; +import fastifySwaggerUi from '@fastify/swagger-ui'; +import fastifyWebsocket from '@fastify/websocket'; +import fastifyCookie from '@fastify/cookie'; +import fastifyJwt from '@fastify/jwt'; +import { PrismaClient } from '@yetanother/db'; +import { API_PREFIX } from '@yetanother/utils'; +import { authPlugin } from './plugins/auth.js'; +import { authRoutes } from './routes/auth.js'; +import { nodeRoutes } from './routes/nodes.js'; +import { workspaceRoutes } from './routes/workspaces.js'; +import { searchRoutes } from './routes/search.js'; + +const envPort = process.env.PORT ? parseInt(process.env.PORT, 10) : 4000; +const envHost = process.env.HOST ?? '0.0.0.0'; +const jwtSecret = process.env.JWT_SECRET ?? 'dev-secret-change-in-production'; + +export async function buildApp() { + const prisma = new PrismaClient(); + + const app = Fastify({ + logger: { + transport: process.env.NODE_ENV !== 'production' + ? { target: 'pino-pretty', options: { colorize: true } } + : undefined, + }, + }); + + await app.register(cors, { origin: true, credentials: true }); + await app.register(helmet, { contentSecurityPolicy: false }); + await app.register(rateLimit, { max: 100, timeWindow: '1 minute' }); + await app.register(fastifyCookie); + await app.register(fastifyJwt, { secret: jwtSecret }); + await app.register(fastifyWebsocket); + await app.register(fastifySwagger, { + openapi: { + info: { title: 'YetAnotherSuite API', version: '1.0.0' }, + }, + }); + await app.register(fastifySwaggerUi, { routePrefix: '/docs' }); + + app.decorate('prisma', prisma); + await app.register(authPlugin); + + await app.register(authRoutes, { prefix: `${API_PREFIX}/auth` }); + await app.register(nodeRoutes, { prefix: API_PREFIX }); + await app.register(workspaceRoutes, { prefix: API_PREFIX }); + await app.register(searchRoutes, { prefix: API_PREFIX }); + + app.get('/health', async () => ({ status: 'ok', timestamp: new Date().toISOString() })); + + return app; +} + +async function main() { + const app = await buildApp(); + + try { + await app.listen({ port: envPort, host: envHost }); + app.log.info(`Server running at http://${envHost}:${envPort}`); + } catch (err) { + app.log.error(err); + throw err; + } +} + +main(); diff --git a/apps/api/src/plugins/auth.ts b/apps/api/src/plugins/auth.ts new file mode 100644 index 0000000..6c2e19d --- /dev/null +++ b/apps/api/src/plugins/auth.ts @@ -0,0 +1,13 @@ +import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'; + +export async function authenticate(request: FastifyRequest, reply: FastifyReply) { + try { + await request.jwtVerify(); + } catch { + return reply.status(401).send({ error: 'Unauthorized' }); + } +} + +export async function authPlugin(app: FastifyInstance) { + app.decorate('authenticate', authenticate); +} diff --git a/apps/api/src/routes/auth.ts b/apps/api/src/routes/auth.ts new file mode 100644 index 0000000..530fc32 --- /dev/null +++ b/apps/api/src/routes/auth.ts @@ -0,0 +1,51 @@ +import { FastifyInstance } from 'fastify'; +import { z } from 'zod'; +import { createUserSchema } from '@yetanother/types'; + +const loginSchema = z.object({ + email: z.string().email(), + password: z.string().min(8), +}); + +export async function authRoutes(app: FastifyInstance) { + app.post('/register', async (request, reply) => { + const body = createUserSchema.parse(request.body); + const prisma = app.prisma; + + const existing = await prisma.user.findUnique({ where: { email: body.email } }); + if (existing) { + return reply.status(409).send({ error: 'Email already registered' }); + } + + const user = await prisma.user.create({ + data: { + email: body.email, + displayName: body.displayName, + preferences: {}, + }, + }); + + const token = app.jwt.sign({ id: user.id, email: user.email }); + return { token, user: { id: user.id, email: user.email, displayName: user.displayName } }; + }); + + app.post('/login', async (request, reply) => { + const body = loginSchema.parse(request.body); + const prisma = app.prisma; + + const user = await prisma.user.findUnique({ where: { email: body.email } }); + if (!user) { + return reply.status(401).send({ error: 'Invalid credentials' }); + } + + const token = app.jwt.sign({ id: user.id, email: user.email }); + return { token, user: { id: user.id, email: user.email, displayName: user.displayName } }; + }); + + app.get('/me', { preHandler: [app.authenticate] }, async (request) => { + const { id } = request.user as { id: string }; + const prisma = app.prisma; + const user = await prisma.user.findUnique({ where: { id } }); + return { user }; + }); +} diff --git a/apps/api/src/routes/nodes.ts b/apps/api/src/routes/nodes.ts new file mode 100644 index 0000000..dda4796 --- /dev/null +++ b/apps/api/src/routes/nodes.ts @@ -0,0 +1,127 @@ +import { FastifyInstance } from 'fastify'; +import { z } from 'zod'; + +const createNodeBodySchema = z.object({ + type: z.enum(['task', 'event', 'note', 'project', 'goal']), + workspaceId: z.string().uuid(), + title: z.string().min(1).max(500), + content: z.record(z.unknown()).optional(), + priority: z.number().int().min(1).max(5).optional(), + startTime: z.string().datetime().optional(), + endTime: z.string().datetime().optional(), + parentId: z.string().uuid().optional(), +}); + +export async function nodeRoutes(app: FastifyInstance) { + app.addHook('preHandler', app.authenticate); + + app.get('/nodes', async (request) => { + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + const { type, status, workspaceId } = request.query as Record; + + const nodes = await prisma.node.findMany({ + where: { + ownerId: userId, + ...(type ? { type: type as never } : {}), + ...(status ? { status: status as never } : {}), + ...(workspaceId ? { workspaceId } : {}), + }, + orderBy: { updatedAt: 'desc' }, + take: 100, + }); + + return { nodes }; + }); + + app.post<{ Body: z.infer }>('/nodes', async (request, reply) => { + const body = createNodeBodySchema.parse(request.body); + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + + const node = await prisma.node.create({ + data: { + type: body.type, + workspaceId: body.workspaceId, + ownerId: userId, + title: body.title, + content: (body.content ?? {}) as never, + priority: body.priority, + startTime: body.startTime ? new Date(body.startTime) : null, + endTime: body.endTime ? new Date(body.endTime) : null, + parentId: body.parentId, + }, + }); + + return reply.status(201).send({ node }); + }); + + app.get<{ Params: { id: string } }>('/nodes/:id', async (request, reply) => { + const { id } = request.params; + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + + const node = await prisma.node.findFirst({ + where: { id, ownerId: userId }, + include: { tags: { include: { tag: true } }, links: true, backlinks: true }, + }); + + if (!node) return reply.status(404).send({ error: 'Node not found' }); + return { node }; + }); + + app.patch<{ Params: { id: string } }>('/nodes/:id', async (request, reply) => { + const { id } = request.params; + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + + const existing = await prisma.node.findFirst({ where: { id, ownerId: userId } }); + if (!existing) return reply.status(404).send({ error: 'Node not found' }); + + const body = request.body as Record; + const node = await prisma.node.update({ + where: { id }, + data: { + ...(body.title ? { title: body.title as string } : {}), + ...(body.content ? { content: body.content as never } : {}), + ...(body.priority !== undefined ? { priority: body.priority as number } : {}), + ...(body.status ? { status: body.status as never } : {}), + version: { increment: 1 }, + }, + }); + + return { node }; + }); + + app.delete<{ Params: { id: string } }>('/nodes/:id', async (request, reply) => { + const { id } = request.params; + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + + const existing = await prisma.node.findFirst({ where: { id, ownerId: userId } }); + if (!existing) return reply.status(404).send({ error: 'Node not found' }); + + await prisma.node.update({ + where: { id }, + data: { status: 'deleted', archivedAt: new Date() }, + }); + + return reply.status(204).send(); + }); + + app.post<{ Params: { id: string } }>('/nodes/:id/restore', async (request, reply) => { + const { id } = request.params; + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + + const existing = await prisma.node.findFirst({ where: { id, ownerId: userId, status: 'deleted' } }); + if (!existing) return reply.status(404).send({ error: 'Node not found' }); + + const node = await prisma.node.update({ + where: { id }, + data: { status: 'active', archivedAt: null }, + }); + + return { node }; + }); +} diff --git a/apps/api/src/routes/search.ts b/apps/api/src/routes/search.ts new file mode 100644 index 0000000..1f853ce --- /dev/null +++ b/apps/api/src/routes/search.ts @@ -0,0 +1,34 @@ +import { FastifyInstance } from 'fastify'; +import { z } from 'zod'; + +const searchQuerySchema = z.object({ + q: z.string().min(1), + type: z.enum(['task', 'event', 'note', 'project', 'goal']).optional(), + limit: z.coerce.number().int().min(1).max(100).default(20), +}); + +export async function searchRoutes(app: FastifyInstance) { + app.addHook('preHandler', app.authenticate); + + app.get('/search', async (request) => { + const { q, type, limit } = searchQuerySchema.parse(request.query); + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + + const nodes = await prisma.node.findMany({ + where: { + ownerId: userId, + status: 'active', + ...(type ? { type: type as never } : {}), + OR: [ + { title: { contains: q, mode: 'insensitive' } }, + { plainText: { contains: q, mode: 'insensitive' } }, + ], + }, + take: limit, + orderBy: { updatedAt: 'desc' }, + }); + + return { results: nodes }; + }); +} diff --git a/apps/api/src/routes/workspaces.ts b/apps/api/src/routes/workspaces.ts new file mode 100644 index 0000000..aae3dd4 --- /dev/null +++ b/apps/api/src/routes/workspaces.ts @@ -0,0 +1,56 @@ +import { FastifyInstance } from 'fastify'; +import { createWorkspaceSchema } from '@yetanother/types'; + +export async function workspaceRoutes(app: FastifyInstance) { + app.addHook('preHandler', app.authenticate); + + app.get('/workspaces', async (request) => { + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + + const workspaces = await prisma.workspace.findMany({ + where: { + OR: [ + { ownerId: userId }, + { members: { some: { userId } } }, + ], + }, + include: { members: true }, + }); + + return { workspaces }; + }); + + app.post('/workspaces', async (request, reply) => { + const body = createWorkspaceSchema.parse(request.body); + const { id: userId } = request.user as { id: string }; + const prisma = app.prisma; + + const workspace = await prisma.workspace.create({ + data: { + name: body.name, + slug: body.slug, + description: body.description, + ownerId: userId, + members: { + create: { userId, role: 'owner' }, + }, + }, + }); + + return reply.status(201).send({ workspace }); + }); + + app.get<{ Params: { id: string } }>('/workspaces/:id', async (request, reply) => { + const { id } = request.params; + const prisma = app.prisma; + + const workspace = await prisma.workspace.findUnique({ + where: { id }, + include: { members: { include: { user: true } }, tags: true, folders: true }, + }); + + if (!workspace) return reply.status(404).send({ error: 'Workspace not found' }); + return { workspace }; + }); +} diff --git a/apps/api/src/types.d.ts b/apps/api/src/types.d.ts new file mode 100644 index 0000000..d419525 --- /dev/null +++ b/apps/api/src/types.d.ts @@ -0,0 +1,12 @@ +import 'fastify'; +import { PrismaClient } from '@yetanother/db'; + +declare module 'fastify' { + interface FastifyInstance { + prisma: PrismaClient; + authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise; + } + interface FastifyRequest { + user: { id: string; email: string }; + } +} diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json new file mode 100644 index 0000000..0059999 --- /dev/null +++ b/apps/api/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@yetanother/tsconfig/node", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist" + } +} diff --git a/apps/web/eslint.config.js b/apps/web/eslint.config.js new file mode 100644 index 0000000..b3b1954 --- /dev/null +++ b/apps/web/eslint.config.js @@ -0,0 +1,2 @@ +import react from '@yetanother/eslint-config/react'; +export default [...react]; diff --git a/apps/web/index.html b/apps/web/index.html new file mode 100644 index 0000000..af5ca03 --- /dev/null +++ b/apps/web/index.html @@ -0,0 +1,14 @@ + + + + + + + + YetAnotherSuite + + +
+ + + diff --git a/apps/web/package.json b/apps/web/package.json new file mode 100644 index 0000000..a57be85 --- /dev/null +++ b/apps/web/package.json @@ -0,0 +1,43 @@ +{ + "name": "@yetanother/web", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "eslint src/", + "typecheck": "tsc --noEmit", + "test": "vitest run", + "test:watch": "vitest", + "clean": "rm -rf .turbo node_modules dist" + }, + "dependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-router-dom": "^7.6.0", + "@yetanother/ui": "workspace:*", + "@yetanother/utils": "workspace:*", + "@yetanother/hooks": "workspace:*", + "@yetanother/types": "workspace:*", + "zustand": "^5.0.0", + "@tanstack/react-query": "^5.75.0", + "jotai": "^2.12.0" + }, + "devDependencies": { + "@yetanother/tsconfig": "workspace:*", + "@yetanother/eslint-config": "workspace:*", + "@types/react": "^19.1.0", + "@types/react-dom": "^19.1.0", + "typescript": "^5.8.0", + "vite": "^6.3.0", + "@vitejs/plugin-react": "^4.4.0", + "vitest": "^3.1.0", + "@testing-library/react": "^16.3.0", + "@testing-library/jest-dom": "^6.6.0", + "jsdom": "^26.0.0", + "eslint": "^9.25.0", + "tailwindcss": "^4.1.0", + "@tailwindcss/vite": "^4.1.0" + } +} diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx new file mode 100644 index 0000000..835f833 --- /dev/null +++ b/apps/web/src/App.tsx @@ -0,0 +1,13 @@ +import { Routes, Route } from 'react-router-dom'; +import { ToastProvider, ToastViewport } from '@yetanother/ui'; + +export function App() { + return ( + + + YetAnotherSuite} /> + + + + ); +} diff --git a/apps/web/src/index.css b/apps/web/src/index.css new file mode 100644 index 0000000..62843a1 --- /dev/null +++ b/apps/web/src/index.css @@ -0,0 +1,32 @@ +@import "tailwindcss"; + +@theme { + --color-background: hsl(0 0% 100%); + --color-foreground: hsl(222.2 84% 4.9%); + --color-primary: hsl(222.2 47.4% 11.2%); + --color-primary-foreground: hsl(210 40% 98%); + --color-secondary: hsl(210 40% 96.1%); + --color-secondary-foreground: hsl(222.2 47.4% 11.2%); + --color-muted: hsl(210 40% 96.1%); + --color-muted-foreground: hsl(215.4 16.3% 46.9%); + --color-accent: hsl(210 40% 96.1%); + --color-accent-foreground: hsl(222.2 47.4% 11.2%); + --color-destructive: hsl(0 84.2% 60.2%); + --color-destructive-foreground: hsl(210 40% 98%); + --color-border: hsl(214.3 31.8% 91.4%); + --color-input: hsl(214.3 31.8% 91.4%); + --color-ring: hsl(222.2 84% 4.9%); + --color-popover: hsl(0 0% 100%); + --color-popover-foreground: hsl(222.2 84% 4.9%); + --radius: 0.5rem; +} + +* { + border-color: var(--color-border); +} + +body { + background-color: var(--color-background); + color: var(--color-foreground); + font-family: system-ui, -apple-system, sans-serif; +} diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx new file mode 100644 index 0000000..714a9cb --- /dev/null +++ b/apps/web/src/main.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { BrowserRouter } from 'react-router-dom'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { App } from './App'; +import './index.css'; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 30_000, + retry: 1, + }, + }, +}); + +const root = document.getElementById('root'); +if (!root) throw new Error('Root element not found'); + +ReactDOM.createRoot(root).render( + + + + + + + , +); diff --git a/apps/web/src/test-setup.ts b/apps/web/src/test-setup.ts new file mode 100644 index 0000000..7b0828b --- /dev/null +++ b/apps/web/src/test-setup.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom'; diff --git a/apps/web/src/vite-env.d.ts b/apps/web/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/apps/web/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json new file mode 100644 index 0000000..d5821a3 --- /dev/null +++ b/apps/web/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@yetanother/tsconfig/react", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts new file mode 100644 index 0000000..65b8062 --- /dev/null +++ b/apps/web/vite.config.ts @@ -0,0 +1,23 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import tailwindcss from '@tailwindcss/vite'; +import path from 'path'; + +export default defineConfig({ + plugins: [react(), tailwindcss()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + server: { + port: 3000, + proxy: { + '/api': 'http://localhost:4000', + '/ws': { + target: 'ws://localhost:4000', + ws: true, + }, + }, + }, +}); diff --git a/apps/web/vitest.config.ts b/apps/web/vitest.config.ts new file mode 100644 index 0000000..6df26e4 --- /dev/null +++ b/apps/web/vitest.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'vitest/config'; +import react from '@vitejs/plugin-react'; +import path from 'path'; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + test: { + environment: 'jsdom', + setupFiles: './src/test-setup.ts', + globals: true, + }, +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..360651f --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "yetanothersuite", + "private": true, + "packageManager": "pnpm@11.15.1", + "scripts": { + "dev": "turbo dev", + "build": "turbo build", + "lint": "turbo lint", + "typecheck": "turbo typecheck", + "test": "turbo test", + "clean": "turbo clean", + "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"", + "format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"", + "prepare": "husky" + }, + "devDependencies": { + "turbo": "^2.5.0", + "prettier": "^3.5.0", + "husky": "^9.1.0", + "lint-staged": "^15.5.0" + }, + "lint-staged": { + "*.{ts,tsx,js,jsx}": ["eslint --fix", "prettier --write"], + "*.{json,md,yaml}": ["prettier --write"] + } +} diff --git a/packages/db/eslint.config.js b/packages/db/eslint.config.js new file mode 100644 index 0000000..70e29b5 --- /dev/null +++ b/packages/db/eslint.config.js @@ -0,0 +1,2 @@ +import node from '@yetanother/eslint-config/node'; +export default [...node]; diff --git a/packages/db/package.json b/packages/db/package.json new file mode 100644 index 0000000..8b9595f --- /dev/null +++ b/packages/db/package.json @@ -0,0 +1,31 @@ +{ + "name": "@yetanother/db", + "private": true, + "type": "module", + "main": "./src/client.ts", + "types": "./src/client.ts", + "scripts": { + "db:generate": "prisma generate", + "db:push": "prisma db push", + "db:migrate": "prisma migrate dev", + "db:deploy": "prisma migrate deploy", + "db:seed": "tsx prisma/seed.ts", + "db:studio": "prisma studio", + "lint": "eslint src/", + "typecheck": "tsc --noEmit", + "clean": "rm -rf .turbo node_modules prisma/migrations" + }, + "dependencies": { + "@prisma/client": "^6.6.0", + "zod": "^3.24.0" + }, + "devDependencies": { + "prisma": "^6.6.0", + "tsx": "^4.19.0", + "@yetanother/tsconfig": "workspace:*", + "@yetanother/eslint-config": "workspace:*", + "typescript": "^5.8.0", + "eslint": "^9.25.0", + "@types/node": "^22.15.0" + } +} diff --git a/packages/db/prisma/schema.prisma b/packages/db/prisma/schema.prisma new file mode 100644 index 0000000..ef8025b --- /dev/null +++ b/packages/db/prisma/schema.prisma @@ -0,0 +1,304 @@ +generator client { + provider = "prisma-client-js" +} + +datasource db { + provider = "postgresql" + url = env("DATABASE_URL") +} + +enum NodeType { + task + event + note + project + goal +} + +enum NodeStatus { + active + archived + deleted +} + +enum LinkType { + references + blocks + relates_to + parent_of + child_of + scheduled_as + prepared_for +} + +enum WorkspaceRole { + owner + admin + editor + viewer +} + +enum ReminderStatus { + pending + sent + dismissed + snoozed +} + +enum NotificationType { + push + email + sms + in_app +} + +enum ActionType { + created + updated + deleted + viewed + shared + linked + completed + ai_assisted +} + +model User { + id String @id @default(uuid()) @db.Uuid + email String @unique + displayName String @map("display_name") + avatarUrl String? @map("avatar_url") @db.VarChar + preferences Json @default("{}") + encryptionKey String? @map("encryption_key") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + lastActiveAt DateTime @default(now()) @map("last_active_at") + + nodes Node[] + ownedWorkspaces Workspace[] @relation("OwnedWorkspaces") + memberships WorkspaceMember[] + activities Activity[] + reminders Reminder[] + syncCheckpoints SyncCheckpoint[] + + @@map("users") +} + +model Workspace { + id String @id @default(uuid()) @db.Uuid + name String + slug String + description String? + settings Json @default("{}") + ownerId String @map("owner_id") @db.Uuid + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + + owner User @relation("OwnedWorkspaces", fields: [ownerId], references: [id]) + members WorkspaceMember[] + nodes Node[] + tags Tag[] + folders Folder[] + + @@unique([slug, ownerId]) + @@map("workspaces") +} + +model Node { + id String @id @default(uuid()) @db.Uuid + type NodeType + workspaceId String @map("workspace_id") @db.Uuid + ownerId String @map("owner_id") @db.Uuid + parentId String? @map("parent_id") @db.Uuid + title String + content Json @default("{}") + plainText String @default("") @map("plain_text") + status NodeStatus @default(active) + priority Int? + startTime DateTime? @map("start_time") + endTime DateTime? @map("end_time") + durationMinutes Int? @map("duration_minutes") + recurrenceRule String? @map("recurrence_rule") + completionRate Float? @map("completion_rate") + metadata Json @default("{}") + version Int @default(1) + isEncrypted Boolean @default(false) @map("is_encrypted") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @updatedAt @map("updated_at") + completedAt DateTime? @map("completed_at") + archivedAt DateTime? @map("archived_at") + + workspace Workspace @relation(fields: [workspaceId], references: [id]) + owner User @relation(fields: [ownerId], references: [id]) + parent Node? @relation("NodeHierarchy", fields: [parentId], references: [id]) + children Node[] @relation("NodeHierarchy") + tags NodeTag[] + links NodeLink[] @relation("NodeLinksSource") + backlinks NodeLink[] @relation("NodeLinksTarget") + activities Activity[] + reminders Reminder[] + attachments Attachment[] + embeddings Embedding[] + + @@index([type, status, workspaceId, ownerId]) + @@index([createdAt]) + @@map("nodes") +} + +model NodeLink { + id String @id @default(uuid()) @db.Uuid + sourceId String @map("source_id") @db.Uuid + targetId String @map("target_id") @db.Uuid + linkType LinkType @map("link_type") + strength Float @default(0.5) + isAuto Boolean @default(false) @map("is_auto") + context String? @db.Text + createdAt DateTime @default(now()) @map("created_at") + + source Node @relation("NodeLinksSource", fields: [sourceId], references: [id]) + target Node @relation("NodeLinksTarget", fields: [targetId], references: [id]) + + @@unique([sourceId, targetId, linkType]) + @@index([sourceId]) + @@index([targetId]) + @@map("node_links") +} + +model Tag { + id String @id @default(uuid()) @db.Uuid + name String + color String @db.VarChar(7) + workspaceId String @map("workspace_id") @db.Uuid + isSystem Boolean @default(false) @map("is_system") + createdAt DateTime @default(now()) @map("created_at") + + workspace Workspace @relation(fields: [workspaceId], references: [id]) + nodes NodeTag[] + + @@map("tags") +} + +model NodeTag { + nodeId String @map("node_id") @db.Uuid + tagId String @map("tag_id") @db.Uuid + + node Node @relation(fields: [nodeId], references: [id]) + tag Tag @relation(fields: [tagId], references: [id]) + + @@id([nodeId, tagId]) + @@map("node_tags") +} + +model Folder { + id String @id @default(uuid()) @db.Uuid + name String + workspaceId String @map("workspace_id") @db.Uuid + parentId String? @map("parent_id") @db.Uuid + viewType String @default("list") @map("view_type") + filterConfig Json @default("{}") @map("filter_config") + sortConfig Json @default("{}") @map("sort_config") + orderIndex Int @default(0) @map("order_index") + createdAt DateTime @default(now()) @map("created_at") + + workspace Workspace @relation(fields: [workspaceId], references: [id]) + parent Folder? @relation("FolderHierarchy", fields: [parentId], references: [id]) + children Folder[] @relation("FolderHierarchy") + + @@map("folders") +} + +model Reminder { + id String @id @default(uuid()) @db.Uuid + nodeId String @map("node_id") @db.Uuid + userId String @map("user_id") @db.Uuid + remindAt DateTime @map("remind_at") + notificationType NotificationType @map("notification_type") + status ReminderStatus @default(pending) + snoozeUntil DateTime? @map("snooze_until") + createdAt DateTime @default(now()) @map("created_at") + + node Node @relation(fields: [nodeId], references: [id]) + user User @relation(fields: [userId], references: [id]) + + @@map("reminders") +} + +model Embedding { + id String @id @default(uuid()) @db.Uuid + nodeId String @map("node_id") @db.Uuid + chunkIndex Int @map("chunk_index") + chunkText String @map("chunk_text") @db.Text + vector Unsupported("vector(1536)") + modelVersion String @map("model_version") + createdAt DateTime @default(now()) @map("created_at") + + node Node @relation(fields: [nodeId], references: [id]) + + @@index([nodeId]) + @@map("embeddings") +} + +model Activity { + id String @id @default(uuid()) @db.Uuid + userId String @map("user_id") @db.Uuid + nodeId String? @map("node_id") @db.Uuid + workspaceId String @map("workspace_id") @db.Uuid + actionType ActionType @map("action_type") + metadata Json @default("{}") + sessionId String? @map("session_id") @db.Text + createdAt DateTime @default(now()) @map("created_at") + + user User @relation(fields: [userId], references: [id]) + node Node? @relation(fields: [nodeId], references: [id]) + + @@index([createdAt]) + @@index([userId, workspaceId, actionType]) + @@map("activities") +} + +model Attachment { + id String @id @default(uuid()) @db.Uuid + nodeId String @map("node_id") @db.Uuid + filename String + mimeType String @map("mime_type") + sizeBytes Int @map("size_bytes") + storageKey String @map("storage_key") + thumbnailKey String? @map("thumbnail_key") + uploadedBy String @map("uploaded_by") @db.Uuid + createdAt DateTime @default(now()) @map("created_at") + + node Node @relation(fields: [nodeId], references: [id]) + + @@map("attachments") +} + +model WorkspaceMember { + id String @id @default(uuid()) @db.Uuid + workspaceId String @map("workspace_id") @db.Uuid + userId String @map("user_id") @db.Uuid + role WorkspaceRole + permissions Json @default("{}") + joinedAt DateTime @default(now()) @map("joined_at") + lastAccessedAt DateTime @default(now()) @map("last_accessed_at") + + workspace Workspace @relation(fields: [workspaceId], references: [id]) + user User @relation(fields: [userId], references: [id]) + + @@unique([workspaceId, userId]) + @@map("workspace_members") +} + +model SyncCheckpoint { + id String @id @default(uuid()) @db.Uuid + userId String @map("user_id") @db.Uuid + deviceId String @map("device_id") + lastSyncAt DateTime @default(now()) @map("last_sync_at") + syncToken String? @map("sync_token") + deviceInfo Json @default("{}") @map("device_info") + updatedAt DateTime @updatedAt @map("updated_at") + + user User @relation(fields: [userId], references: [id]) + + @@unique([userId, deviceId]) + @@map("sync_checkpoints") +} diff --git a/packages/db/prisma/seed.ts b/packages/db/prisma/seed.ts new file mode 100644 index 0000000..c702ab6 --- /dev/null +++ b/packages/db/prisma/seed.ts @@ -0,0 +1,47 @@ +import { PrismaClient } from '@prisma/client'; + +const prisma = new PrismaClient(); + +async function main() { + const user = await prisma.user.upsert({ + where: { email: 'dev@yetanothersuite.dev' }, + update: {}, + create: { + email: 'dev@yetanothersuite.dev', + displayName: 'Dev User', + preferences: { + theme: 'system', + timezone: 'UTC', + notificationSettings: { push: true, email: true, inApp: true }, + defaultViews: { tasks: 'list', calendar: 'week', notes: 'list' }, + }, + }, + }); + + const workspace = await prisma.workspace.upsert({ + where: { slug_ownerId: { slug: 'personal', ownerId: user.id } }, + update: {}, + create: { + name: 'Personal', + slug: 'personal', + description: 'My personal workspace', + ownerId: user.id, + settings: { + defaultView: 'list', + aiEnabled: true, + retentionPolicy: 'forever', + }, + }, + }); + + console.log({ user: user.id, workspace: workspace.id }); +} + +main() + .catch((e) => { + console.error(e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + }); diff --git a/packages/db/src/client.ts b/packages/db/src/client.ts new file mode 100644 index 0000000..8b8bd2f --- /dev/null +++ b/packages/db/src/client.ts @@ -0,0 +1,15 @@ +import { PrismaClient } from '@prisma/client'; + +const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined }; + +export const prisma = + globalForPrisma.prisma ?? + new PrismaClient({ + log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'], + }); + +if (process.env.NODE_ENV !== 'production') { + globalForPrisma.prisma = prisma; +} + +export * from '@prisma/client'; diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json new file mode 100644 index 0000000..0ba25a7 --- /dev/null +++ b/packages/db/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@yetanother/tsconfig/node", + "include": ["src", "prisma"], + "compilerOptions": { + "outDir": "./dist" + } +} diff --git a/packages/hooks/eslint.config.js b/packages/hooks/eslint.config.js new file mode 100644 index 0000000..b3b1954 --- /dev/null +++ b/packages/hooks/eslint.config.js @@ -0,0 +1,2 @@ +import react from '@yetanother/eslint-config/react'; +export default [...react]; diff --git a/packages/hooks/package.json b/packages/hooks/package.json new file mode 100644 index 0000000..f49d119 --- /dev/null +++ b/packages/hooks/package.json @@ -0,0 +1,22 @@ +{ + "name": "@yetanother/hooks", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "scripts": { + "lint": "eslint src/", + "typecheck": "tsc --noEmit", + "clean": "rm -rf .turbo node_modules" + }, + "dependencies": { + "react": "^19.1.0" + }, + "devDependencies": { + "@yetanother/tsconfig": "workspace:*", + "@yetanother/eslint-config": "workspace:*", + "@types/react": "^19.1.0", + "typescript": "^5.8.0", + "eslint": "^9.25.0" + } +} diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts new file mode 100644 index 0000000..313e165 --- /dev/null +++ b/packages/hooks/src/index.ts @@ -0,0 +1,3 @@ +export { useDebounce } from './useDebounce'; +export { useLocalStorage } from './useLocalStorage'; +export { useMediaQuery } from './useMediaQuery'; diff --git a/packages/hooks/src/useDebounce.ts b/packages/hooks/src/useDebounce.ts new file mode 100644 index 0000000..a878bd2 --- /dev/null +++ b/packages/hooks/src/useDebounce.ts @@ -0,0 +1,12 @@ +import { useState, useEffect } from 'react'; + +export function useDebounce(value: T, delay: number): T { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const timer = setTimeout(() => setDebouncedValue(value), delay); + return () => clearTimeout(timer); + }, [value, delay]); + + return debouncedValue; +} diff --git a/packages/hooks/src/useLocalStorage.ts b/packages/hooks/src/useLocalStorage.ts new file mode 100644 index 0000000..fd4ba3d --- /dev/null +++ b/packages/hooks/src/useLocalStorage.ts @@ -0,0 +1,23 @@ +import { useState, useCallback } from 'react'; + +export function useLocalStorage(key: string, initialValue: T) { + const [storedValue, setStoredValue] = useState(() => { + try { + const item = window.localStorage.getItem(key); + return item ? (JSON.parse(item) as T) : initialValue; + } catch { + return initialValue; + } + }); + + const setValue = useCallback( + (value: T | ((val: T) => T)) => { + const valueToStore = value instanceof Function ? value(storedValue) : value; + setStoredValue(valueToStore); + window.localStorage.setItem(key, JSON.stringify(valueToStore)); + }, + [key, storedValue], + ); + + return [storedValue, setValue] as const; +} diff --git a/packages/hooks/src/useMediaQuery.ts b/packages/hooks/src/useMediaQuery.ts new file mode 100644 index 0000000..7629b4b --- /dev/null +++ b/packages/hooks/src/useMediaQuery.ts @@ -0,0 +1,19 @@ +import { useState, useEffect } from 'react'; + +export function useMediaQuery(query: string): boolean { + const [matches, setMatches] = useState(() => { + if (typeof window !== 'undefined') { + return window.matchMedia(query).matches; + } + return false; + }); + + useEffect(() => { + const mediaQuery = window.matchMedia(query); + const handler = (event: MediaQueryListEvent) => setMatches(event.matches); + mediaQuery.addEventListener('change', handler); + return () => mediaQuery.removeEventListener('change', handler); + }, [query]); + + return matches; +} diff --git a/packages/hooks/tsconfig.json b/packages/hooks/tsconfig.json new file mode 100644 index 0000000..eebb0e7 --- /dev/null +++ b/packages/hooks/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@yetanother/tsconfig/react", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist" + } +} diff --git a/packages/types/eslint.config.js b/packages/types/eslint.config.js new file mode 100644 index 0000000..23022f0 --- /dev/null +++ b/packages/types/eslint.config.js @@ -0,0 +1,2 @@ +import base from '@yetanother/eslint-config/base'; +export default [...base]; diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 0000000..323713b --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,21 @@ +{ + "name": "@yetanother/types", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "scripts": { + "lint": "eslint src/", + "typecheck": "tsc --noEmit", + "clean": "rm -rf .turbo node_modules" + }, + "dependencies": { + "zod": "^3.24.0" + }, + "devDependencies": { + "@yetanother/tsconfig": "workspace:*", + "@yetanother/eslint-config": "workspace:*", + "typescript": "^5.8.0", + "eslint": "^9.25.0" + } +} diff --git a/packages/types/src/common.ts b/packages/types/src/common.ts new file mode 100644 index 0000000..c4db9da --- /dev/null +++ b/packages/types/src/common.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; + +export const uuidSchema = z.string().uuid(); + +export const timestampSchema = z.string().datetime(); + +export const paginationSchema = z.object({ + limit: z.coerce.number().int().min(1).max(100).default(50), + offset: z.coerce.number().int().min(0).default(0), +}); + +export type Pagination = z.infer; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts new file mode 100644 index 0000000..f8dc5b5 --- /dev/null +++ b/packages/types/src/index.ts @@ -0,0 +1,4 @@ +export * from './node'; +export * from './user'; +export * from './workspace'; +export * from './common'; diff --git a/packages/types/src/node.ts b/packages/types/src/node.ts new file mode 100644 index 0000000..c37824c --- /dev/null +++ b/packages/types/src/node.ts @@ -0,0 +1,113 @@ +import { z } from 'zod'; +import { uuidSchema, timestampSchema } from './common'; + +export const nodeTypeSchema = z.enum(['task', 'event', 'note', 'project', 'goal']); +export type NodeType = z.infer; + +export const nodeStatusSchema = z.enum(['active', 'archived', 'deleted']); +export type NodeStatus = z.infer; + +export const linkTypeSchema = z.enum([ + 'references', + 'blocks', + 'relates_to', + 'parent_of', + 'child_of', + 'scheduled_as', + 'prepared_for', +]); +export type LinkType = z.infer; + +export const nodeSchema = z.object({ + id: uuidSchema, + type: nodeTypeSchema, + workspaceId: uuidSchema, + ownerId: uuidSchema, + parentId: uuidSchema.nullable(), + title: z.string().min(1).max(500), + content: z.record(z.unknown()).default({}), + plainText: z.string().default(''), + status: nodeStatusSchema.default('active'), + priority: z.number().int().min(1).max(5).nullable(), + startTime: z.string().datetime().nullable(), + endTime: z.string().datetime().nullable(), + durationMinutes: z.number().int().min(0).nullable(), + recurrenceRule: z.string().nullable(), + completionRate: z.number().min(0).max(1).nullable(), + metadata: z.record(z.unknown()).default({}), + version: z.number().int().default(1), + isEncrypted: z.boolean().default(false), + createdAt: timestampSchema, + updatedAt: timestampSchema, + completedAt: timestampSchema.nullable(), + archivedAt: timestampSchema.nullable(), +}); + +export const createNodeSchema = nodeSchema.pick({ + type: true, + workspaceId: true, + title: true, + content: true, + priority: true, + startTime: true, + endTime: true, + durationMinutes: true, + recurrenceRule: true, + parentId: true, + metadata: true, +}); + +export const updateNodeSchema = nodeSchema.partial().pick({ + title: true, + content: true, + status: true, + priority: true, + startTime: true, + endTime: true, + durationMinutes: true, + recurrenceRule: true, + metadata: true, + parentId: true, +}); + +export type Node = z.infer; +export type CreateNodeInput = z.infer; +export type UpdateNodeInput = z.infer; + +export const nodeLinkSchema = z.object({ + id: uuidSchema, + sourceId: uuidSchema, + targetId: uuidSchema, + linkType: linkTypeSchema, + strength: z.number().min(0).max(1).default(0.5), + isAuto: z.boolean().default(false), + context: z.string().nullable(), + createdAt: timestampSchema, +}); + +export type NodeLink = z.infer; + +export const tagSchema = z.object({ + id: uuidSchema, + name: z.string().min(1).max(50), + color: z.string().regex(/^#[0-9a-fA-F]{6}$/), + workspaceId: uuidSchema, + isSystem: z.boolean().default(false), + createdAt: timestampSchema, +}); + +export type Tag = z.infer; + +export const folderSchema = z.object({ + id: uuidSchema, + name: z.string().min(1).max(100), + workspaceId: uuidSchema, + parentId: uuidSchema.nullable(), + viewType: z.enum(['list', 'board', 'calendar', 'gallery']).default('list'), + filterConfig: z.record(z.unknown()).default({}), + sortConfig: z.record(z.unknown()).default({}), + orderIndex: z.number().int().default(0), + createdAt: timestampSchema, +}); + +export type Folder = z.infer; diff --git a/packages/types/src/user.ts b/packages/types/src/user.ts new file mode 100644 index 0000000..da8c731 --- /dev/null +++ b/packages/types/src/user.ts @@ -0,0 +1,33 @@ +import { z } from 'zod'; +import { uuidSchema, timestampSchema } from './common'; + +export const userSchema = z.object({ + id: uuidSchema, + email: z.string().email(), + displayName: z.string().min(1).max(100), + avatarUrl: z.string().url().nullable(), + preferences: z.object({ + theme: z.enum(['light', 'dark', 'system']).default('system'), + timezone: z.string().default('UTC'), + notificationSettings: z.object({ + push: z.boolean().default(true), + email: z.boolean().default(true), + inApp: z.boolean().default(true), + }).default({}), + defaultViews: z.object({ + tasks: z.enum(['list', 'board', 'calendar']).default('list'), + calendar: z.enum(['day', 'week', 'month']).default('week'), + notes: z.enum(['list', 'grid']).default('list'), + }).default({}), + }).default({}), + createdAt: timestampSchema, + updatedAt: timestampSchema, + lastActiveAt: timestampSchema, +}); + +export const createUserSchema = userSchema.pick({ email: true, displayName: true }); +export const updateUserSchema = userSchema.partial().pick({ displayName: true, avatarUrl: true, preferences: true }); + +export type User = z.infer; +export type CreateUserInput = z.infer; +export type UpdateUserInput = z.infer; diff --git a/packages/types/src/workspace.ts b/packages/types/src/workspace.ts new file mode 100644 index 0000000..29f2176 --- /dev/null +++ b/packages/types/src/workspace.ts @@ -0,0 +1,40 @@ +import { z } from 'zod'; +import { uuidSchema, timestampSchema } from './common'; + +export const workspaceSchema = z.object({ + id: uuidSchema, + name: z.string().min(1).max(100), + slug: z.string().min(1).max(50), + description: z.string().max(500).nullable(), + settings: z.object({ + defaultView: z.enum(['list', 'board', 'calendar', 'gallery']).default('list'), + colorScheme: z.string().optional(), + aiEnabled: z.boolean().default(true), + retentionPolicy: z.enum(['forever', '30d', '90d', '1y']).default('forever'), + }).default({}), + ownerId: uuidSchema, + createdAt: timestampSchema, + updatedAt: timestampSchema, +}); + +export const createWorkspaceSchema = workspaceSchema.pick({ name: true, slug: true, description: true }); +export const updateWorkspaceSchema = workspaceSchema.partial().pick({ name: true, description: true, settings: true }); + +export type Workspace = z.infer; +export type CreateWorkspaceInput = z.infer; +export type UpdateWorkspaceInput = z.infer; + +export const workspaceRoleSchema = z.enum(['owner', 'admin', 'editor', 'viewer']); +export type WorkspaceRole = z.infer; + +export const workspaceMemberSchema = z.object({ + id: uuidSchema, + workspaceId: uuidSchema, + userId: uuidSchema, + role: workspaceRoleSchema, + permissions: z.record(z.unknown()).default({}), + joinedAt: timestampSchema, + lastAccessedAt: timestampSchema, +}); + +export type WorkspaceMember = z.infer; diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json new file mode 100644 index 0000000..4203857 --- /dev/null +++ b/packages/types/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@yetanother/tsconfig/base", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist" + } +} diff --git a/packages/ui/eslint.config.js b/packages/ui/eslint.config.js new file mode 100644 index 0000000..b3b1954 --- /dev/null +++ b/packages/ui/eslint.config.js @@ -0,0 +1,2 @@ +import react from '@yetanother/eslint-config/react'; +export default [...react]; diff --git a/packages/ui/package.json b/packages/ui/package.json new file mode 100644 index 0000000..fda3ff2 --- /dev/null +++ b/packages/ui/package.json @@ -0,0 +1,36 @@ +{ + "name": "@yetanother/ui", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "scripts": { + "lint": "eslint src/", + "typecheck": "tsc --noEmit", + "clean": "rm -rf .turbo node_modules" + }, + "dependencies": { + "react": "^19.1.0", + "clsx": "^2.1.0", + "tailwind-merge": "^3.2.0", + "@yetanother/utils": "workspace:*", + "@radix-ui/react-slot": "^1.2.0", + "@radix-ui/react-dialog": "^1.1.0", + "@radix-ui/react-dropdown-menu": "^2.1.0", + "@radix-ui/react-tooltip": "^1.2.0", + "@radix-ui/react-popover": "^1.1.0", + "@radix-ui/react-tabs": "^1.1.0", + "@radix-ui/react-toast": "^1.2.0", + "@radix-ui/react-label": "^2.1.0", + "lucide-react": "^0.510.0", + "@tanstack/react-query": "^5.75.0" + }, + "devDependencies": { + "@yetanother/tsconfig": "workspace:*", + "@yetanother/eslint-config": "workspace:*", + "@types/react": "^19.1.0", + "typescript": "^5.8.0", + "eslint": "^9.25.0", + "tailwindcss": "^4.1.0" + } +} diff --git a/packages/ui/src/button.tsx b/packages/ui/src/button.tsx new file mode 100644 index 0000000..a269249 --- /dev/null +++ b/packages/ui/src/button.tsx @@ -0,0 +1,49 @@ +import * as React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cn } from '@yetanother/utils'; + +const buttonVariants = { + default: 'bg-primary text-primary-foreground hover:bg-primary/90', + destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90', + outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', + secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'hover:bg-accent hover:text-accent-foreground', + link: 'text-primary underline-offset-4 hover:underline', +} as const; + +const buttonSizes = { + default: 'h-10 px-4 py-2', + sm: 'h-9 rounded-md px-3', + lg: 'h-11 rounded-md px-8', + icon: 'h-10 w-10', +} as const; + +type ButtonVariant = keyof typeof buttonVariants; +type ButtonSize = keyof typeof buttonSizes; + +interface ButtonProps extends React.ButtonHTMLAttributes { + variant?: ButtonVariant; + size?: ButtonSize; + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant = 'default', size = 'default', asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : 'button'; + return ( + + ); + }, +); +Button.displayName = 'Button'; + +export { Button, type ButtonProps, type ButtonVariant, type ButtonSize }; diff --git a/packages/ui/src/dialog.tsx b/packages/ui/src/dialog.tsx new file mode 100644 index 0000000..8b369f1 --- /dev/null +++ b/packages/ui/src/dialog.tsx @@ -0,0 +1,67 @@ +import * as React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { X } from 'lucide-react'; +import { cn } from '@yetanother/utils'; + +const Dialog = DialogPrimitive.Root; +const DialogTrigger = DialogPrimitive.Trigger; +const DialogPortal = DialogPrimitive.Portal; +const DialogClose = DialogPrimitive.Close; + +const DialogOverlay = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = 'DialogHeader'; + +const DialogTitle = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +export { Dialog, DialogPortal, DialogOverlay, DialogTrigger, DialogClose, DialogContent, DialogHeader, DialogTitle }; diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts new file mode 100644 index 0000000..e053e8a --- /dev/null +++ b/packages/ui/src/index.ts @@ -0,0 +1,6 @@ +export * from './button'; +export * from './dialog'; +export * from './toast'; +export * from './tooltip'; +export * from './tabs'; +export * from './label'; diff --git a/packages/ui/src/label.tsx b/packages/ui/src/label.tsx new file mode 100644 index 0000000..8c6d6bb --- /dev/null +++ b/packages/ui/src/label.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import * as LabelPrimitive from '@radix-ui/react-label'; +import { cn } from '@yetanother/utils'; + +const Label = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; diff --git a/packages/ui/src/tabs.tsx b/packages/ui/src/tabs.tsx new file mode 100644 index 0000000..3ec9250 --- /dev/null +++ b/packages/ui/src/tabs.tsx @@ -0,0 +1,52 @@ +import * as React from 'react'; +import * as TabsPrimitive from '@radix-ui/react-tabs'; +import { cn } from '@yetanother/utils'; + +const Tabs = TabsPrimitive.Root; + +const TabsList = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsList.displayName = TabsPrimitive.List.displayName; + +const TabsTrigger = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; + +const TabsContent = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsContent.displayName = TabsPrimitive.Content.displayName; + +export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/packages/ui/src/toast.tsx b/packages/ui/src/toast.tsx new file mode 100644 index 0000000..cea9509 --- /dev/null +++ b/packages/ui/src/toast.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import * as ToastPrimitives from '@radix-ui/react-toast'; +import { cn } from '@yetanother/utils'; + +const ToastProvider = ToastPrimitives.Provider; + +const ToastViewport = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ToastViewport.displayName = ToastPrimitives.Viewport.displayName; + +interface ToastProps extends React.ComponentPropsWithoutRef { + variant?: 'default' | 'destructive'; +} + +const Toast = React.forwardRef< + React.ComponentRef, + ToastProps +>(({ className, variant = 'default', ...props }, ref) => { + return ( + + ); +}); +Toast.displayName = ToastPrimitives.Root.displayName; + +export { ToastProvider, ToastViewport, Toast, type ToastProps }; diff --git a/packages/ui/src/tooltip.tsx b/packages/ui/src/tooltip.tsx new file mode 100644 index 0000000..dbcb23b --- /dev/null +++ b/packages/ui/src/tooltip.tsx @@ -0,0 +1,27 @@ +import * as React from 'react'; +import * as TooltipPrimitive from '@radix-ui/react-tooltip'; +import { cn } from '@yetanother/utils'; + +const TooltipProvider = TooltipPrimitive.Provider; + +const Tooltip = TooltipPrimitive.Root; + +const TooltipTrigger = TooltipPrimitive.Trigger; + +const TooltipContent = React.forwardRef< + React.ComponentRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json new file mode 100644 index 0000000..eebb0e7 --- /dev/null +++ b/packages/ui/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@yetanother/tsconfig/react", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist" + } +} diff --git a/packages/utils/eslint.config.js b/packages/utils/eslint.config.js new file mode 100644 index 0000000..23022f0 --- /dev/null +++ b/packages/utils/eslint.config.js @@ -0,0 +1,2 @@ +import base from '@yetanother/eslint-config/base'; +export default [...base]; diff --git a/packages/utils/package.json b/packages/utils/package.json new file mode 100644 index 0000000..ed8ac28 --- /dev/null +++ b/packages/utils/package.json @@ -0,0 +1,22 @@ +{ + "name": "@yetanother/utils", + "private": true, + "type": "module", + "main": "./src/index.ts", + "types": "./src/index.ts", + "scripts": { + "lint": "eslint src/", + "typecheck": "tsc --noEmit", + "clean": "rm -rf .turbo node_modules" + }, + "dependencies": { + "clsx": "^2.1.0", + "tailwind-merge": "^3.2.0" + }, + "devDependencies": { + "@yetanother/tsconfig": "workspace:*", + "@yetanother/eslint-config": "workspace:*", + "typescript": "^5.8.0", + "eslint": "^9.25.0" + } +} diff --git a/packages/utils/src/cn.ts b/packages/utils/src/cn.ts new file mode 100644 index 0000000..9ad0df4 --- /dev/null +++ b/packages/utils/src/cn.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/packages/utils/src/constants.ts b/packages/utils/src/constants.ts new file mode 100644 index 0000000..2f7c08f --- /dev/null +++ b/packages/utils/src/constants.ts @@ -0,0 +1,14 @@ +export const API_VERSION = 'v1'; +export const API_PREFIX = `/api/${API_VERSION}`; + +export const TRASH_RETENTION_DAYS = 30; +export const SYNC_DEBOUNCE_MS = 1500; +export const SEARCH_DEBOUNCE_MS = 300; + +export const PRIORITY_LABELS: Record = { + 1: 'P1 - Critical', + 2: 'P2 - High', + 3: 'P3 - Medium', + 4: 'P4 - Low', + 5: 'P5 - Wishlist', +}; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts new file mode 100644 index 0000000..af78bd6 --- /dev/null +++ b/packages/utils/src/index.ts @@ -0,0 +1,2 @@ +export * from './cn'; +export * from './constants'; diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json new file mode 100644 index 0000000..4203857 --- /dev/null +++ b/packages/utils/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@yetanother/tsconfig/base", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..b48013a --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,7470 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + husky: + specifier: ^9.1.0 + version: 9.1.7 + lint-staged: + specifier: ^15.5.0 + version: 15.5.2(supports-color@7.2.0) + prettier: + specifier: ^3.5.0 + version: 3.9.5 + turbo: + specifier: ^2.5.0 + version: 2.10.5 + + apps/api: + dependencies: + '@fastify/cookie': + specifier: ^11.0.0 + version: 11.1.2 + '@fastify/cors': + specifier: ^11.0.0 + version: 11.3.0 + '@fastify/helmet': + specifier: ^13.0.0 + version: 13.1.0 + '@fastify/jwt': + specifier: ^9.0.0 + version: 9.1.0 + '@fastify/rate-limit': + specifier: ^10.2.0 + version: 10.3.0 + '@fastify/redis': + specifier: ^7.0.0 + version: 7.2.0(supports-color@7.2.0) + '@fastify/swagger': + specifier: ^9.5.0 + version: 9.8.1(supports-color@7.2.0) + '@fastify/swagger-ui': + specifier: ^5.2.0 + version: 5.2.6 + '@fastify/websocket': + specifier: ^11.0.0 + version: 11.3.0 + '@yetanother/db': + specifier: workspace:* + version: link:../../packages/db + '@yetanother/types': + specifier: workspace:* + version: link:../../packages/types + '@yetanother/utils': + specifier: workspace:* + version: link:../../packages/utils + fastify: + specifier: ^5.3.0 + version: 5.10.0 + ioredis: + specifier: ^5.6.0 + version: 5.11.1(supports-color@7.2.0) + pino: + specifier: ^9.6.0 + version: 9.14.0 + pino-pretty: + specifier: ^13.1.0 + version: 13.1.3 + zod: + specifier: ^3.24.0 + version: 3.25.76 + devDependencies: + '@types/node': + specifier: ^22.15.0 + version: 22.20.1 + '@yetanother/eslint-config': + specifier: workspace:* + version: link:../../tooling/eslint + '@yetanother/tsconfig': + specifier: workspace:* + version: link:../../tooling/typescript + eslint: + specifier: ^9.25.0 + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + tsx: + specifier: ^4.19.0 + version: 4.23.1 + typescript: + specifier: ^5.8.0 + version: 5.9.3 + vitest: + specifier: ^3.1.0 + version: 3.2.7(@types/node@22.20.1)(jiti@2.7.0)(jsdom@26.1.0(supports-color@7.2.0))(lightningcss@1.32.0)(supports-color@7.2.0)(tsx@4.23.1)(yaml@2.9.0) + + apps/web: + dependencies: + '@tanstack/react-query': + specifier: ^5.75.0 + version: 5.101.2(react@19.2.7) + '@yetanother/hooks': + specifier: workspace:* + version: link:../../packages/hooks + '@yetanother/types': + specifier: workspace:* + version: link:../../packages/types + '@yetanother/ui': + specifier: workspace:* + version: link:../../packages/ui + '@yetanother/utils': + specifier: workspace:* + version: link:../../packages/utils + jotai: + specifier: ^2.12.0 + version: 2.20.2(@babel/core@7.29.7(supports-color@7.2.0))(@babel/template@7.29.7)(@types/react@19.2.17)(react@19.2.7) + react: + specifier: ^19.1.0 + version: 19.2.7 + react-dom: + specifier: ^19.1.0 + version: 19.2.7(react@19.2.7) + react-router-dom: + specifier: ^7.6.0 + version: 7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + zustand: + specifier: ^5.0.0 + version: 5.0.14(@types/react@19.2.17)(react@19.2.7) + devDependencies: + '@tailwindcss/vite': + specifier: ^4.1.0 + version: 4.3.3(vite@6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0)) + '@testing-library/jest-dom': + specifier: ^6.6.0 + version: 6.9.1 + '@testing-library/react': + specifier: ^16.3.0 + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@types/react': + specifier: ^19.1.0 + version: 19.2.17 + '@types/react-dom': + specifier: ^19.1.0 + version: 19.2.3(@types/react@19.2.17) + '@vitejs/plugin-react': + specifier: ^4.4.0 + version: 4.7.0(supports-color@7.2.0)(vite@6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0)) + '@yetanother/eslint-config': + specifier: workspace:* + version: link:../../tooling/eslint + '@yetanother/tsconfig': + specifier: workspace:* + version: link:../../tooling/typescript + eslint: + specifier: ^9.25.0 + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + jsdom: + specifier: ^26.0.0 + version: 26.1.0(supports-color@7.2.0) + tailwindcss: + specifier: ^4.1.0 + version: 4.3.3 + typescript: + specifier: ^5.8.0 + version: 5.9.3 + vite: + specifier: ^6.3.0 + version: 6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0) + vitest: + specifier: ^3.1.0 + version: 3.2.7(@types/node@22.20.1)(jiti@2.7.0)(jsdom@26.1.0(supports-color@7.2.0))(lightningcss@1.32.0)(supports-color@7.2.0)(tsx@4.23.1)(yaml@2.9.0) + + packages/db: + dependencies: + '@prisma/client': + specifier: ^6.6.0 + version: 6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3) + zod: + specifier: ^3.24.0 + version: 3.25.76 + devDependencies: + '@types/node': + specifier: ^22.15.0 + version: 22.20.1 + '@yetanother/eslint-config': + specifier: workspace:* + version: link:../../tooling/eslint + '@yetanother/tsconfig': + specifier: workspace:* + version: link:../../tooling/typescript + eslint: + specifier: ^9.25.0 + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + prisma: + specifier: ^6.6.0 + version: 6.19.3(typescript@5.9.3) + tsx: + specifier: ^4.19.0 + version: 4.23.1 + typescript: + specifier: ^5.8.0 + version: 5.9.3 + + packages/hooks: + dependencies: + react: + specifier: ^19.1.0 + version: 19.2.7 + devDependencies: + '@types/react': + specifier: ^19.1.0 + version: 19.2.17 + '@yetanother/eslint-config': + specifier: workspace:* + version: link:../../tooling/eslint + '@yetanother/tsconfig': + specifier: workspace:* + version: link:../../tooling/typescript + eslint: + specifier: ^9.25.0 + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + typescript: + specifier: ^5.8.0 + version: 5.9.3 + + packages/types: + dependencies: + zod: + specifier: ^3.24.0 + version: 3.25.76 + devDependencies: + '@yetanother/eslint-config': + specifier: workspace:* + version: link:../../tooling/eslint + '@yetanother/tsconfig': + specifier: workspace:* + version: link:../../tooling/typescript + eslint: + specifier: ^9.25.0 + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + typescript: + specifier: ^5.8.0 + version: 5.9.3 + + packages/ui: + dependencies: + '@radix-ui/react-dialog': + specifier: ^1.1.0 + version: 1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-dropdown-menu': + specifier: ^2.1.0 + version: 2.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-label': + specifier: ^2.1.0 + version: 2.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-popover': + specifier: ^1.1.0 + version: 1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': + specifier: ^1.2.0 + version: 1.3.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-tabs': + specifier: ^1.1.0 + version: 1.1.17(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-toast': + specifier: ^1.2.0 + version: 1.2.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-tooltip': + specifier: ^1.2.0 + version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@tanstack/react-query': + specifier: ^5.75.0 + version: 5.101.2(react@19.2.7) + '@yetanother/utils': + specifier: workspace:* + version: link:../utils + clsx: + specifier: ^2.1.0 + version: 2.1.1 + lucide-react: + specifier: ^0.510.0 + version: 0.510.0(react@19.2.7) + react: + specifier: ^19.1.0 + version: 19.2.7 + tailwind-merge: + specifier: ^3.2.0 + version: 3.6.0 + devDependencies: + '@types/react': + specifier: ^19.1.0 + version: 19.2.17 + '@yetanother/eslint-config': + specifier: workspace:* + version: link:../../tooling/eslint + '@yetanother/tsconfig': + specifier: workspace:* + version: link:../../tooling/typescript + eslint: + specifier: ^9.25.0 + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + tailwindcss: + specifier: ^4.1.0 + version: 4.3.3 + typescript: + specifier: ^5.8.0 + version: 5.9.3 + + packages/utils: + dependencies: + clsx: + specifier: ^2.1.0 + version: 2.1.1 + tailwind-merge: + specifier: ^3.2.0 + version: 3.6.0 + devDependencies: + '@yetanother/eslint-config': + specifier: workspace:* + version: link:../../tooling/eslint + '@yetanother/tsconfig': + specifier: workspace:* + version: link:../../tooling/typescript + eslint: + specifier: ^9.25.0 + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + typescript: + specifier: ^5.8.0 + version: 5.9.3 + + tooling/eslint: + dependencies: + '@typescript-eslint/eslint-plugin': + specifier: ^8.30.0 + version: 8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/parser': + specifier: ^8.30.0 + version: 8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + eslint: + specifier: ^9.25.0 + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + eslint-config-prettier: + specifier: ^10.1.0 + version: 10.1.8(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) + eslint-plugin-react: + specifier: ^7.37.0 + version: 7.37.5(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) + eslint-plugin-react-hooks: + specifier: ^5.2.0 + version: 5.2.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) + + tooling/typescript: {} + +packages: + + '@adobe/css-tools@4.5.0': + resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==} + + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + engines: {node: '>=6.9.0'} + + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.28.1': + resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.28.1': + resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.28.1': + resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.28.1': + resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.28.1': + resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.1': + resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.28.1': + resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.28.1': + resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.28.1': + resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.28.1': + resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.28.1': + resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.28.1': + resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.28.1': + resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.28.1': + resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.28.1': + resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.28.1': + resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.28.1': + resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.28.1': + resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.1': + resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.28.1': + resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.28.1': + resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.28.1': + resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.28.1': + resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.28.1': + resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.28.1': + resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.28.1': + resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.6': + resolution: {integrity: sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.5': + resolution: {integrity: sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@fastify/accept-negotiator@2.0.1': + resolution: {integrity: sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==} + + '@fastify/ajv-compiler@4.0.5': + resolution: {integrity: sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==} + + '@fastify/cookie@11.1.2': + resolution: {integrity: sha512-Dtrpk/YOGUsbRMvP/8ZqPpwnMRv0qSqodFdoQ2B589Obc7jw4s4Qla+cV72Bsm7WsZJnqlYFX/i7uSBq0xzg6g==} + + '@fastify/cors@11.3.0': + resolution: {integrity: sha512-ggQGua+xHv1MvePbPr0v//xLYEsCXbWspquXCJS9Ot5YoRXq8J8ZWzHnxDBVnbtXosvistXo6LtNzOJswf64Fw==} + + '@fastify/error@4.2.0': + resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==} + + '@fastify/fast-json-stringify-compiler@5.1.0': + resolution: {integrity: sha512-PxcYtKLbQ8Z+yApiqjK8FwxIwvEj38k2OiLc17u8dkJSlmfi2wHHPaSnaoqBPQqtvF8YVsDgDpP2snDCfFrpfw==} + + '@fastify/forwarded@3.0.1': + resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==} + + '@fastify/helmet@13.1.0': + resolution: {integrity: sha512-SvVOU0IrzYJW1BvSkfq9G1WUdW3dnaRUvg6m0BtgGMBmML62No0VmSu087jecH58SFbicbREgZTPJ89mAguupA==} + + '@fastify/jwt@9.1.0': + resolution: {integrity: sha512-CiGHCnS5cPMdb004c70sUWhQTfzrJHAeTywt7nVw6dAiI0z1o4WRvU94xfijhkaId4bIxTCOjFgn4sU+Gvk43w==} + + '@fastify/merge-json-schemas@0.2.1': + resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} + + '@fastify/proxy-addr@5.1.0': + resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==} + + '@fastify/rate-limit@10.3.0': + resolution: {integrity: sha512-eIGkG9XKQs0nyynatApA3EVrojHOuq4l6fhB4eeCk4PIOeadvOJz9/4w3vGI44Go17uaXOWEcPkaD8kuKm7g6Q==} + + '@fastify/redis@7.2.0': + resolution: {integrity: sha512-Ql8emmkajVBCCz0pRjPFZRFI2069Jrp/iufKb5TJwgBeu7B+oZp+GeZIgf+4WX3EX7Vi/h3KTyGf+5DUWI1oFw==} + + '@fastify/send@4.1.0': + resolution: {integrity: sha512-TMYeQLCBSy2TOFmV95hQWkiTYgC/SEx7vMdV+wnZVX4tt8VBLKzmH8vV9OzJehV0+XBfg+WxPMt5wp+JBUKsVw==} + + '@fastify/static@9.3.0': + resolution: {integrity: sha512-9YMYRpCOtMBrqKYWcqiw7ykOrn4D0jogHpJrFS0KGeSuOwzKMM5/mjj7B0CFLVoQ6htqKYw//Zs7APn9DBq05w==} + + '@fastify/swagger-ui@5.2.6': + resolution: {integrity: sha512-OMnms0O5s9wb6wis/K5nlrAMLsgUbr1GA8uphM41IasWe3AFdgxz6r/3bA9HTxlDNUYc2FGGKeqMp3ntxmSiNA==} + + '@fastify/swagger@9.8.1': + resolution: {integrity: sha512-VpHMnqZTY8iBZYJE8WWkbKPrXIYWy2rDfIf5qLr6DzZSpQYZ+KxQVcJFiq/AMlvNwI4gCBd66++iUlxXXGT0IQ==} + + '@fastify/websocket@11.3.0': + resolution: {integrity: sha512-g89ag4BCcD9YP5wBZXixzoLnuf5j89p/sXFcfpCiv2pdEkYYukBEoK3heVzqsp0EAtszVDc2BBZG0KZqeAShIA==} + + '@floating-ui/core@1.8.0': + resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} + + '@floating-ui/dom@1.8.0': + resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} + + '@floating-ui/react-dom@2.1.9': + resolution: {integrity: sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.12': + resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} + + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@ioredis/commands@1.10.0': + resolution: {integrity: sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@lukeed/ms@2.0.2': + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} + + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + + '@prisma/client@6.19.3': + resolution: {integrity: sha512-mKq3jQFhjvko5LTJFHGilsuQs+W+T3Gm451NzuTDGQxwCzwXHYnIu2zGkRoW+Exq3Rob7yp2MfzSrdIiZVhrBg==} + engines: {node: '>=18.18'} + peerDependencies: + prisma: '*' + typescript: '>=5.1.0' + peerDependenciesMeta: + prisma: + optional: true + typescript: + optional: true + + '@prisma/config@6.19.3': + resolution: {integrity: sha512-CBPT44BjlQxEt8kiMEauji2WHTDoVBOKl7UlewXmUgBPnr/oPRZC3psci5chJnYmH0ivEIog2OU9PGWoki3DLQ==} + + '@prisma/debug@6.19.3': + resolution: {integrity: sha512-ljkJ+SgpXNktLG0Q/n4JGYCkKf0f8oYLyjImS2I8e2q2WCfdRRtWER062ZV/ixaNP2M2VKlWXVJiGzZaUgbKZw==} + + '@prisma/engines-version@7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7': + resolution: {integrity: sha512-03bgb1VD5gvuumNf+7fVGBzfpJPjmqV423l/WxsWk2cNQ42JD0/SsFBPhN6z8iAvdHs07/7ei77SKu7aZfq8bA==} + + '@prisma/engines@6.19.3': + resolution: {integrity: sha512-RSYxtlYFl5pJ8ZePgMv0lZ9IzVCOdTPOegrs2qcbAEFrBI1G33h6wyC9kjQvo0DnYEhEVY0X4LsuFHXLKQk88g==} + + '@prisma/fetch-engine@6.19.3': + resolution: {integrity: sha512-tKtl/qco9Nt7LU5iKhpultD8O4vMCZcU2CHjNTnRrL1QvSUr5W/GcyFPjNL87GtRrwBc7ubXXD9xy4EvLvt8JA==} + + '@prisma/get-platform@6.19.3': + resolution: {integrity: sha512-xFj1VcJ1N3MKooOQAGO0W5tsd0W2QzIvW7DD7c/8H14Zmp4jseeWAITm+w2LLoLrlhoHdPPh0NMZ8mfL6puoHA==} + + '@radix-ui/primitive@1.1.5': + resolution: {integrity: sha512-d86WIWFYNtGA0H/d8exstrTRTp7eWJYlYJbtNofxr/3ljupZYn6EFDG/Qgu/0Kc8v7yMUxySagqJsL1+PdYjWg==} + + '@radix-ui/react-arrow@1.1.11': + resolution: {integrity: sha512-Kdil9BB1rIFC/khmf4hC35bn8701AJcizTU7G7cUbEbk5XqqbjDuHW60uUfKqO5WojjZcbAW51Q7P0hRmMLw8A==} + 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 + + '@radix-ui/react-collection@1.1.12': + resolution: {integrity: sha512-nb67INpE0IahJKN7EYPp9m9YGwYeKlnzxT3MwXVkgCskaSJia97kG4T0ywpjNUSSnoJk/uvk12V8vbrEHEj+/Q==} + 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 + + '@radix-ui/react-compose-refs@1.1.3': + resolution: {integrity: sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context@1.2.0': + resolution: {integrity: sha512-fOE+JtN9rygNZkCnHRBEP0TAvLldlhyOxMsbwFvTP4nAs+nBmfnna+o/Zski2wkmY1YMrFC0aSzsHoLY47iLrg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dialog@1.1.19': + resolution: {integrity: sha512-+HhbN2+YtkRgVirjZ2afMeutQRuGOrdkWR5+EFC58SJojGmtyNQwYzgi6tHBpOxvFHefMtPeHdgtjz0BOGxFQg==} + 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 + + '@radix-ui/react-direction@1.1.2': + resolution: {integrity: sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.15': + resolution: {integrity: sha512-b0XaRlzn2QKuo10XyNgi2DAJDf5XC9d1nD3FJcuvCjbR7+4Ad28zmZsLsqx+hvDEzMnRuZaZxZm9gYObV6RmRA==} + 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 + + '@radix-ui/react-dropdown-menu@2.1.20': + resolution: {integrity: sha512-slfm+rRaZRuQBvHq60lXvSVUPhid0IPtjSZzIuUlWZMUs01iYZNlGS3mJgRD3ChLQVBAYlKiL/tFyWGX+dz8Xw==} + 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 + + '@radix-ui/react-focus-guards@1.1.4': + resolution: {integrity: sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.12': + resolution: {integrity: sha512-jjk/lqTeNL0azUx5ZYzVrl4NgaDIrdzTNE4mABV9yBFI7FQqN7pIgzV1bTleUezP2QiTGA1BFTqY8MegDgWX9A==} + 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 + + '@radix-ui/react-id@1.1.2': + resolution: {integrity: sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-label@2.1.11': + resolution: {integrity: sha512-3PKvDDxOn62k0oV1n4QtNtD2vpu+zYjXR7ojLBPaO6SPvhy53yg0vAmgNeBQeJW5rV3dffoRG+HYfLBZuzw0CQ==} + 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 + + '@radix-ui/react-menu@2.1.20': + resolution: {integrity: sha512-VsUrXxFe9d2ScbZF0fR/oPR1+qjyeLs5p0jzG8h90puMoA9bq4SirYlXbE+USRg9Q2qTeJSFNqjw2nts8jJe4w==} + 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 + + '@radix-ui/react-popover@1.1.19': + resolution: {integrity: sha512-jkrTdQVxnIB8fpn0NyyxW9CTB5aCXZZelVz5z+Xmii6g5WxMqS3fInNslZ63puP39+Puu4jYohUK31y3dT87gQ==} + 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 + + '@radix-ui/react-popper@1.3.3': + resolution: {integrity: sha512-mS7dGpyjv6b+gsDjLF7e0ia1W4Im1B1hSCy2yuXlHuvnZxHKagfDaobt/KAKt27EpZMit2pss8eJBVyVjEWM+g==} + 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 + + '@radix-ui/react-portal@1.1.13': + resolution: {integrity: sha512-z3oXfmaHLJTF1wktbjgD6cn9jiEbq3WSondB10LIuIt2m2Ym4iJlrW04/euMwENDdWDdE7z+OuY7Qyp1YpRSwA==} + 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 + + '@radix-ui/react-presence@1.1.7': + resolution: {integrity: sha512-zBZ4QM5XG3JRanDmqXYf3MD6th4AFXFmgU6KNMFzUaV6F3uw9I5/zjMUvFriSEn5ewo1nxuibvyxJdmLlDcslA==} + 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 + + '@radix-ui/react-primitive@2.1.7': + resolution: {integrity: sha512-bC3NiwsprbxKjuon9l7X6BUTw7FPVzEYaL92MPEY5SCd/9hUTPXVFtVwRix7778wtRsVao+zE062gL79FZleeQ==} + 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 + + '@radix-ui/react-roving-focus@1.1.15': + resolution: {integrity: sha512-40svmmugfM3mUN7VUDGVE1tQGOhyi8enlGD0CNJEcMM36C1f71PKM21DFgNHUfem0XnA+d8H8oN3Z9ZpJjSslg==} + 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 + + '@radix-ui/react-slot@1.3.0': + resolution: {integrity: sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-tabs@1.1.17': + resolution: {integrity: sha512-nRyXnrAVCwjeXcHbvEbLS6ndbTeKHG1RqCP4A8Gw5L4cemDzPXdD8rAmr6wet0v57R69wGvuIIsFjHSVkZiMzQ==} + 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 + + '@radix-ui/react-toast@1.2.19': + resolution: {integrity: sha512-SxfVZfVOibWKWdkf0Xx1awW2d09fQu4V4PXDY1j5hi4MVf7MWdJZqTBJMa1KWtOr1S6GGtCk02nniZ0Iia+dHw==} + 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 + + '@radix-ui/react-tooltip@1.2.12': + resolution: {integrity: sha512-U3HoftgWnmla78vzQbLvKKb7bUYJxoiiqYFzp1wu/TBMyDqMZSuCl3aRICsD6EfVEwcJD2mumGDGUXLFVqQHKA==} + 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 + + '@radix-ui/react-use-callback-ref@1.1.2': + resolution: {integrity: sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.2.3': + resolution: {integrity: sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.3': + resolution: {integrity: sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-is-hydrated@0.1.1': + resolution: {integrity: sha512-qwOiz4Tjo8CNnrOLAYUMXeZwDzXgXpvK4TKQPmWLECM9XoWvA6+0Z2/7Ag3A4ivjS4ovbLJPbskkxioFyBhr8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.2': + resolution: {integrity: sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-rect@1.1.2': + resolution: {integrity: sha512-d8a+bBY/FxikNPlgJJoaBHZX+zKVbWHYJGTLnLvveQgFSTntkGdEKv3JDtHrMS0DNYpllz2nRsTLGLKYttbpmw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-size@1.1.2': + resolution: {integrity: sha512-giWQp+4mxjBPt4KZ0MmyuykFNWfbDxKt4x+fPkRYmgRFJSbCZFzUglvMb/Kjn38tm10YP4ufiQZDx3zna4LU6w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-visually-hidden@1.2.7': + resolution: {integrity: sha512-1wNZBggTDK3GRuuQ6nP4k2yi7a6l7I5qbMPbZcRsrGsGVead/f/d5FhEzUvqFs0bcrDLx7n1zKQ3JvLR6whaaw==} + 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 + + '@radix-ui/rect@1.1.2': + resolution: {integrity: sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==} + + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + + '@rollup/rollup-android-arm-eabi@4.62.2': + resolution: {integrity: sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.62.2': + resolution: {integrity: sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.62.2': + resolution: {integrity: sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.62.2': + resolution: {integrity: sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.62.2': + resolution: {integrity: sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.62.2': + resolution: {integrity: sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.62.2': + resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.62.2': + resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.62.2': + resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.62.2': + resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.62.2': + resolution: {integrity: sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.62.2': + resolution: {integrity: sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + resolution: {integrity: sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + resolution: {integrity: sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.62.2': + resolution: {integrity: sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.62.2': + resolution: {integrity: sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==} + cpu: [x64] + os: [win32] + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + + '@tailwindcss/oxide-android-arm64@4.3.3': + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.3': + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.3': + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.3.3': + resolution: {integrity: sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + + '@tanstack/query-core@5.101.2': + resolution: {integrity: sha512-hH5MLoJhF7KaIGd7q3xTXGXvslI+GYlM1Z/35aSHHWaCJWB7XvTSHYuV3eM7tw+aE0mT/xMro4M4Q9rCGHT0lw==} + + '@tanstack/react-query@5.101.2': + resolution: {integrity: sha512-seDkr6kzGzX1okaaTtZPtgA688CDPlXUz1C6xSg0ESqn04Vuc8tlrYms1s3de+znBqhPVxFRfpAfUf+6XvfPWg==} + peerDependencies: + react: ^18 || ^19 + + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.3.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@turbo/darwin-64@2.10.5': + resolution: {integrity: sha512-ENvPwy3x5yS7MwNYHeWjqOBXkwIMp39Pd+/zXC6PoiNzF8EIvvLZOZZ+ny6L9x4WgS5vxUii2LM5gM+zjPdnWw==} + cpu: [x64] + os: [darwin] + + '@turbo/darwin-arm64@2.10.5': + resolution: {integrity: sha512-rqROo9zsF/P9RqsdtbLD1nFJicjSrYyvQ9kNJC38AbxA3pAs6VAlATvtvOFx7bqOv6vicf20SP9kF33avJjy2w==} + cpu: [arm64] + os: [darwin] + + '@turbo/linux-64@2.10.5': + resolution: {integrity: sha512-RoSSiNFUxi27zLJuM9F6GyWWjHgLch9t6nwD6K0FkXRirZkTLlzIj6IhFnK8H9++nefLtdFqylE4vGjZAv6AAA==} + cpu: [x64] + os: [linux] + + '@turbo/linux-arm64@2.10.5': + resolution: {integrity: sha512-4ZComcpzmHGmVynQqvvi+iZOSq/tBvY1SltXB8g4NZRsrA01W8E+yRL8RNM+PLoyWsrCnJa8xa+DkWkv+xg4iQ==} + cpu: [arm64] + os: [linux] + + '@turbo/windows-64@2.10.5': + resolution: {integrity: sha512-eL2Iyj4DbMINq1Sr1w0iAi6nAiZOF16KSlRGwCJpVh+IWZeY33MAsLHVOBMj1xoFtncVJXclCVpTPL2nBoYkFg==} + cpu: [x64] + os: [win32] + + '@turbo/windows-arm64@2.10.5': + resolution: {integrity: sha512-sog+wP+8YSJrdWZ/rUJg8xghVTrwoG+BrSlDQpnK5fzSgJHn1INRWXbVWRH0d3vX8dBI01E3yxXRre9Dn+OXQA==} + cpu: [arm64] + os: [win32] + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@22.20.1': + resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==} + + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.17': + resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + + '@typescript-eslint/eslint-plugin@8.64.0': + resolution: {integrity: sha512-CGvQPBxN3wZLu6Rz2kFUpZeoCm78xUic92ck39KPePkO1NPOwjCqdQnm5Q87tpWw9vcBvW8XLrDXjH9PWYtJ3Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.64.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.64.0': + resolution: {integrity: sha512-KA0OshtlcCCXmbfqyZkM5pV3/WNraJf7DkJRLpyrmwPtud57H5BDX7C3k0LPSPxpprfRL+cJDGabF10mvNCoCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.64.0': + resolution: {integrity: sha512-tk4WpOJ6IEbGrVHaNmM0YRrwAD3exZlIK3iadQNAxh4YKk6jvUQ4ecq18n+v7+meh+cJ3j+D8nbk8sRKhlwLQg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.64.0': + resolution: {integrity: sha512-CXEaFdYXjSTgKhisNkwCcJwTP8Pl+fmRrEQrri4nm3vU743bALrxzLmq7fHG/7e6a5xO0lDYeURpZmBuhHk54w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.64.0': + resolution: {integrity: sha512-2yo8rRNKuzbVWQp5kslhANqZ2uDAeROQHBRZNPu8JDsHmeFNj/XJJhX/FhNUWmkHHvoNsKa6+tHJiig87EzsQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.64.0': + resolution: {integrity: sha512-XWG4Fmmv/6SvyS9nH8jWrKs6terwJvE8cyRt1CzYYqzp9OrPhCT4cMc/f7C6RZCwG+qMmiffJS1/qJP8G1URtg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.64.0': + resolution: {integrity: sha512-qjhfuTfLXjA4IOzXvz0rTjT01BqEiIgPoUeMwiEjnaHKJMTNo8rH5pYW1a2L/0Dnux2fPC85AeyJoWaGa8WxTA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.64.0': + resolution: {integrity: sha512-Pztpsn1aCE1oWDvDEfUk31nngvvF7vUB5SwHFEaZIFpvw7WJtqUHHL4plBZDA9HfWJJjL13BdG0YrJInTUvoVA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.64.0': + resolution: {integrity: sha512-aJUGVB3+U0htrrCjoA8qukw8cm8fNCGAxK/tVoS70k8aeb7DETKeFozRiVFIwEeN9WJLsjaP3ph8I60tY2XZoQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.64.0': + resolution: {integrity: sha512-mrtuL8Nsn6gi2H4mo5KMTp823M+3Q19Ew/i+Zlikq20tIMm99C3Ez0dCmkWWnxut20esQvTg8aUSEhMcAOXhEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + + '@vitest/expect@3.2.7': + resolution: {integrity: sha512-E8eBXaKibuvH2pSZErOjdVb5vF4PbKYcrnluBTYxEk1l/VhhwZg1kZQsdtjq+CsF5CFydf2Rdkz7jDHKSisi3w==} + + '@vitest/mocker@3.2.7': + resolution: {integrity: sha512-Trr0hYO9CM3Wj6ksWHRhK9IZpIY6wTMO5u/MqXurMxT57sWBaOPEtP3Oq60ihZuh5JsiagKfz95OcxdEP6dBrA==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.7': + resolution: {integrity: sha512-KUHlwqVu0sRlhCdyPdQ/wBoTfRahjUky1MubOmYw9fWfIZy1gNoHpuaaQBPAaMaVYdQYHJLurzj8ECCj5OwTqA==} + + '@vitest/runner@3.2.7': + resolution: {integrity: sha512-sB9y4ovltoQP+WaUPwmSxO9WIg9Ig694Di5PalVPsYHklAdE027mehpWF2SQSVq+k6sFgaivbTjTJwZLSHbedA==} + + '@vitest/snapshot@3.2.7': + resolution: {integrity: sha512-7C+MwShwtBSI5Buwoyg3s/iY1eHL9PKAf+O1wVh/TdnjXUtkoL/9YQtre90i4MtNXM6edP1wJ2zOBpfCyhIS7g==} + + '@vitest/spy@3.2.7': + resolution: {integrity: sha512-Q2eQGI6d2L/hBtZ0qNuKcAGid68XK6cv1xsoaIma6PaJhHPoqcEJhYpXZ/5myCMqkNgtP6UKuBhbc0nHKnrkuQ==} + + '@vitest/utils@3.2.7': + resolution: {integrity: sha512-x6BDOd7dyo3PFLY3I9/HJ25X/6OurhGXk2/B9gOZNPF7XDVjeBK4k01lQE5uvDpbuheErh91qYuE1E2OEjK3Rw==} + + abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} + engines: {node: '>=18'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-includes@3.1.9: + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + asn1.js@5.4.1: + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + avvio@9.3.0: + resolution: {integrity: sha512-g2tQ7LE7oOSqDfwEm3M+ZCMTJc7KiZCdJ4UwyZJb5ckTKyYu50OYmvv0mCFXPuYXoM4zkSt8zM9XQ9KCvxA74A==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + baseline-browser-mapping@2.10.43: + resolution: {integrity: sha512-AjYpR78kDWAY3Efj+cDTFH9t9SCoL7OoTp1BOb0mQV7S+6CiLwnWM3FyxhJtdPufDFKzmCSFoUncKjWgJEZTCQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + bn.js@4.12.5: + resolution: {integrity: sha512-3aRg6/JxfffFD+OlOjOFR3Vo79l39ooBTFucxx+MT3dhCtzn3EmiUPQo+6/OZuI2jbXi3YKgmiTFBgChQMwIRQ==} + + brace-expansion@1.1.16: + resolution: {integrity: sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==} + + brace-expansion@5.0.7: + resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==} + engines: {node: 18 || 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.6: + resolution: {integrity: sha512-FQBYNK15VMslhLHpA7+n+n1GOlF1kId2xcCg7/j95f24AOF6VDYMNH4mFxF7KuaTdv627faazpOAjFzMrfJOUw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + c12@3.1.0: + resolution: {integrity: sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==} + peerDependencies: + magicast: ^0.3.5 + peerDependenciesMeta: + magicast: + optional: true + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001806: + resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + citty@0.1.6: + resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + + citty@0.2.2: + resolution: {integrity: sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + cluster-key-slot@1.1.1: + resolution: {integrity: sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==} + engines: {node: '>=0.10.0'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.2.4: + resolution: {integrity: sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + + content-disposition@1.1.0: + resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} + engines: {node: '>=18'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + cookie@2.0.1: + resolution: {integrity: sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==} + engines: {node: '>=22'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge-ts@7.1.5: + resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==} + engines: {node: '>=16.0.0'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexify@4.1.3: + resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + effect@3.21.0: + resolution: {integrity: sha512-PPN80qRokCd1f015IANNhrwOnLO7GrrMQfk4/lnZRE/8j7UPWrNNjPV0uBrZutI/nHzernbW+J0hdqQysHiSnQ==} + + electron-to-chromium@1.5.393: + resolution: {integrity: sha512-kiDJdIUawuEIcp9XoICKp1iTYDEbgguIPq526N1Q7jIQDeQ3CqoMx71025PI/7E48Ddtw2HuWsVjY7afEgNxmg==} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + enhanced-resolve@5.24.2: + resolution: {integrity: sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw==} + engines: {node: '>=10.13.0'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + es-abstract-get@1.0.0: + resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==} + engines: {node: '>= 0.4'} + + es-abstract@1.24.2: + resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.4.0: + resolution: {integrity: sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.4: + resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==} + engines: {node: '>= 0.4'} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.28.1: + resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-react-hooks@5.2.0: + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@9.39.5: + resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + + exsolve@1.1.0: + resolution: {integrity: sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw==} + + fast-check@3.23.2: + resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} + engines: {node: '>=8.0.0'} + + fast-copy@4.0.4: + resolution: {integrity: sha512-eVAiWVNPSEGIzDl5yPuLrx8fNMogScXvD9xp1Kzd41FjRIz2I3sSIcxsFeM5EzFfHAfobdvs8ZySffUopljvIA==} + + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-json-stringify@7.0.1: + resolution: {integrity: sha512-eRSayARSbbwlBjpP4vnTTIRD5QPcIrmihPxDeN1DtKnHPg66UuJLx+8hlK1kaFdjvzyQ/dzALoi4vwAQ+T+iZA==} + + fast-jwt@5.0.6: + resolution: {integrity: sha512-LPE7OCGUl11q3ZgW681cEU2d0d2JZ37hhJAmetCgNyW8waVaJVZXhyFF6U2so1Iim58Yc7pfxJe2P7MNetQH2g==} + engines: {node: '>=20'} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-uri@3.1.4: + resolution: {integrity: sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==} + + fast-uri@4.1.1: + resolution: {integrity: sha512-YPOs1zD5TG2+EZt+r88LwF6mclA7TPkpwMP7ZN3TO2HiHS8TXvq7QA/17iJsV9dubcLo/f8eEYqMBruyQV21hQ==} + + fastfall@1.5.1: + resolution: {integrity: sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==} + engines: {node: '>=0.10.0'} + + fastify-plugin@5.1.0: + resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} + + fastify-plugin@6.0.0: + resolution: {integrity: sha512-fZOty7z3O7vOliF6d8bHE3wiEh1KcNnKEQensSgTk9C1DvN6nRLS++XVd86v33Hw/8u9Un8A1zDrQ8ujcQDHEg==} + + fastify@5.10.0: + resolution: {integrity: sha512-A9L0ziuWGQHgEEVgF3davQ9vbD93IuX+lo2IsxapQmu5b/Y/ynn9m9K5JHt9dvyJXOFc5iN0Zk5GHEOqnzhWjg==} + + fastparallel@2.4.1: + resolution: {integrity: sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fastseries@1.7.2: + resolution: {integrity: sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-my-way@9.6.0: + resolution: {integrity: sha512-Zf4Xve4RymLl7NgaavNebZ01joJ8MfVerOG43wy7SHLO+r+K0C6d/SE0BiR7AV5V1VOCFlOP7ecdo+I4qmiHrQ==} + engines: {node: '>=20'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.2.0: + resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + giget@2.0.0: + resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} + hasBin: true + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + helmet@8.3.0: + resolution: {integrity: sha512-Qgpiaws3Sm30Av8Eah6sjMCZZwjlBu+E68rhpCWBshY1lb09HtLwj5GviX0OyQIn+ulUS0iX0AxN5n3tLZzz1w==} + engines: {node: '>=18.0.0'} + + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} + engines: {node: '>=18'} + hasBin: true + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.6: + resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + ioredis@5.11.1: + resolution: {integrity: sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A==} + engines: {node: '>=12.22.0'} + + ipaddr.js@2.4.0: + resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} + engines: {node: '>= 10'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-document.all@1.0.0: + resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.1.0: + resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==} + engines: {node: '>=18'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + jotai@2.20.2: + resolution: {integrity: sha512-aHB4CNb9qRcyf0mwSB6EO5bCGAjx8cTwFgOFCE2leOnTzqACbnSWG8XoWB3LxCT1Qoj03I1OWAHszDmN4uHb/w==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@babel/core': '>=7.0.0' + '@babel/template': '>=7.0.0' + '@types/react': '>=17.0.0' + react: '>=17.0.0' + peerDependenciesMeta: + '@babel/core': + optional: true + '@babel/template': + optional: true + '@types/react': + optional: true + react: + optional: true + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + + js-yaml@4.3.0: + resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + hasBin: true + + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-ref-resolver@3.0.0: + resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==} + + json-schema-resolver@3.0.0: + resolution: {integrity: sha512-HqMnbz0tz2DaEJ3ntsqtx3ezzZyDE7G56A/pPY/NGmrPu76UzsWquOpHFRAf5beTNXoH2LU5cQePVvRli1nchA==} + engines: {node: '>=20'} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + light-my-request@6.6.0: + resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lint-staged@15.5.2: + resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.3.3: + resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==} + engines: {node: '>=18.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lucide-react@0.510.0: + resolution: {integrity: sha512-p8SQRAMVh7NhsAIETokSqDrc5CHnDLbV29mMnzaXx+Vc/hnqQzwI2r0FMWCcoTXnbw2KEjy48xwpGdEL+ck06Q==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + mnemonist@0.40.4: + resolution: {integrity: sha512-ZAv+KNavneRVzu4tUeOgzkScI3W5BGwZ3rkxIpKtzzVgfTtWQFN1CgX0U72cyvyh3iTuHL3SiSmrQxTlryEIcw==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.16: + resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-exports-info@1.6.2: + resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==} + engines: {node: '>= 0.4'} + + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + + node-releases@2.0.51: + resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + engines: {node: '>=18'} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + nwsapi@2.2.24: + resolution: {integrity: sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==} + + nypm@0.6.8: + resolution: {integrity: sha512-Q9K4Diu6l5u6xJQogeFSs/zKtyMSgFKFtRQV+tHP4kL7KPm2grpBU0dFIwFaXwNxN0MtfKWc43VpCugAa+LPsw==} + engines: {node: '>=18'} + hasBin: true + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + obliterator@2.0.5: + resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==} + + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + + perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + pidtree@0.6.1: + resolution: {integrity: sha512-e0F9AOF1JMrCfBsyJOwU9lNvQ0WtXTq0j/4jk0BQ5JSI9VAybPXmDpPRw/2FQ3e5d3ZFN1mLh7jW99m/jjaptw==} + engines: {node: '>=0.10'} + hasBin: true + + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-abstract-transport@3.0.0: + resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} + + pino-pretty@13.1.3: + resolution: {integrity: sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==} + hasBin: true + + pino-std-serializers@7.1.0: + resolution: {integrity: sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==} + + pino@9.14.0: + resolution: {integrity: sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==} + hasBin: true + + pkg-types@2.3.1: + resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss@8.5.20: + resolution: {integrity: sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.9.5: + resolution: {integrity: sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + prisma@6.19.3: + resolution: {integrity: sha512-++ZJ0ijLrDJF6hNB4t4uxg2br3fC4H9Yc9tcbjr2fcNFP3rh/SBNrAgjhsqBU4Ght8JPrVofG/ZkXfnSfnYsFg==} + engines: {node: '>=18.18'} + hasBin: true + peerDependencies: + typescript: '>=5.1.0' + peerDependenciesMeta: + typescript: + optional: true + + process-warning@4.0.1: + resolution: {integrity: sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==} + + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + rc9@2.1.2: + resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + + react-dom@19.2.7: + resolution: {integrity: sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==} + peerDependencies: + react: ^19.2.7 + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.2: + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-router-dom@7.18.1: + resolution: {integrity: sha512-KaZh+X/6UtEp28x51AUYZDMg9NGoz2ja3dNHa+ta/tk40vCzKhQ/RypCWBMLbmDr6//E24Vv5uPsrqXFozdkAg==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + + react-router@7.18.1: + resolution: {integrity: sha512-GDLgg3i3uM0aeJO3Fm+TCS+sDQ7gu12T6x0qdTEzcwqEfleci7JwugVNIF3U//0FWKnJT7ptG+20B2jfDqnZAg==} + engines: {node: '>=20.0.0'} + peerDependencies: + react: '>=18' + react-dom: '>=18' + peerDependenciesMeta: + react-dom: + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react@19.2.7: + resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} + engines: {node: '>=0.10.0'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve@2.0.0-next.7: + resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + ret@0.5.0: + resolution: {integrity: sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==} + engines: {node: '>=10'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rollup@4.62.2: + resolution: {integrity: sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + safe-array-concat@1.1.4: + resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safe-regex2@5.1.1: + resolution: {integrity: sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==} + hasBin: true + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + set-cookie-parser@2.7.2: + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.2: + resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} + engines: {node: '>=18'} + + sonic-boom@4.2.1: + resolution: {integrity: sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + steed@1.1.3: + resolution: {integrity: sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA==} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.11: + resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.10: + resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tailwind-merge@3.6.0: + resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} + + tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + thread-stream@3.2.0: + resolution: {integrity: sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toad-cache@3.7.4: + resolution: {integrity: sha512-m1TdR/rvT7kgGJZhspNtXdsdYk0fddFpJJFlG5s+UkPFo6lkLoZ3YLOaovPYjq1R75NP5JfeTlSHaOsE09peCg==} + engines: {node: '>=20'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.23.1: + resolution: {integrity: sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==} + engines: {node: '>=18.0.0'} + hasBin: true + + turbo@2.10.5: + resolution: {integrity: sha512-07Y/C7OUp23l4P92PJoYtFNbHjLhftrZH5Ce7dbczS4kX2Re+wtbXvZLoxn/pUtzgsQaRCBaRuZPJp4zmAn0WQ==} + hasBin: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.8: + resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} + engines: {node: '>= 0.4'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.4.3: + resolution: {integrity: sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@3.2.7: + resolution: {integrity: sha512-KrxIJ62Fd89gfysR4WotlgZABiz2dqFPgqGzX7s+CwsqLFomRH7777ZcrOD6+WVAh7khPQP41A+BKbpcJFrdEg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.7 + '@vitest/ui': 3.2.7 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.22: + resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@8.21.1: + resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@2.9.0: + resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==} + engines: {node: '>= 14.6'} + hasBin: true + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zustand@5.0.14: + resolution: {integrity: sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + +snapshots: + + '@adobe/css-tools@4.5.0': {} + + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7(supports-color@7.2.0)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@7.2.0) + '@babel/types': 7.29.7 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@7.2.0) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.7': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.6 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7(supports-color@7.2.0)': + dependencies: + '@babel/traverse': 7.29.7(supports-color@7.2.0) + '@babel/types': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))(supports-color@7.2.0)': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0) + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/parser@7.29.7': + dependencies: + '@babel/types': 7.29.7 + + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7(supports-color@7.2.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/runtime@7.29.7': {} + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@babel/traverse@7.29.7(supports-color@7.2.0)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.7': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/aix-ppc64@0.28.1': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.28.1': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-arm@0.28.1': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/android-x64@0.28.1': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.28.1': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.28.1': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.28.1': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.28.1': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.28.1': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-arm@0.28.1': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.28.1': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.28.1': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.28.1': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.28.1': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.28.1': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.28.1': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/linux-x64@0.28.1': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.28.1': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.28.1': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.28.1': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.28.1': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.28.1': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.28.1': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.28.1': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.28.1': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@esbuild/win32-x64@0.28.1': + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))': + dependencies: + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.2(supports-color@7.2.0)': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3(supports-color@7.2.0) + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.6(supports-color@7.2.0)': + dependencies: + ajv: 6.15.0 + debug: 4.4.3(supports-color@7.2.0) + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.3.0 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.5': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@fastify/accept-negotiator@2.0.1': {} + + '@fastify/ajv-compiler@4.0.5': + dependencies: + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 3.1.4 + + '@fastify/cookie@11.1.2': + dependencies: + cookie: 2.0.1 + fastify-plugin: 6.0.0 + + '@fastify/cors@11.3.0': + dependencies: + fastify-plugin: 6.0.0 + toad-cache: 3.7.4 + + '@fastify/error@4.2.0': {} + + '@fastify/fast-json-stringify-compiler@5.1.0': + dependencies: + fast-json-stringify: 7.0.1 + + '@fastify/forwarded@3.0.1': {} + + '@fastify/helmet@13.1.0': + dependencies: + fastify-plugin: 6.0.0 + helmet: 8.3.0 + + '@fastify/jwt@9.1.0': + dependencies: + '@fastify/error': 4.2.0 + '@lukeed/ms': 2.0.2 + fast-jwt: 5.0.6 + fastify-plugin: 5.1.0 + steed: 1.1.3 + + '@fastify/merge-json-schemas@0.2.1': + dependencies: + dequal: 2.0.3 + + '@fastify/proxy-addr@5.1.0': + dependencies: + '@fastify/forwarded': 3.0.1 + ipaddr.js: 2.4.0 + + '@fastify/rate-limit@10.3.0': + dependencies: + '@lukeed/ms': 2.0.2 + fastify-plugin: 5.1.0 + toad-cache: 3.7.4 + + '@fastify/redis@7.2.0(supports-color@7.2.0)': + dependencies: + fastify-plugin: 5.1.0 + ioredis: 5.11.1(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + '@fastify/send@4.1.0': + dependencies: + '@lukeed/ms': 2.0.2 + escape-html: 1.0.3 + fast-decode-uri-component: 1.0.1 + http-errors: 2.0.1 + mime: 3.0.0 + + '@fastify/static@9.3.0': + dependencies: + '@fastify/accept-negotiator': 2.0.1 + '@fastify/send': 4.1.0 + content-disposition: 1.1.0 + fastify-plugin: 6.0.0 + fastq: 1.20.1 + glob: 13.0.6 + + '@fastify/swagger-ui@5.2.6': + dependencies: + '@fastify/static': 9.3.0 + fastify-plugin: 5.1.0 + openapi-types: 12.1.3 + rfdc: 1.4.1 + yaml: 2.9.0 + + '@fastify/swagger@9.8.1(supports-color@7.2.0)': + dependencies: + fastify-plugin: 6.0.0 + json-schema-resolver: 3.0.0(supports-color@7.2.0) + openapi-types: 12.1.3 + rfdc: 1.4.1 + yaml: 2.9.0 + transitivePeerDependencies: + - supports-color + + '@fastify/websocket@11.3.0': + dependencies: + duplexify: 4.1.3 + fastify-plugin: 6.0.0 + ws: 8.21.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@floating-ui/core@1.8.0': + dependencies: + '@floating-ui/utils': 0.2.12 + + '@floating-ui/dom@1.8.0': + dependencies: + '@floating-ui/core': 1.8.0 + '@floating-ui/utils': 0.2.12 + + '@floating-ui/react-dom@2.1.9(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@floating-ui/dom': 1.8.0 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + + '@floating-ui/utils@0.2.12': {} + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@ioredis/commands@1.10.0': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@lukeed/ms@2.0.2': {} + + '@pinojs/redact@0.4.0': {} + + '@prisma/client@6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3)': + optionalDependencies: + prisma: 6.19.3(typescript@5.9.3) + typescript: 5.9.3 + + '@prisma/config@6.19.3': + dependencies: + c12: 3.1.0 + deepmerge-ts: 7.1.5 + effect: 3.21.0 + empathic: 2.0.0 + transitivePeerDependencies: + - magicast + + '@prisma/debug@6.19.3': {} + + '@prisma/engines-version@7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7': {} + + '@prisma/engines@6.19.3': + dependencies: + '@prisma/debug': 6.19.3 + '@prisma/engines-version': 7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7 + '@prisma/fetch-engine': 6.19.3 + '@prisma/get-platform': 6.19.3 + + '@prisma/fetch-engine@6.19.3': + dependencies: + '@prisma/debug': 6.19.3 + '@prisma/engines-version': 7.1.1-3.c2990dca591cba766e3b7ef5d9e8a84796e47ab7 + '@prisma/get-platform': 6.19.3 + + '@prisma/get-platform@6.19.3': + dependencies: + '@prisma/debug': 6.19.3 + + '@radix-ui/primitive@1.1.5': {} + + '@radix-ui/react-arrow@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-collection@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-compose-refs@1.1.3(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-context@1.2.0(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-dialog@1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + aria-hidden: 1.2.6 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-direction@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-dismissable-layer@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-effect-event': 0.0.3(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-dropdown-menu@2.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-menu': 2.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-focus-guards@1.1.4(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-focus-scope@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-id@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-label@2.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-menu@2.1.20(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-collection': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-popper': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + aria-hidden: 1.2.6 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-popover@1.1.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-focus-guards': 1.1.4(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-focus-scope': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-popper': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + aria-hidden: 1.2.6 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + react-remove-scroll: 2.7.2(@types/react@19.2.17)(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-popper@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@floating-ui/react-dom': 2.1.9(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-arrow': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-rect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-size': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/rect': 1.1.2 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-portal@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-presence@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-primitive@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-roving-focus@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-collection': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-is-hydrated': 0.1.1(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-slot@1.3.0(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-tabs@1.1.17(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-direction': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-roving-focus': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-toast@1.2.19(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-collection': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-use-callback-ref': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-tooltip@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/primitive': 1.1.5 + '@radix-ui/react-compose-refs': 1.1.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-context': 1.2.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-dismissable-layer': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-id': 1.1.2(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-popper': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-portal': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-presence': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@radix-ui/react-slot': 1.3.0(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-controllable-state': 1.2.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-visually-hidden': 1.2.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/react-use-callback-ref@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-controllable-state@1.2.3(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.3(@types/react@19.2.17)(react@19.2.7) + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-effect-event@0.0.3(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-is-hydrated@0.1.1(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-layout-effect@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-rect@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/rect': 1.1.2 + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-use-size@1.1.2(@types/react@19.2.17)(react@19.2.7)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.2(@types/react@19.2.17)(react@19.2.7) + react: 19.2.7 + optionalDependencies: + '@types/react': 19.2.17 + + '@radix-ui/react-visually-hidden@1.2.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@radix-ui/react-primitive': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@radix-ui/rect@1.1.2': {} + + '@rolldown/pluginutils@1.0.0-beta.27': {} + + '@rollup/rollup-android-arm-eabi@4.62.2': + optional: true + + '@rollup/rollup-android-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.62.2': + optional: true + + '@rollup/rollup-darwin-x64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.62.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.62.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.62.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.62.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.62.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.62.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.62.2': + optional: true + + '@standard-schema/spec@1.1.0': {} + + '@tailwindcss/node@4.3.3': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.24.2 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.3 + + '@tailwindcss/oxide-android-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide@4.3.3': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + + '@tailwindcss/vite@4.3.3(vite@6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0))': + dependencies: + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + tailwindcss: 4.3.3 + vite: 6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0) + + '@tanstack/query-core@5.101.2': {} + + '@tanstack/react-query@5.101.2(react@19.2.7)': + dependencies: + '@tanstack/query-core': 5.101.2 + react: 19.2.7 + + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/runtime': 7.29.7 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.5.0 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@babel/runtime': 7.29.7 + '@testing-library/dom': 10.4.1 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + '@types/react-dom': 19.2.3(@types/react@19.2.17) + + '@turbo/darwin-64@2.10.5': + optional: true + + '@turbo/darwin-arm64@2.10.5': + optional: true + + '@turbo/linux-64@2.10.5': + optional: true + + '@turbo/linux-arm64@2.10.5': + optional: true + + '@turbo/windows-64@2.10.5': + optional: true + + '@turbo/windows-arm64@2.10.5': + optional: true + + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.7 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.7 + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.9': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@22.20.1': + dependencies: + undici-types: 6.21.0 + + '@types/react-dom@19.2.3(@types/react@19.2.17)': + dependencies: + '@types/react': 19.2.17 + + '@types/react@19.2.17': + dependencies: + csstype: 3.2.3 + + '@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.64.0 + '@typescript-eslint/type-utils': 8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.64.0 + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + ignore: 7.0.6 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.64.0 + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/typescript-estree': 8.64.0(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.64.0 + debug: 4.4.3(supports-color@7.2.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.64.0(supports-color@7.2.0)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.64.0(typescript@5.9.3) + '@typescript-eslint/types': 8.64.0 + debug: 4.4.3(supports-color@7.2.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.64.0': + dependencies: + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/visitor-keys': 8.64.0 + + '@typescript-eslint/tsconfig-utils@8.64.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + + '@typescript-eslint/type-utils@8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/typescript-estree': 8.64.0(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + debug: 4.4.3(supports-color@7.2.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.64.0': {} + + '@typescript-eslint/typescript-estree@8.64.0(supports-color@7.2.0)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.64.0(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.64.0(typescript@5.9.3) + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/visitor-keys': 8.64.0 + debug: 4.4.3(supports-color@7.2.0) + minimatch: 10.2.5 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) + '@typescript-eslint/scope-manager': 8.64.0 + '@typescript-eslint/types': 8.64.0 + '@typescript-eslint/typescript-estree': 8.64.0(supports-color@7.2.0)(typescript@5.9.3) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.64.0': + dependencies: + '@typescript-eslint/types': 8.64.0 + eslint-visitor-keys: 5.0.1 + + '@vitejs/plugin-react@4.7.0(supports-color@7.2.0)(vite@6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0))': + dependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7(supports-color@7.2.0)) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@3.2.7': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.7 + '@vitest/utils': 3.2.7 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.7(vite@6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0))': + dependencies: + '@vitest/spy': 3.2.7 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0) + + '@vitest/pretty-format@3.2.7': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.7': + dependencies: + '@vitest/utils': 3.2.7 + pathe: 2.0.3 + strip-literal: 3.1.0 + + '@vitest/snapshot@3.2.7': + dependencies: + '@vitest/pretty-format': 3.2.7 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@3.2.7': + dependencies: + tinyspy: 4.0.4 + + '@vitest/utils@3.2.7': + dependencies: + '@vitest/pretty-format': 3.2.7 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + + abstract-logging@2.0.1: {} + + acorn-jsx@5.3.2(acorn@8.17.0): + dependencies: + acorn: 8.17.0 + + acorn@8.17.0: {} + + agent-base@7.1.4: {} + + ajv-formats@3.0.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.4 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.3: {} + + argparse@2.0.1: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + asn1.js@5.4.1: + dependencies: + bn.js: 4.12.5 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + safer-buffer: 2.1.2 + + assertion-error@2.0.1: {} + + async-function@1.0.0: {} + + atomic-sleep@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + avvio@9.3.0: + dependencies: + '@fastify/error': 4.2.0 + fastq: 1.20.1 + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + baseline-browser-mapping@2.10.43: {} + + bn.js@4.12.5: {} + + brace-expansion@1.1.16: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@5.0.7: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.6: + dependencies: + baseline-browser-mapping: 2.10.43 + caniuse-lite: 1.0.30001806 + electron-to-chromium: 1.5.393 + node-releases: 2.0.51 + update-browserslist-db: 1.2.3(browserslist@4.28.6) + + c12@3.1.0: + dependencies: + chokidar: 4.0.3 + confbox: 0.2.4 + defu: 6.1.7 + dotenv: 16.6.1 + exsolve: 1.1.0 + giget: 2.0.0 + jiti: 2.7.0 + ohash: 2.0.11 + pathe: 2.0.3 + perfect-debounce: 1.0.0 + pkg-types: 2.3.1 + rc9: 2.1.2 + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001806: {} + + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + check-error@2.1.3: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + citty@0.1.6: + dependencies: + consola: 3.4.2 + + citty@0.2.2: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + clsx@2.1.1: {} + + cluster-key-slot@1.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colorette@2.0.20: {} + + commander@13.1.0: {} + + concat-map@0.0.1: {} + + confbox@0.2.4: {} + + consola@3.4.2: {} + + content-disposition@1.1.0: {} + + convert-source-map@2.0.0: {} + + cookie@1.1.1: {} + + cookie@2.0.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css.escape@1.5.1: {} + + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + + csstype@3.2.3: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + dateformat@4.6.3: {} + + debug@4.4.3(supports-color@7.2.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 7.2.0 + + decimal.js@10.6.0: {} + + deep-eql@5.0.2: {} + + deep-is@0.1.4: {} + + deepmerge-ts@7.1.5: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + defu@6.1.7: {} + + denque@2.1.0: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + destr@2.0.5: {} + + detect-libc@2.1.2: {} + + detect-node-es@1.1.0: {} + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + dotenv@16.6.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexify@4.1.3: + dependencies: + end-of-stream: 1.4.5 + inherits: 2.0.4 + readable-stream: 3.6.2 + stream-shift: 1.0.3 + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + effect@3.21.0: + dependencies: + '@standard-schema/spec': 1.1.0 + fast-check: 3.23.2 + + electron-to-chromium@1.5.393: {} + + emoji-regex@10.6.0: {} + + empathic@2.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + enhanced-resolve@5.24.2: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + entities@6.0.1: {} + + environment@1.1.0: {} + + es-abstract-get@1.0.0: + dependencies: + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + is-callable: 1.2.7 + object-inspect: 1.13.4 + + es-abstract@1.24.2: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.4 + function.prototype.name: 1.2.0 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.4 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.11 + string.prototype.trimend: 1.0.10 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.8 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.22 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.4.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + math-intrinsics: 1.1.0 + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.4 + + es-to-primitive@1.3.4: + dependencies: + es-abstract-get: 1.0.0 + es-define-property: 1.0.1 + es-errors: 1.3.0 + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + esbuild@0.28.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.1 + '@esbuild/android-arm': 0.28.1 + '@esbuild/android-arm64': 0.28.1 + '@esbuild/android-x64': 0.28.1 + '@esbuild/darwin-arm64': 0.28.1 + '@esbuild/darwin-x64': 0.28.1 + '@esbuild/freebsd-arm64': 0.28.1 + '@esbuild/freebsd-x64': 0.28.1 + '@esbuild/linux-arm': 0.28.1 + '@esbuild/linux-arm64': 0.28.1 + '@esbuild/linux-ia32': 0.28.1 + '@esbuild/linux-loong64': 0.28.1 + '@esbuild/linux-mips64el': 0.28.1 + '@esbuild/linux-ppc64': 0.28.1 + '@esbuild/linux-riscv64': 0.28.1 + '@esbuild/linux-s390x': 0.28.1 + '@esbuild/linux-x64': 0.28.1 + '@esbuild/netbsd-arm64': 0.28.1 + '@esbuild/netbsd-x64': 0.28.1 + '@esbuild/openbsd-arm64': 0.28.1 + '@esbuild/openbsd-x64': 0.28.1 + '@esbuild/openharmony-arm64': 0.28.1 + '@esbuild/sunos-x64': 0.28.1 + '@esbuild/win32-arm64': 0.28.1 + '@esbuild/win32-ia32': 0.28.1 + '@esbuild/win32-x64': 0.28.1 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@10.1.8(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)): + dependencies: + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + + eslint-plugin-react-hooks@5.2.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)): + dependencies: + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + + eslint-plugin-react@7.37.5(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.4.0 + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + estraverse: 5.3.0 + hasown: 2.0.4 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.5 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.7 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.2(supports-color@7.2.0) + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.6(supports-color@7.2.0) + '@eslint/js': 9.39.5 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3(supports-color@7.2.0) + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) + eslint-visitor-keys: 4.2.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + esutils@2.0.3: {} + + eventemitter3@5.0.4: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + expect-type@1.4.0: {} + + exsolve@1.1.0: {} + + fast-check@3.23.2: + dependencies: + pure-rand: 6.1.0 + + fast-copy@4.0.4: {} + + fast-decode-uri-component@1.0.1: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-json-stringify@7.0.1: + dependencies: + '@fastify/merge-json-schemas': 0.2.1 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 4.1.1 + json-schema-ref-resolver: 3.0.0 + rfdc: 1.4.1 + + fast-jwt@5.0.6: + dependencies: + '@lukeed/ms': 2.0.2 + asn1.js: 5.4.1 + ecdsa-sig-formatter: 1.0.11 + mnemonist: 0.40.4 + + fast-levenshtein@2.0.6: {} + + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-safe-stringify@2.1.1: {} + + fast-uri@3.1.4: {} + + fast-uri@4.1.1: {} + + fastfall@1.5.1: + dependencies: + reusify: 1.1.0 + + fastify-plugin@5.1.0: {} + + fastify-plugin@6.0.0: {} + + fastify@5.10.0: + dependencies: + '@fastify/ajv-compiler': 4.0.5 + '@fastify/error': 4.2.0 + '@fastify/fast-json-stringify-compiler': 5.1.0 + '@fastify/proxy-addr': 5.1.0 + abstract-logging: 2.0.1 + avvio: 9.3.0 + fast-json-stringify: 7.0.1 + find-my-way: 9.6.0 + light-my-request: 6.6.0 + pino: 9.14.0 + process-warning: 5.0.0 + rfdc: 1.4.1 + secure-json-parse: 4.1.0 + semver: 7.8.5 + toad-cache: 3.7.4 + + fastparallel@2.4.1: + dependencies: + reusify: 1.1.0 + xtend: 4.0.2 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fastseries@1.7.2: + dependencies: + reusify: 1.1.0 + xtend: 4.0.2 + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-my-way@9.6.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 5.1.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + + flatted@3.4.2: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.2.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + es-define-property: 1.0.1 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + hasown: 2.0.4 + is-callable: 1.2.7 + is-document.all: 1.0.0 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + gensync@1.0.0-beta.2: {} + + get-east-asian-width@1.6.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-nonce@1.0.1: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + get-stream@8.0.1: {} + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + giget@2.0.0: + dependencies: + citty: 0.1.6 + consola: 3.4.2 + defu: 6.1.7 + node-fetch-native: 1.6.7 + nypm: 0.6.8 + pathe: 2.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@13.0.6: + dependencies: + minimatch: 10.2.5 + minipass: 7.1.3 + path-scurry: 2.0.2 + + globals@14.0.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + helmet@8.3.0: {} + + help-me@5.0.0: {} + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http-proxy-agent@7.0.2(supports-color@7.2.0): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6(supports-color@7.2.0): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + human-signals@5.0.0: {} + + husky@9.1.7: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + ignore@7.0.6: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inherits@2.0.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.4 + side-channel: 1.1.1 + + ioredis@5.11.1(supports-color@7.2.0): + dependencies: + '@ioredis/commands': 1.10.0 + cluster-key-slot: 1.1.1 + debug: 4.4.3(supports-color@7.2.0) + denque: 2.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + + ipaddr.js@2.4.0: {} + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.2: + dependencies: + hasown: 2.0.4 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-document.all@1.0.0: + dependencies: + call-bound: 1.0.4 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.1.0: + dependencies: + get-east-asian-width: 1.6.0 + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@3.0.0: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.22 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + jiti@2.7.0: {} + + jotai@2.20.2(@babel/core@7.29.7(supports-color@7.2.0))(@babel/template@7.29.7)(@types/react@19.2.17)(react@19.2.7): + optionalDependencies: + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/template': 7.29.7 + '@types/react': 19.2.17 + react: 19.2.7 + + joycon@3.1.1: {} + + js-tokens@4.0.0: {} + + js-tokens@9.0.1: {} + + js-yaml@4.3.0: + dependencies: + argparse: 2.0.1 + + jsdom@26.1.0(supports-color@7.2.0): + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2(supports-color@7.2.0) + https-proxy-agent: 7.0.6(supports-color@7.2.0) + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.24 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.21.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-ref-resolver@3.0.0: + dependencies: + dequal: 2.0.3 + + json-schema-resolver@3.0.0(supports-color@7.2.0): + dependencies: + debug: 4.4.3(supports-color@7.2.0) + fast-uri: 3.1.4 + rfdc: 1.4.1 + transitivePeerDependencies: + - supports-color + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.9 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + light-my-request@6.6.0: + dependencies: + cookie: 1.1.1 + process-warning: 4.0.1 + set-cookie-parser: 2.7.2 + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lilconfig@3.1.3: {} + + lint-staged@15.5.2(supports-color@7.2.0): + dependencies: + chalk: 5.6.2 + commander: 13.1.0 + debug: 4.4.3(supports-color@7.2.0) + execa: 8.0.1 + lilconfig: 3.1.3 + listr2: 8.3.3 + micromatch: 4.0.8 + pidtree: 0.6.1 + string-argv: 0.3.2 + yaml: 2.9.0 + transitivePeerDependencies: + - supports-color + + listr2@8.3.3: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.4 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.2 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.3.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.2 + strip-ansi: 7.2.0 + wrap-ansi: 9.0.2 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.2.1: {} + + lru-cache@10.4.3: {} + + lru-cache@11.5.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lucide-react@0.510.0(react@19.2.7): + dependencies: + react: 19.2.7 + + lz-string@1.5.0: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + math-intrinsics@1.1.0: {} + + merge-stream@2.0.0: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mime@3.0.0: {} + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + min-indent@1.0.1: {} + + minimalistic-assert@1.0.1: {} + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.7 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.16 + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + mnemonist@0.40.4: + dependencies: + obliterator: 2.0.5 + + ms@2.1.3: {} + + nanoid@3.3.16: {} + + natural-compare@1.4.0: {} + + node-exports-info@1.6.2: + dependencies: + array.prototype.flatmap: 1.3.3 + es-errors: 1.3.0 + object.entries: 1.1.9 + semver: 6.3.1 + + node-fetch-native@1.6.7: {} + + node-releases@2.0.51: {} + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + nwsapi@2.2.24: {} + + nypm@0.6.8: + dependencies: + citty: 0.2.2 + pathe: 2.0.3 + tinyexec: 1.2.4 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + obliterator@2.0.5: {} + + ohash@2.0.11: {} + + on-exit-leak-free@2.1.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + openapi-types@12.1.3: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.5.2 + minipass: 7.1.3 + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + perfect-debounce@1.0.0: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.5: {} + + pidtree@0.6.1: {} + + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-abstract-transport@3.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.1.3: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 4.0.4 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 3.0.0 + pump: 3.0.4 + secure-json-parse: 4.1.0 + sonic-boom: 4.2.1 + strip-json-comments: 5.0.3 + + pino-std-serializers@7.1.0: {} + + pino@9.14.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.1.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.1 + thread-stream: 3.2.0 + + pkg-types@2.3.1: + dependencies: + confbox: 0.2.4 + exsolve: 1.1.0 + pathe: 2.0.3 + + possible-typed-array-names@1.1.0: {} + + postcss@8.5.20: + dependencies: + nanoid: 3.3.16 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier@3.9.5: {} + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + prisma@6.19.3(typescript@5.9.3): + dependencies: + '@prisma/config': 6.19.3 + '@prisma/engines': 6.19.3 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - magicast + + process-warning@4.0.1: {} + + process-warning@5.0.0: {} + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + punycode@2.3.1: {} + + pure-rand@6.1.0: {} + + quick-format-unescaped@4.0.4: {} + + rc9@2.1.2: + dependencies: + defu: 6.1.7 + destr: 2.0.5 + + react-dom@19.2.7(react@19.2.7): + dependencies: + react: 19.2.7 + scheduler: 0.27.0 + + react-is@16.13.1: {} + + react-is@17.0.2: {} + + react-refresh@0.17.0: {} + + react-remove-scroll-bar@2.3.8(@types/react@19.2.17)(react@19.2.7): + dependencies: + react: 19.2.7 + react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.17 + + react-remove-scroll@2.7.2(@types/react@19.2.17)(react@19.2.7): + dependencies: + react: 19.2.7 + react-remove-scroll-bar: 2.3.8(@types/react@19.2.17)(react@19.2.7) + react-style-singleton: 2.2.3(@types/react@19.2.17)(react@19.2.7) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.2.17)(react@19.2.7) + use-sidecar: 1.1.3(@types/react@19.2.17)(react@19.2.7) + optionalDependencies: + '@types/react': 19.2.17 + + react-router-dom@7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + dependencies: + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + react-router: 7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + + react-router@7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + dependencies: + cookie: 1.1.1 + react: 19.2.7 + set-cookie-parser: 2.7.2 + optionalDependencies: + react-dom: 19.2.7(react@19.2.7) + + react-style-singleton@2.2.3(@types/react@19.2.17)(react@19.2.7): + dependencies: + get-nonce: 1.0.1 + react: 19.2.7 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.17 + + react@19.2.7: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@4.1.2: {} + + real-require@0.2.0: {} + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + redis-errors@1.2.0: {} + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + resolve@2.0.0-next.7: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.2 + node-exports-info: 1.6.2 + object-keys: 1.1.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + ret@0.5.0: {} + + reusify@1.1.0: {} + + rfdc@1.4.1: {} + + rollup@4.62.2: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.62.2 + '@rollup/rollup-android-arm64': 4.62.2 + '@rollup/rollup-darwin-arm64': 4.62.2 + '@rollup/rollup-darwin-x64': 4.62.2 + '@rollup/rollup-freebsd-arm64': 4.62.2 + '@rollup/rollup-freebsd-x64': 4.62.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.62.2 + '@rollup/rollup-linux-arm-musleabihf': 4.62.2 + '@rollup/rollup-linux-arm64-gnu': 4.62.2 + '@rollup/rollup-linux-arm64-musl': 4.62.2 + '@rollup/rollup-linux-loong64-gnu': 4.62.2 + '@rollup/rollup-linux-loong64-musl': 4.62.2 + '@rollup/rollup-linux-ppc64-gnu': 4.62.2 + '@rollup/rollup-linux-ppc64-musl': 4.62.2 + '@rollup/rollup-linux-riscv64-gnu': 4.62.2 + '@rollup/rollup-linux-riscv64-musl': 4.62.2 + '@rollup/rollup-linux-s390x-gnu': 4.62.2 + '@rollup/rollup-linux-x64-gnu': 4.62.2 + '@rollup/rollup-linux-x64-musl': 4.62.2 + '@rollup/rollup-openbsd-x64': 4.62.2 + '@rollup/rollup-openharmony-arm64': 4.62.2 + '@rollup/rollup-win32-arm64-msvc': 4.62.2 + '@rollup/rollup-win32-ia32-msvc': 4.62.2 + '@rollup/rollup-win32-x64-gnu': 4.62.2 + '@rollup/rollup-win32-x64-msvc': 4.62.2 + fsevents: 2.3.3 + + rrweb-cssom@0.8.0: {} + + safe-array-concat@1.1.4: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-regex2@5.1.1: + dependencies: + ret: 0.5.0 + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.27.0: {} + + secure-json-parse@4.1.0: {} + + semver@6.3.1: {} + + semver@7.8.5: {} + + set-cookie-parser@2.7.2: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.2: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + + sonic-boom@4.2.1: + dependencies: + atomic-sleep: 1.0.0 + + source-map-js@1.2.1: {} + + split2@4.2.0: {} + + stackback@0.0.2: {} + + standard-as-callback@2.1.0: {} + + statuses@2.0.2: {} + + std-env@3.10.0: {} + + steed@1.1.3: + dependencies: + fastfall: 1.5.1 + fastparallel: 2.4.1 + fastq: 1.20.1 + fastseries: 1.7.2 + reusify: 1.1.0 + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + stream-shift@1.0.3: {} + + string-argv@0.3.2: {} + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.1 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.2 + + string.prototype.trim@1.2.11: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + has-property-descriptors: 1.0.2 + safe-regex-test: 1.1.0 + + string.prototype.trimend@1.0.10: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-final-newline@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + strip-json-comments@5.0.3: {} + + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-tree@3.2.4: {} + + tailwind-merge@3.6.0: {} + + tailwindcss@4.3.3: {} + + tapable@2.3.3: {} + + thread-stream@3.2.0: + dependencies: + real-require: 0.2.0 + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinyexec@1.2.4: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.4: {} + + tldts-core@6.1.86: {} + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toad-cache@3.7.4: {} + + toidentifier@1.0.1: {} + + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + ts-api-utils@2.5.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + tslib@2.8.1: {} + + tsx@4.23.1: + dependencies: + esbuild: 0.28.1 + optionalDependencies: + fsevents: 2.3.3 + + turbo@2.10.5: + optionalDependencies: + '@turbo/darwin-64': 2.10.5 + '@turbo/darwin-arm64': 2.10.5 + '@turbo/linux-64': 2.10.5 + '@turbo/linux-arm64': 2.10.5 + '@turbo/windows-64': 2.10.5 + '@turbo/windows-arm64': 2.10.5 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.8: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typescript@5.9.3: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + undici-types@6.21.0: {} + + update-browserslist-db@1.2.3(browserslist@4.28.6): + dependencies: + browserslist: 4.28.6 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + use-callback-ref@1.3.3(@types/react@19.2.17)(react@19.2.7): + dependencies: + react: 19.2.7 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.17 + + use-sidecar@1.1.3(@types/react@19.2.17)(react@19.2.7): + dependencies: + detect-node-es: 1.1.0 + react: 19.2.7 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.17 + + util-deprecate@1.0.2: {} + + vite-node@3.2.4(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(supports-color@7.2.0)(tsx@4.23.1)(yaml@2.9.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3(supports-color@7.2.0) + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + postcss: 8.5.20 + rollup: 4.62.2 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 22.20.1 + fsevents: 2.3.3 + jiti: 2.7.0 + lightningcss: 1.32.0 + tsx: 4.23.1 + yaml: 2.9.0 + + vitest@3.2.7(@types/node@22.20.1)(jiti@2.7.0)(jsdom@26.1.0(supports-color@7.2.0))(lightningcss@1.32.0)(supports-color@7.2.0)(tsx@4.23.1)(yaml@2.9.0): + dependencies: + '@types/chai': 5.2.3 + '@vitest/expect': 3.2.7 + '@vitest/mocker': 3.2.7(vite@6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0)) + '@vitest/pretty-format': 3.2.7 + '@vitest/runner': 3.2.7 + '@vitest/snapshot': 3.2.7 + '@vitest/spy': 3.2.7 + '@vitest/utils': 3.2.7 + chai: 5.3.3 + debug: 4.4.3(supports-color@7.2.0) + expect-type: 1.4.0 + magic-string: 0.30.21 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.17 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 6.4.3(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.23.1)(yaml@2.9.0) + vite-node: 3.2.4(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(supports-color@7.2.0)(tsx@4.23.1)(yaml@2.9.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.20.1 + jsdom: 26.1.0(supports-color@7.2.0) + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + webidl-conversions@7.0.0: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.2.0 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.22 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.22: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + + ws@8.21.1: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + + xtend@4.0.2: {} + + yallist@3.1.1: {} + + yaml@2.9.0: {} + + yocto-queue@0.1.0: {} + + zod@3.25.76: {} + + zustand@5.0.14(@types/react@19.2.17)(react@19.2.7): + optionalDependencies: + '@types/react': 19.2.17 + react: 19.2.7 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..049cc5e --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,9 @@ +packages: + - "apps/*" + - "packages/*" + - "tooling/*" +allowBuilds: + '@prisma/client': true + '@prisma/engines': true + esbuild: true + prisma: true diff --git a/tooling/eslint/base.js b/tooling/eslint/base.js new file mode 100644 index 0000000..ed90e01 --- /dev/null +++ b/tooling/eslint/base.js @@ -0,0 +1,33 @@ +import eslintConfigPrettier from 'eslint-config-prettier'; +import tsParser from '@typescript-eslint/parser'; + +const config = [ + { + ignores: [ + '**/dist/**', + '**/.turbo/**', + '**/node_modules/**', + '**/*.config.*', + ], + }, + { + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + }, + eslintConfigPrettier, + { + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + }, + rules: { + 'no-unused-vars': 'off', + 'no-undef': 'off', + }, + }, +]; + +export default config; diff --git a/tooling/eslint/node.js b/tooling/eslint/node.js new file mode 100644 index 0000000..d2e3928 --- /dev/null +++ b/tooling/eslint/node.js @@ -0,0 +1,11 @@ +import base from './base.js'; + +export default [ + ...base, + { + files: ['**/*.ts', '**/*.js'], + rules: { + 'no-process-exit': 'error', + }, + }, +]; diff --git a/tooling/eslint/package.json b/tooling/eslint/package.json new file mode 100644 index 0000000..3ff3788 --- /dev/null +++ b/tooling/eslint/package.json @@ -0,0 +1,20 @@ +{ + "name": "@yetanother/eslint-config", + "private": true, + "type": "module", + "exports": { + "./base": "./base.js", + "./react": "./react.js", + "./node": "./node.js" + }, + "dependencies": { + "@typescript-eslint/eslint-plugin": "^8.30.0", + "@typescript-eslint/parser": "^8.30.0", + "eslint-config-prettier": "^10.1.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.2.0" + }, + "peerDependencies": { + "eslint": "^9.25.0" + } +} diff --git a/tooling/eslint/react.js b/tooling/eslint/react.js new file mode 100644 index 0000000..3e015e4 --- /dev/null +++ b/tooling/eslint/react.js @@ -0,0 +1,22 @@ +import base from './base.js'; +import reactPlugin from 'eslint-plugin-react'; +import hooksPlugin from 'eslint-plugin-react-hooks'; + +export default [ + ...base, + reactPlugin.configs.flat.recommended, + { + plugins: { + 'react-hooks': hooksPlugin, + }, + files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], + rules: { + ...hooksPlugin.configs.recommended.rules, + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + }, + settings: { + react: { version: 'detect' }, + }, + }, +]; diff --git a/tooling/typescript/base.json b/tooling/typescript/base.json new file mode 100644 index 0000000..895013d --- /dev/null +++ b/tooling/typescript/base.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2022"], + "strict": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "exactOptionalPropertyTypes": false, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "esModuleInterop": true, + "isolatedModules": true, + "resolveJsonModule": true, + "composite": true, + "incremental": true + } +} diff --git a/tooling/typescript/node.json b/tooling/typescript/node.json new file mode 100644 index 0000000..4412ce7 --- /dev/null +++ b/tooling/typescript/node.json @@ -0,0 +1,7 @@ +{ + "extends": "./base.json", + "compilerOptions": { + "lib": ["ES2022"], + "types": ["node"] + } +} diff --git a/tooling/typescript/package.json b/tooling/typescript/package.json new file mode 100644 index 0000000..72da042 --- /dev/null +++ b/tooling/typescript/package.json @@ -0,0 +1,9 @@ +{ + "name": "@yetanother/tsconfig", + "private": true, + "exports": { + "./base": "./base.json", + "./react": "./react.json", + "./node": "./node.json" + } +} diff --git a/tooling/typescript/react.json b/tooling/typescript/react.json new file mode 100644 index 0000000..7aed7be --- /dev/null +++ b/tooling/typescript/react.json @@ -0,0 +1,7 @@ +{ + "extends": "./base.json", + "compilerOptions": { + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "jsx": "react-jsx" + } +} diff --git a/turbo.json b/turbo.json new file mode 100644 index 0000000..3b784bc --- /dev/null +++ b/turbo.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://turbo.build/schema.json", + "globalDependencies": ["**/.env.*local"], + "tasks": { + "build": { + "dependsOn": ["^build"], + "outputs": ["dist/**", ".next/**"] + }, + "dev": { + "cache": false, + "persistent": true + }, + "lint": { + "dependsOn": ["^build"] + }, + "typecheck": { + "dependsOn": ["^build"] + }, + "test": { + "dependsOn": ["^build"], + "outputs": ["coverage/**"] + }, + "clean": { + "cache": false + } + } +} diff --git a/yetanothersuite_implementation_plan.json b/yetanothersuite_implementation_plan.json new file mode 100644 index 0000000..dad394c --- /dev/null +++ b/yetanothersuite_implementation_plan.json @@ -0,0 +1,1575 @@ +{ + "project": { + "name": "YetAnotherSuite", + "tagline": "The Unified Productivity Ecosystem \u2014 Todo, Calendar, and Notes, Connected by AI", + "type": "Interactive Web Application (PWA + Desktop + Mobile)", + "target_platform": "Web (PWA), Desktop (Electron/Tauri), Mobile (React Native)", + "development_phases": 6, + "estimated_timeline": "24-28 weeks" + }, + "core_concept": { + "vision": "A unified workspace where tasks, events, and knowledge naturally interconnect. No more context switching between apps \u2014 your todos appear in your calendar, your notes link to your tasks, and AI surfaces the right information at the right time.", + "problem_statement": "Current productivity stacks are fragmented: todos in one app, calendar in another, notes in a third. Users lose context, duplicate effort, and miss connections between their work. YetAnotherSuite eliminates fragmentation by treating tasks, events, and notes as interconnected nodes in a personal knowledge and action graph.", + "differentiation": [ + "Unified data model \u2014 tasks, events, and notes share a single graph structure", + "AI-powered cross-modal linking (e.g., 'this note relates to this meeting and these tasks')", + "Contextual workspace switching \u2014 calendar view shows relevant notes, task view shows upcoming deadlines", + "Natural language input across all modules ('Schedule meeting with Sarah next Tuesday and create prep notes')", + "Local-first with seamless cloud sync \u2014 works offline, syncs when connected", + "Time-blocking integration \u2014 drag tasks directly onto calendar as time blocks", + "Bi-directional references \u2014 tasks reference notes, notes reference events, events link to tasks" + ], + "target_users": [ + "Knowledge workers managing complex projects", + "Executives and managers coordinating teams", + "Researchers and academics with time-bound deliverables", + "Freelancers juggling multiple clients and deadlines", + "Students managing coursework and research" + ], + "competitive_positioning": "Notion (notes) + Todoist (tasks) + Google Calendar (events) = 3 apps, 3 contexts, 3 syncs. YetAnotherSuite = 1 app, 1 context, 1 sync, with AI connecting everything." + }, + "architecture": { + "frontend": { + "framework": "React 18+ with TypeScript (strict mode)", + "state_management": "Zustand (global) + TanStack Query (server state) + Jotai (local UI)", + "editor_engine": "TipTap / ProseMirror (block-based, extensible)", + "calendar_engine": "Custom React components + date-fns + rrule for recurrence", + "styling": "Tailwind CSS + Radix UI primitives + shadcn/ui components", + "realtime_collaboration": "Yjs (CRDT) for all modules", + "build_tool": "Vite + Turborepo (monorepo)", + "desktop_wrapper": "Tauri (Rust-based, lightweight, secure)", + "mobile": "React Native (shared business logic via React Native Web)", + "testing": "Vitest + React Testing Library + Playwright + MSW (API mocking)" + }, + "backend": { + "api_gateway": "Node.js + Fastify (or Go + Gin for performance-critical paths)", + "database": "PostgreSQL 15+ (primary) with JSONB for flexible content", + "caching": "Redis (sessions, hot data, rate limiting)", + "search": "Meilisearch (instant) + pgvector (semantic) \u2014 hybrid search", + "realtime": "WebSocket server (Socket.io or native WS with Redis adapter)", + "queue": "BullMQ (Redis-based) for background jobs (AI processing, sync, exports)", + "ai_services": "OpenAI/Anthropic API + local fallback (Ollama) + self-hosted embeddings", + "file_storage": "S3-compatible (MinIO for self-hosting) + CDN for assets", + "vector_database": "pgvector (PostgreSQL extension) for semantic search and recommendations", + "sync_engine": "Custom sync protocol (based on CRDTs + operational transforms) for offline-first" + }, + "infrastructure": { + "containerization": "Docker + Docker Compose (dev) + Kubernetes (production)", + "orchestration": "Helm charts for K8s deployment", + "ci_cd": "GitHub Actions with matrix builds (Web, Desktop, Mobile)", + "monitoring": "Prometheus + Grafana (metrics) + Sentry (errors) + LogRocket (session replay)", + "deployment": "Railway/Render (MVP) \u2192 AWS/GCP (scale) with Terraform", + "cdn": "Cloudflare (global edge caching)", + "backup": "Automated PostgreSQL backups + S3 versioning" + } + }, + "unified_data_model": { + "philosophy": "All entities (tasks, events, notes) are 'Nodes' in a unified graph. They share common properties (title, content, timestamps, metadata) but have type-specific extensions. Relationships are first-class citizens.", + "core_entities": [ + { + "entity": "User", + "fields": [ + "id (UUID PK)", + "email (unique, indexed)", + "display_name", + "avatar_url", + "preferences (JSONB: theme, timezone, notification_settings, default_views)", + "encryption_key (for E2E encrypted notes)", + "created_at", + "updated_at", + "last_active_at" + ], + "relations": [ + "Workspaces (many-to-many via WorkspaceMember)", + "Nodes (one-to-many, owned)", + "SharedNodes (many-to-many via NodeShare)", + "Activities (one-to-many)" + ] + }, + { + "entity": "Workspace", + "fields": [ + "id (UUID PK)", + "name", + "slug (unique per user)", + "description", + "settings (JSONB: default_view, color_scheme, ai_enabled, retention_policy)", + "owner_id (FK \u2192 User)", + "created_at", + "updated_at" + ], + "relations": [ + "Members (many-to-many via WorkspaceMember)", + "Nodes (one-to-many)", + "Tags (one-to-many, workspace-scoped)", + "Folders (one-to-many, workspace-scoped)", + "Integrations (one-to-many)" + ] + }, + { + "entity": "Node (Polymorphic Base)", + "fields": [ + "id (UUID PK)", + "type (ENUM: 'task', 'event', 'note', 'project', 'goal')", + "workspace_id (FK \u2192 Workspace)", + "owner_id (FK \u2192 User)", + "parent_id (FK \u2192 Node, self-referencing for hierarchy)", + "title", + "content (JSONB: ProseMirror doc for notes, structured data for tasks/events)", + "plain_text (generated, for search)", + "status (ENUM: 'active', 'archived', 'deleted')", + "priority (INTEGER: 1-5, nullable)", + "start_time (TIMESTAMPTZ, for events and task deadlines)", + "end_time (TIMESTAMPTZ, for events and task durations)", + "duration_minutes (INTEGER, computed or explicit)", + "recurrence_rule (TEXT, iCal RRULE format)", + "completion_rate (DECIMAL, for projects/goals)", + "metadata (JSONB: type-specific data)", + "version (INTEGER, for optimistic locking)", + "is_encrypted (BOOLEAN, for E2E notes)", + "created_at", + "updated_at", + "completed_at", + "archived_at" + ], + "relations": [ + "Parent (self-referencing)", + "Children (self-referencing)", + "Tags (many-to-many via NodeTag)", + "Links (many-to-many via NodeLink, self-referencing)", + "Backlinks (many-to-many via NodeLink, inverse)", + "Embeddings (one-to-many)", + "Activities (one-to-many)", + "Reminders (one-to-many)", + "Attachments (one-to-many)" + ], + "indexes": [ + "GIN on content (JSONB)", + "GIN on metadata (JSONB)", + "B-tree on type, status, workspace_id, owner_id", + "BRIN on created_at (time-series optimization)", + "GIST on tsvector (full-text search)" + ] + }, + { + "entity": "NodeLink (Relationship Graph)", + "fields": [ + "id (UUID PK)", + "source_id (FK \u2192 Node)", + "target_id (FK \u2192 Node)", + "link_type (ENUM: 'references', 'blocks', 'relates_to', 'parent_of', 'child_of', 'scheduled_as', 'prepared_for')", + "strength (DECIMAL: 0-1, AI-computed relevance)", + "is_auto (BOOLEAN, AI-generated vs user-created)", + "context (TEXT, why they're related)", + "created_at" + ], + "constraints": [ + "UNIQUE(source_id, target_id, link_type)", + "CHECK(source_id != target_id)" + ], + "indexes": [ + "B-tree on source_id, target_id", + "B-tree on link_type, is_auto" + ] + }, + { + "entity": "Tag", + "fields": [ + "id (UUID PK)", + "name", + "color (HEX)", + "workspace_id (FK \u2192 Workspace)", + "is_system (BOOLEAN, e.g., 'urgent', 'meeting')", + "created_at" + ], + "relations": [ + "Nodes (many-to-many via NodeTag)", + "Workspace (many-to-one)" + ] + }, + { + "entity": "Folder", + "fields": [ + "id (UUID PK)", + "name", + "workspace_id (FK \u2192 Workspace)", + "parent_id (FK \u2192 Folder, self-referencing)", + "view_type (ENUM: 'list', 'board', 'calendar', 'gallery')", + "filter_config (JSONB: saved filters)", + "sort_config (JSONB: default sort)", + "order_index (INTEGER)", + "created_at" + ], + "relations": [ + "Nodes (many-to-many via NodeFolder)", + "Parent (self-referencing)", + "Children (self-referencing)" + ] + }, + { + "entity": "Reminder", + "fields": [ + "id (UUID PK)", + "node_id (FK \u2192 Node)", + "user_id (FK \u2192 User)", + "remind_at (TIMESTAMPTZ)", + "notification_type (ENUM: 'push', 'email', 'sms', 'in_app')", + "status (ENUM: 'pending', 'sent', 'dismissed', 'snoozed')", + "snooze_until (TIMESTAMPTZ)", + "created_at" + ] + }, + { + "entity": "Embedding", + "fields": [ + "id (UUID PK)", + "node_id (FK \u2192 Node)", + "chunk_index (INTEGER, for long content)", + "chunk_text (TEXT, the text segment)", + "vector (VECTOR(1536), pgvector)", + "model_version (TEXT, e.g., 'text-embedding-3-large-v1')", + "created_at" + ], + "indexes": [ + "HNSW index on vector (for fast similarity search)" + ] + }, + { + "entity": "Activity", + "fields": [ + "id (UUID PK)", + "user_id (FK \u2192 User)", + "node_id (FK \u2192 Node, nullable)", + "workspace_id (FK \u2192 Workspace)", + "action_type (ENUM: 'created', 'updated', 'deleted', 'viewed', 'shared', 'linked', 'completed', 'ai_assisted')", + "metadata (JSONB: before/after snapshots, AI prompt used, etc.)", + "session_id (TEXT, for grouping)", + "created_at" + ], + "indexes": [ + "BRIN on created_at", + "B-tree on user_id, workspace_id, action_type" + ] + }, + { + "entity": "Attachment", + "fields": [ + "id (UUID PK)", + "node_id (FK \u2192 Node)", + "filename", + "mime_type", + "size_bytes", + "storage_key (S3 path)", + "thumbnail_key (S3 path, for images)", + "uploaded_by (FK \u2192 User)", + "created_at" + ] + }, + { + "entity": "WorkspaceMember", + "fields": [ + "id (UUID PK)", + "workspace_id (FK \u2192 Workspace)", + "user_id (FK \u2192 User)", + "role (ENUM: 'owner', 'admin', 'editor', 'viewer')", + "permissions (JSONB: granular overrides)", + "joined_at", + "last_accessed_at" + ] + }, + { + "entity": "SyncCheckpoint", + "fields": [ + "id (UUID PK)", + "user_id (FK \u2192 User)", + "device_id (TEXT)", + "last_sync_at (TIMESTAMPTZ)", + "sync_token (TEXT, for delta sync)", + "device_info (JSONB: os, app_version, screen_size)", + "updated_at" + ] + } + ] + }, + "modules": { + "todo_module": { + "name": "Tasks", + "description": "Full-featured task management with projects, subtasks, and time estimates", + "core_views": [ + { + "name": "Inbox", + "description": "Uncategorized tasks, quick capture" + }, + { + "name": "Today", + "description": "Tasks due today + scheduled events" + }, + { + "name": "Upcoming", + "description": "Calendar-integrated task timeline" + }, + { + "name": "Projects", + "description": "Hierarchical project boards with progress" + }, + { + "name": "Anytime", + "description": "Tasks without specific deadlines" + }, + { + "name": "Completed", + "description": "Archive with search and restore" + } + ], + "features": [ + "Quick capture with natural language ('Buy milk tomorrow morning')", + "Subtasks and checklists within tasks", + "Priority levels (P1-P4) with visual urgency indicators", + "Time estimates and actual time tracking", + "Recurring tasks with flexible patterns", + "Drag-and-drop reordering and nesting", + "Batch operations (complete, reschedule, tag, assign)", + "Focus mode (Pomodoro integration with task context)" + ] + }, + "calendar_module": { + "name": "Calendar", + "description": "Time-blocking calendar with task integration and smart scheduling", + "core_views": [ + { + "name": "Day", + "description": "Hour-by-hour with task slots" + }, + { + "name": "Week", + "description": "Standard work week view" + }, + { + "name": "Month", + "description": "Overview with density indicators" + }, + { + "name": "Year", + "description": "Long-term planning with goals" + }, + { + "name": "Schedule", + "description": "List view of upcoming events" + }, + { + "name": "Availability", + "description": "Shareable free/busy slots" + } + ], + "features": [ + "Drag tasks from todo list onto calendar as time blocks", + "Smart scheduling suggestions ('You have 2 hours free Thursday afternoon')", + "Recurring events with complex patterns (bi-weekly, nth weekday)", + "Multiple calendar layers (work, personal, shared)", + "External calendar sync (Google, Outlook, Apple iCal)", + "Meeting prep auto-linking (find relevant notes for upcoming meetings)", + "Travel time buffers and location-based reminders", + "Focus time protection (auto-block deep work sessions)" + ] + }, + "notes_module": { + "name": "Notes", + "description": "AI-native note-taking with bidirectional linking and knowledge graph", + "core_views": [ + { + "name": "All Notes", + "description": "Chronological list with search" + }, + { + "name": "Graph", + "description": "Visual knowledge graph of all notes" + }, + { + "name": "Daily Notes", + "description": "Date-stamped journal entries" + }, + { + "name": "Templates", + "description": "Reusable note structures" + }, + { + "name": "Trash", + "description": "Soft-deleted notes with recovery" + } + ], + "features": [ + "Block-based editor with slash commands and markdown", + "Bidirectional linking with auto-suggestion ('[[Meeting Notes]]')", + "Daily notes with automatic date headings", + "Templates with dynamic fields and placeholders", + "Web clipper for saving articles and annotating", + "AI-powered summarization and expansion", + "Semantic search across all notes", + "Export to Markdown, PDF, HTML, Notion" + ] + } + }, + "features": { + "phase_1_foundation": { + "timeline": "Weeks 1-4", + "theme": "Foundation & Core Infrastructure", + "features": [ + { + "name": "Monorepo Setup & Design System", + "description": "Turborepo with shared packages (ui, utils, types, hooks). shadcn/ui base components. Theme system (light/dark/auto).", + "tech_stack": [ + "Turborepo", + "pnpm", + "Tailwind", + "Radix UI", + "shadcn/ui" + ], + "complexity": "Medium", + "dependencies": [], + "acceptance_criteria": [ + "Shared packages build independently", + "Design tokens (colors, spacing, typography) centralized", + "Storybook running with all base components", + "Dark mode toggle working globally" + ] + }, + { + "name": "Authentication & User Management", + "description": "JWT-based auth with refresh tokens, OAuth (Google, GitHub, Microsoft), magic links, password reset, profile management.", + "tech_stack": [ + "Fastify", + "Passport.js", + "PostgreSQL", + "Redis", + "JWT" + ], + "complexity": "Medium", + "dependencies": [ + "Monorepo Setup" + ], + "acceptance_criteria": [ + "All auth flows working end-to-end", + "Session management with Redis", + "Rate limiting on auth endpoints", + "Email verification and password reset" + ] + }, + { + "name": "Database Schema & Migrations", + "description": "Implement full unified schema with migrations, seed data, and test fixtures. Set up pgvector extension.", + "tech_stack": [ + "PostgreSQL", + "pgvector", + "Prisma ORM", + "Docker" + ], + "complexity": "High", + "dependencies": [ + "Monorepo Setup" + ], + "acceptance_criteria": [ + "All entities created with proper constraints", + "Migration system reversible", + "Seed data for development", + "pgvector extension enabled and indexed" + ] + }, + { + "name": "API Foundation & Middleware", + "description": "REST API structure, error handling, validation (Zod), logging, rate limiting, CORS, API versioning.", + "tech_stack": [ + "Fastify", + "Zod", + "Pino", + "Helmet" + ], + "complexity": "Medium", + "dependencies": [ + "Database Schema", + "Authentication" + ], + "acceptance_criteria": [ + "Consistent API response format", + "Request validation on all endpoints", + "Structured logging with correlation IDs", + "Rate limiting per user/IP" + ] + }, + { + "name": "Offline-First Sync Engine", + "description": "CRDT-based sync protocol with IndexedDB local storage, background sync, conflict resolution UI.", + "tech_stack": [ + "Yjs", + "IndexedDB", + "Service Workers", + "Background Sync API" + ], + "complexity": "High", + "dependencies": [ + "API Foundation" + ], + "acceptance_criteria": [ + "Create/edit/delete notes offline, sync on reconnect", + "Conflict resolution UI for simultaneous edits", + "Sync status indicator in UI", + "Data integrity verified across devices" + ] + } + ] + }, + "phase_2_notes_mvp": { + "timeline": "Weeks 5-8", + "theme": "Notes Module MVP", + "features": [ + { + "name": "Block-Based Editor", + "description": "Notion-like editor with slash commands, markdown shortcuts, rich embeds, drag-and-drop blocks.", + "tech_stack": [ + "TipTap", + "ProseMirror", + "React", + "tippy.js" + ], + "complexity": "High", + "dependencies": [ + "Monorepo Setup", + "Offline-First Sync" + ], + "acceptance_criteria": [ + "All basic block types (paragraph, heading, list, code, quote, divider)", + "Slash menu with 15+ commands", + "Markdown shortcuts (## for H2, - for list)", + "Drag-and-drop reordering of blocks" + ] + }, + { + "name": "Note CRUD & Organization", + "description": "Create, read, update, delete notes. Folders, tags, favorites, trash. Note list with sorting and filtering.", + "tech_stack": [ + "PostgreSQL", + "Prisma", + "Zustand", + "TanStack Query" + ], + "complexity": "Medium", + "dependencies": [ + "Database Schema", + "Block-Based Editor" + ], + "acceptance_criteria": [ + "Full CRUD with optimistic UI updates", + "Folder hierarchy with drag-and-drop", + "Tag management with color coding", + "Trash with 30-day retention and restore" + ] + }, + { + "name": "Full-Text Search", + "description": "Instant search across all notes with highlighting, filters (date, type, tag), and search history.", + "tech_stack": [ + "Meilisearch", + "PostgreSQL tsvector", + "React" + ], + "complexity": "Medium", + "dependencies": [ + "Note CRUD" + ], + "acceptance_criteria": [ + "Search results in <100ms for 10k notes", + "Highlighting of matched terms", + "Filter by date range, tags, folders", + "Recent searches and suggestions" + ] + }, + { + "name": "Bidirectional Linking", + "description": "[[Wiki-style links]] with auto-completion, backlink panels, and unlinked references suggestions.", + "tech_stack": [ + "TipTap plugin", + "PostgreSQL", + "React" + ], + "complexity": "High", + "dependencies": [ + "Block-Based Editor", + "Note CRUD" + ], + "acceptance_criteria": [ + "Type [[ to trigger note autocomplete", + "Backlink panel showing all references to current note", + "Unlinked mentions detection (text matching note titles)", + "Broken link detection and repair suggestions" + ] + } + ] + }, + "phase_3_todo_calendar": { + "timeline": "Weeks 9-14", + "theme": "Tasks & Calendar Integration", + "features": [ + { + "name": "Task Management Core", + "description": "Full task CRUD with priorities, due dates, subtasks, projects, sections. Inbox, Today, Upcoming views.", + "tech_stack": [ + "React", + "DnD Kit", + "date-fns", + "PostgreSQL" + ], + "complexity": "High", + "dependencies": [ + "Note CRUD", + "API Foundation" + ], + "acceptance_criteria": [ + "Task creation with natural language parsing", + "Subtask nesting (3 levels deep)", + "Priority colors and urgency sorting", + "Bulk operations (complete, reschedule, move)" + ] + }, + { + "name": "Calendar Engine", + "description": "Full calendar with day/week/month/year views. Event CRUD, recurring events, all-day events, time zones.", + "tech_stack": [ + "React", + "date-fns", + "rrule", + "luxon" + ], + "complexity": "High", + "dependencies": [ + "Task Management Core" + ], + "acceptance_criteria": [ + "All calendar views rendering correctly", + "Recurring events with complex patterns", + "Timezone handling (user + event timezones)", + "All-day and multi-day events" + ] + }, + { + "name": "Task-Calendar Integration", + "description": "Drag tasks onto calendar as time blocks. Tasks shown in calendar views. Calendar events linked to tasks.", + "tech_stack": [ + "DnD Kit", + "React", + "PostgreSQL", + "NodeLink" + ], + "complexity": "High", + "dependencies": [ + "Task Management Core", + "Calendar Engine" + ], + "acceptance_criteria": [ + "Drag task from list to calendar slot", + "Task appears as time block in calendar", + "Calendar event can be converted to task", + "Bidirectional updates (reschedule in calendar updates task)" + ] + }, + { + "name": "Natural Language Input", + "description": "Parse natural language for tasks and events ('Meeting with Sarah next Tuesday at 3pm for 1 hour').", + "tech_stack": [ + "OpenAI API", + "compromise.js", + "chrono-node", + "custom NLP" + ], + "complexity": "High", + "dependencies": [ + "Task Management Core", + "Calendar Engine" + ], + "acceptance_criteria": [ + "Parse 90%+ of common date/time expressions", + "Extract duration, participants, location", + "Handle relative dates (tomorrow, next week)", + "Fallback to manual input when parsing fails" + ] + }, + { + "name": "Reminders & Notifications", + "description": "Push, email, and in-app notifications for tasks and events. Smart reminders (travel time, prep time).", + "tech_stack": [ + "Web Push API", + "BullMQ", + "Redis", + "Firebase Cloud Messaging" + ], + "complexity": "Medium", + "dependencies": [ + "Task Management Core", + "Calendar Engine" + ], + "acceptance_criteria": [ + "Push notifications delivered reliably", + "Email reminders with note context", + "Smart reminders (15min before, travel time)", + "Notification preferences per workspace" + ] + }, + { + "name": "External Calendar Sync", + "description": "Sync with Google Calendar, Outlook, Apple iCal. Two-way or one-way sync options.", + "tech_stack": [ + "Google Calendar API", + "Microsoft Graph API", + "iCal parser", + "BullMQ" + ], + "complexity": "High", + "dependencies": [ + "Calendar Engine" + ], + "acceptance_criteria": [ + "Import events from external calendars", + "Export Suite events to external calendars", + "Conflict detection and resolution", + "Sync frequency configurable (real-time, hourly, daily)" + ] + } + ] + }, + "phase_4_ai_intelligence": { + "timeline": "Weeks 15-18", + "theme": "AI-Powered Intelligence Layer", + "features": [ + { + "name": "Semantic Search & Embeddings", + "description": "Vector-based semantic search across all content. Find notes/tasks/events by meaning, not just keywords.", + "tech_stack": [ + "OpenAI text-embedding-3-large", + "pgvector", + "HNSW index", + "React" + ], + "complexity": "High", + "dependencies": [ + "Full-Text Search", + "Note CRUD", + "Task Management Core" + ], + "acceptance_criteria": [ + "Semantic search results relevant to query intent", + "Hybrid search (keyword + semantic) ranking", + "Embeddings updated within 5s of content change", + "Search across all modules (notes, tasks, events)" + ] + }, + { + "name": "AI Writing Assistant", + "description": "Inline AI for expanding, summarizing, rewriting, translating, and answering questions about content.", + "tech_stack": [ + "OpenAI GPT-4o", + "SSE streaming", + "TipTap plugin", + "React" + ], + "complexity": "High", + "dependencies": [ + "Block-Based Editor" + ], + "acceptance_criteria": [ + "AI suggestions appear inline with streaming", + "Accept/reject/dismiss UI for suggestions", + "Context-aware (uses surrounding paragraphs + linked notes)", + "Works offline with local model fallback" + ] + }, + { + "name": "Smart Linking & Knowledge Graph", + "description": "AI auto-discovers relationships between all nodes. Visual graph explorer with filtering and clustering.", + "tech_stack": [ + "D3.js", + "OpenAI API", + "pgvector", + "Graph algorithms", + "React" + ], + "complexity": "High", + "dependencies": [ + "Semantic Search", + "Bidirectional Linking", + "Task-Calendar Integration" + ], + "acceptance_criteria": [ + "Auto-suggest 3-5 related items for any node", + "Graph view with 100+ nodes rendering at 60fps", + "Clustering by workspace, time, or topic", + "User can confirm/reject AI-suggested links" + ] + }, + { + "name": "Smart Scheduling Assistant", + "description": "AI suggests optimal times for tasks based on calendar, priorities, energy levels, and deadlines.", + "tech_stack": [ + "OpenAI/Anthropic API", + "Constraint solver", + "Calendar Engine", + "React" + ], + "complexity": "High", + "dependencies": [ + "Task-Calendar Integration", + "Calendar Engine" + ], + "acceptance_criteria": [ + "Suggest time blocks for unscheduled tasks", + "Respect user preferences (morning focus, afternoon meetings)", + "Consider task dependencies and deadlines", + "One-click accept or modify suggestion" + ] + }, + { + "name": "Meeting Prep & Action Extraction", + "description": "Before meetings, auto-surface relevant notes. After meetings, extract action items and create tasks.", + "tech_stack": [ + "OpenAI GPT-4o", + "NodeLink", + "Task Management Core", + "BullMQ" + ], + "complexity": "High", + "dependencies": [ + "Smart Linking", + "Task Management Core" + ], + "acceptance_criteria": [ + "Auto-collect notes linked to meeting participants/topic", + "Generate meeting prep summary 15min before", + "Extract action items from meeting notes", + "Create linked tasks with assignees and deadlines" + ] + } + ] + }, + "phase_5_collaboration": { + "timeline": "Weeks 19-22", + "theme": "Collaboration & Team Features", + "features": [ + { + "name": "Real-time Collaboration", + "description": "Multi-user editing on notes, shared task lists, shared calendars. Presence awareness, cursors, comments.", + "tech_stack": [ + "Yjs", + "WebSocket", + "Redis adapter", + "React" + ], + "complexity": "High", + "dependencies": [ + "Offline-First Sync", + "Notes MVP", + "Task Management Core" + ], + "acceptance_criteria": [ + "3+ users editing same note simultaneously", + "Cursor positions and selections visible", + "Comments and suggestions on specific blocks", + "Conflict-free merging with CRDTs" + ] + }, + { + "name": "Workspace & Team Management", + "description": "Workspaces with members, roles (Owner/Admin/Editor/Viewer), permissions, and activity feeds.", + "tech_stack": [ + "PostgreSQL RLS", + "CASL", + "React", + "Zustand" + ], + "complexity": "Medium", + "dependencies": [ + "Authentication", + "Real-time Collaboration" + ], + "acceptance_criteria": [ + "Role-based access control enforced at API level", + "Workspace switching with isolated data", + "Member invitation via email/link", + "Activity feed showing team actions" + ] + }, + { + "name": "Sharing & Permissions", + "description": "Share individual nodes or folders with granular permissions. Public links with optional passwords.", + "tech_stack": [ + "PostgreSQL", + "CASL", + "React", + "UUID tokens" + ], + "complexity": "Medium", + "dependencies": [ + "Workspace & Team Management" + ], + "acceptance_criteria": [ + "Share via link with view/edit permissions", + "Password-protected public links", + "Revoke sharing instantly", + "Audit log of all share actions" + ] + }, + { + "name": "Templates & Automation", + "description": "Customizable templates for notes, tasks, events. Automation rules (when X, do Y).", + "tech_stack": [ + "JSON Schema", + "Workflow engine", + "BullMQ", + "React" + ], + "complexity": "High", + "dependencies": [ + "Notes MVP", + "Task Management Core", + "Calendar Engine" + ], + "acceptance_criteria": [ + "Template gallery with 20+ built-in templates", + "User-created templates with dynamic fields", + "Automation: 'When task created with tag X, add to project Y'", + "Webhook triggers for external integrations" + ] + } + ] + }, + "phase_6_platform_scale": { + "timeline": "Weeks 23-28", + "theme": "Platform, Extensibility & Enterprise", + "features": [ + { + "name": "Public API & Webhooks", + "description": "REST and GraphQL APIs with comprehensive documentation. Webhook events for all mutations.", + "tech_stack": [ + "Fastify", + "GraphQL (Mercurius)", + "OpenAPI", + "Webhook delivery" + ], + "complexity": "Medium", + "dependencies": [ + "Workspace & Team Management" + ], + "acceptance_criteria": [ + "REST API covering all CRUD operations", + "GraphQL with subscriptions for real-time", + "Webhook retry logic with exponential backoff", + "API rate limits and usage dashboards" + ] + }, + { + "name": "Plugin System", + "description": "Third-party extensions with sandboxed execution. Plugin marketplace.", + "tech_stack": [ + "iframe sandbox", + "Plugin API", + "Manifest schema", + "CodeSandbox API" + ], + "complexity": "High", + "dependencies": [ + "Public API" + ], + "acceptance_criteria": [ + "Plugin manifest validation and installation", + "Sandboxed execution with limited permissions", + "Plugin settings UI integration", + "Marketplace with ratings and reviews" + ] + }, + { + "name": "Desktop & Mobile Apps", + "description": "Native desktop (Tauri) and mobile (React Native) with full feature parity and offline support.", + "tech_stack": [ + "Tauri", + "React Native", + "Expo", + "SQLite (local)", + "Capacitor" + ], + "complexity": "High", + "dependencies": [ + "Offline-First Sync", + "All core modules" + ], + "acceptance_criteria": [ + "Desktop app <50MB installer", + "Mobile app on iOS and Android", + "Full offline functionality on all platforms", + "Native notifications and system integrations" + ] + }, + { + "name": "SSO & Enterprise Compliance", + "description": "SAML 2.0, OIDC, SCIM provisioning. Audit logs, data retention, GDPR tools, SOC 2 readiness.", + "tech_stack": [ + "Passport.js", + "SAML", + "SCIM", + "Audit trail", + "Encryption" + ], + "complexity": "Medium", + "dependencies": [ + "Workspace & Team Management" + ], + "acceptance_criteria": [ + "SAML integration with major IdPs (Okta, Azure AD)", + "SCIM user provisioning and deprovisioning", + "Complete audit trail exportable as CSV/JSON", + "GDPR data export and deletion within 24h" + ] + }, + { + "name": "Self-Hosting & On-Premise", + "description": "Docker-based deployment with license management. Single-tenant option for enterprise.", + "tech_stack": [ + "Docker Compose", + "Kubernetes", + "License API", + "Terraform" + ], + "complexity": "Medium", + "dependencies": [ + "All core modules" + ], + "acceptance_criteria": [ + "One-command Docker deployment", + "License validation and renewal", + "Automated backups and restore", + "Health checks and monitoring endpoints" + ] + }, + { + "name": "Advanced Analytics Dashboard", + "description": "Personal and team productivity insights. Time tracking, completion rates, focus metrics.", + "tech_stack": [ + "ClickHouse", + "Metabase", + "D3.js", + "React" + ], + "complexity": "Medium", + "dependencies": [ + "Activity tracking", + "Workspace & Team Management" + ], + "acceptance_criteria": [ + "Personal productivity score and trends", + "Team workload distribution view", + "Time spent by project/category", + "Exportable reports (PDF, CSV)" + ] + } + ] + } + }, + "api_design": { + "rest_endpoints": [ + { + "method": "GET", + "path": "/api/v1/nodes", + "description": "List all nodes with filtering by type, workspace, date, status, tags" + }, + { + "method": "POST", + "path": "/api/v1/nodes", + "description": "Create new node (task, event, note, project, goal)" + }, + { + "method": "GET", + "path": "/api/v1/nodes/:id", + "description": "Get node by ID with links, backlinks, and related content" + }, + { + "method": "PATCH", + "path": "/api/v1/nodes/:id", + "description": "Update node (partial, optimistic locking)" + }, + { + "method": "DELETE", + "path": "/api/v1/nodes/:id", + "description": "Soft delete node (move to trash)" + }, + { + "method": "POST", + "path": "/api/v1/nodes/:id/restore", + "description": "Restore node from trash" + }, + { + "method": "GET", + "path": "/api/v1/nodes/:id/links", + "description": "Get all outgoing and incoming links for a node" + }, + { + "method": "POST", + "path": "/api/v1/nodes/:id/links", + "description": "Create link between nodes" + }, + { + "method": "GET", + "path": "/api/v1/nodes/:id/related", + "description": "AI-suggested related nodes (semantic + graph)" + }, + { + "method": "POST", + "path": "/api/v1/nodes/:id/ai", + "description": "AI operations: summarize, expand, rewrite, extract actions, suggest links" + }, + { + "method": "GET", + "path": "/api/v1/search", + "description": "Hybrid search (full-text + semantic) across all nodes" + }, + { + "method": "GET", + "path": "/api/v1/workspaces/:id/graph", + "description": "Knowledge graph data for visualization (nodes + links)" + }, + { + "method": "GET", + "path": "/api/v1/workspaces/:id/calendar", + "description": "Calendar events for a workspace with date range" + }, + { + "method": "GET", + "path": "/api/v1/workspaces/:id/tasks", + "description": "Tasks for a workspace with filters and sorting" + }, + { + "method": "GET", + "path": "/api/v1/workspaces/:id/notes", + "description": "Notes for a workspace with folder hierarchy" + }, + { + "method": "GET", + "path": "/api/v1/workspaces/:id/activity", + "description": "Activity feed for workspace" + }, + { + "method": "POST", + "path": "/api/v1/natural-language", + "description": "Parse natural language input into structured node data" + }, + { + "method": "POST", + "path": "/api/v1/sync", + "description": "Delta sync endpoint for offline-first clients" + }, + { + "method": "GET", + "path": "/ws/collab/:nodeId", + "description": "WebSocket for real-time collaboration on a node" + }, + { + "method": "GET", + "path": "/api/v1/user/me", + "description": "Current user profile, preferences, and workspaces" + }, + { + "method": "PATCH", + "path": "/api/v1/user/me", + "description": "Update user preferences and settings" + }, + { + "method": "GET", + "path": "/api/v1/user/me/notifications", + "description": "User notification feed" + }, + { + "method": "GET", + "path": "/api/v1/integrations/calendars", + "description": "List connected external calendars" + }, + { + "method": "POST", + "path": "/api/v1/integrations/calendars/:provider/connect", + "description": "Connect external calendar (Google, Outlook, Apple)" + } + ], + "graphql_schema": "\n Core Types: User, Workspace, Node, NodeLink, Tag, Folder, Reminder, Activity, Attachment, WorkspaceMember\n\n Queries:\n - nodes(filter: NodeFilter, pagination: Pagination): NodeConnection\n - node(id: UUID!): Node\n - search(query: String!, type: SearchType, filters: SearchFilters): SearchResultConnection\n - relatedNodes(id: UUID!, limit: Int): [NodeLink]\n - graph(workspaceId: UUID!, depth: Int): GraphData\n - calendar(workspaceId: UUID!, range: DateRange): [Node]\n - tasks(workspaceId: UUID!, filters: TaskFilters): [Node]\n - notes(workspaceId: UUID!, folderId: UUID): [Node]\n - activity(workspaceId: UUID!, limit: Int): [Activity]\n\n Mutations:\n - createNode(input: CreateNodeInput!): Node\n - updateNode(id: UUID!, input: UpdateNodeInput!): Node\n - deleteNode(id: UUID!): Boolean\n - createLink(input: CreateLinkInput!): NodeLink\n - deleteLink(id: UUID!): Boolean\n - aiAssist(id: UUID!, operation: AIOperation!, context: String): AIResult\n - naturalLanguage(input: String!): ParsedNodeData\n\n Subscriptions:\n - nodeUpdated(id: UUID!): Node\n - userPresence(workspaceId: UUID!): [UserPresence]\n - notificationReceived(userId: UUID!): Notification\n " + }, + "ai_integration": { + "models": [ + { + "provider": "OpenAI", + "model": "gpt-4o", + "use_case": "Writing assistant, summarization, action extraction, natural language parsing", + "priority": "Primary" + }, + { + "provider": "Anthropic", + "model": "claude-3-5-sonnet", + "use_case": "Long-context analysis, complex reasoning, meeting prep", + "priority": "Fallback" + }, + { + "provider": "Local", + "model": "llama3.1/phi4 via Ollama", + "use_case": "Privacy-sensitive operations, offline mode, cost reduction", + "priority": "Offline fallback" + }, + { + "provider": "OpenAI", + "model": "text-embedding-3-large", + "use_case": "Node embeddings for semantic search and recommendations", + "priority": "Primary" + }, + { + "provider": "Local", + "model": "nomic-embed-text via Ollama", + "use_case": "Offline embeddings for local-only content", + "priority": "Offline fallback" + } + ], + "prompts": { + "summarize": "Summarize the following content in 3-5 bullet points, preserving key insights, action items, and decisions:\n\n{content}", + "expand": "Expand on the following outline/idea with detailed explanations, examples, and connections to related concepts. Maintain the original tone and style:\n\n{content}", + "rewrite": "Rewrite the following text to be {style} (e.g., more concise, more formal, simpler). Preserve all key information:\n\n{content}", + "link_suggestions": "Given this node:\n{current_node}\n\nAnd these candidate nodes:\n{candidates}\n\nIdentify which nodes are semantically related and explain why. Consider content similarity, shared topics, temporal proximity, and participant overlap. Return as JSON array of {{node_id, relevance_score, reason, link_type}}.", + "tag_generation": "Generate 3-5 relevant tags for this content. Be specific and use domain-appropriate terminology. Consider existing tags: {existing_tags}:\n\n{content}", + "natural_language_parse": "Parse the following natural language input into structured data. Extract: type (task/event/note), title, description, due_date, duration, priority, participants, location, tags, related_notes. Return as JSON. Input: '{input}'", + "action_extraction": "Extract all action items from the following meeting notes or text. For each action item, identify: task description, assignee (if mentioned), deadline (if mentioned), priority. Return as JSON array.\n\n{content}", + "meeting_prep": "The user has a meeting titled '{meeting_title}' with {participants} at {time}. Based on their notes and previous meetings, summarize relevant context, open questions, and suggested talking points.\n\nRelevant notes:\n{related_notes}", + "smart_schedule": "Given these unscheduled tasks with priorities and deadlines:\n{tasks}\n\nAnd this calendar availability:\n{availability}\n\nSuggest optimal time blocks for each task. Consider: task priority, deadline proximity, estimated duration, user energy patterns (morning/evening preference), and meeting prep time. Return as JSON array of {{task_id, suggested_start, suggested_end, reasoning}}." + }, + "embedding_pipeline": [ + "1. Chunk node content into semantic segments (paragraphs, sections, task descriptions)", + "2. Generate embeddings for each chunk + full node summary", + "3. Store in pgvector with metadata (node_id, chunk_index, type, workspace_id)", + "4. Build HNSW index for fast approximate nearest neighbor search", + "5. Update embeddings asynchronously on node modification (BullMQ queue)", + "6. Cache popular embeddings in Redis", + "7. Re-embed all content monthly with latest model version" + ], + "ai_features": [ + "Inline writing assistant (expand, summarize, rewrite, translate)", + "Smart linking suggestions across all modules", + "Auto-tagging based on content analysis", + "Natural language task/event creation", + "Meeting prep auto-collection", + "Action item extraction from notes", + "Smart scheduling with calendar optimization", + "Daily/weekly digest generation", + "Duplicate detection and merge suggestions", + "Content similarity warnings (avoid redundant notes)" + ] + }, + "security": { + "authentication": [ + "JWT with refresh token rotation (7-day access, 30-day refresh)", + "OAuth 2.0 (Google, GitHub, Microsoft, Apple)", + "Magic links (passwordless option)", + "WebAuthn/FIDO2 for hardware key support", + "SAML 2.0 and OIDC for enterprise SSO", + "TOTP-based 2FA (optional for personal, required for teams)" + ], + "authorization": [ + "RBAC with predefined roles: Owner, Admin, Editor, Viewer", + "Resource-level permissions (share individual nodes with custom access)", + "Workspace-level access controls with inheritance", + "Field-level encryption for sensitive notes (E2E optional)", + "Row-level security (RLS) in PostgreSQL", + "API-level permission checks (CASL/Ability)", + "Audit logging for all permission changes" + ], + "data_protection": [ + "AES-256 encryption at rest (PostgreSQL TDE)", + "TLS 1.3 in transit (HSTS enforced)", + "E2E encryption option for sensitive workspaces (keys held by user)", + "GDPR data export (complete user data dump in 24h)", + "GDPR right to erasure (complete deletion within 30 days)", + "Data retention policies configurable per workspace", + "Automated backup encryption (AES-256-GCM)", + "SOC 2 Type II compliance target (Phase 6)", + "Penetration testing quarterly (external firm)" + ] + }, + "performance": { + "targets": [ + { + "metric": "Time to First Contentful Paint", + "target": "< 1.0s", + "measurement": "Lighthouse" + }, + { + "metric": "Time to Interactive", + "target": "< 2.5s", + "measurement": "Lighthouse" + }, + { + "metric": "Editor interaction latency", + "target": "< 30ms", + "measurement": "Chrome DevTools" + }, + { + "metric": "Search response time (full-text)", + "target": "< 50ms", + "measurement": "API response time" + }, + { + "metric": "Search response time (semantic)", + "target": "< 200ms", + "measurement": "API response time" + }, + { + "metric": "AI suggestion latency (first token)", + "target": "< 500ms", + "measurement": "SSE stream start" + }, + { + "metric": "Calendar render (month view, 100 events)", + "target": "< 100ms", + "measurement": "React profiler" + }, + { + "metric": "Task list render (1000 tasks)", + "target": "< 150ms", + "measurement": "React profiler" + }, + { + "metric": "Sync reconciliation (100 changes)", + "target": "< 2s", + "measurement": "Offline simulation" + }, + { + "metric": "Concurrent users per API node", + "target": "> 2000", + "measurement": "Load testing" + }, + { + "metric": "WebSocket message latency", + "target": "< 50ms", + "measurement": "Ping/pong" + }, + { + "metric": "Database query P99", + "target": "< 100ms", + "measurement": "PostgreSQL logs" + } + ], + "optimization_strategies": [ + "Virtualized rendering for long lists (react-window/react-virtuoso)", + "Lazy loading of note content and embeddings (intersection observer)", + "CDN for static assets, avatars, and thumbnails (Cloudflare)", + "Database connection pooling (PgBouncer, 100 connections)", + "Redis caching for hot data (search results, user sessions, workspace configs)", + "Query result caching with stale-while-revalidate", + "WebSocket connection multiplexing (single connection per user)", + "Debounced auto-save (1.5s) with optimistic UI updates", + "Service Worker for asset caching and offline support", + "Image optimization (WebP/AVIF, responsive sizes)", + "Code splitting by module (todo, calendar, notes loaded on demand)", + "Tree shaking and dead code elimination", + "Database query optimization (composite indexes, query plan analysis)", + "Read replicas for search and analytics queries", + "GraphQL query complexity analysis and depth limiting" + ] + }, + "development_workflow": { + "version_control": "Git with trunk-based development (main branch + short-lived feature branches)", + "branching_strategy": "main \u2192 feature/xxx branches (max 3 days) \u2192 PR \u2192 CI \u2192 merge \u2192 auto-deploy staging", + "code_quality": [ + "ESLint + Prettier (strict config, no warnings allowed)", + "TypeScript strict mode with noImplicitAny", + "Husky pre-commit hooks (lint, type-check, test affected)", + "Conventional commits (feat:, fix:, docs:, refactor:, test:, chore:)", + "Branch naming: feature/xxx, fix/xxx, refactor/xxx, docs/xxx" + ], + "testing_strategy": { + "unit_tests": "Vitest for logic, React Testing Library for components, 80% coverage minimum", + "integration_tests": "API endpoint testing with supertest + test database, 60% coverage", + "e2e_tests": "Playwright for critical user flows (auth, create note, search, calendar drag, sync)", + "visual_regression": "Chromatic/Storybook for UI component snapshots", + "performance_tests": "Lighthouse CI + custom benchmarks for editor and calendar", + "contract_tests": "Pact for API consumer-provider contracts" + }, + "deployment_pipeline": [ + "1. Developer pushes feature branch \u2192 triggers CI (lint, type-check, unit tests, build)", + "2. PR created \u2192 automated review (CodeRabbit/PR-Agent) + human review required", + "3. CI passes \u2192 preview deployment generated (Vercel/Railway preview URL)", + "4. E2E tests run against preview environment", + "5. Merge to main \u2192 auto-deploy to staging environment", + "6. Staging smoke tests (automated + manual QA checklist)", + "7. Manual promotion to production with feature flags", + "8. Production deployment with blue-green strategy (zero downtime)", + "9. Post-deploy monitoring (error rates, performance metrics) for 30 minutes", + "10. Automatic rollback if error rate > 0.1% or P95 latency > 2x baseline" + ] + }, + "monetization": { + "free_tier": { + "price": "$0", + "features": [ + "Unlimited personal notes, tasks, and events", + "1 workspace", + "Basic AI (20 requests/day)", + "7-day version history", + "Local sync only (no cloud)", + "Web and mobile access", + "Community support" + ] + }, + "pro_tier": { + "price": "$10/month or $96/year", + "features": [ + "Everything in Free", + "Unlimited AI requests", + "Unlimited workspaces", + "Cloud sync across devices", + "30-day version history", + "Advanced search (semantic + full-text)", + "Knowledge graph view", + "External calendar sync", + "Web clipper", + "Priority email support" + ] + }, + "team_tier": { + "price": "$18/user/month or $180/user/year", + "features": [ + "Everything in Pro", + "Real-time collaboration", + "Team workspaces with RBAC", + "Shared templates and automation", + "Admin dashboard and analytics", + "SSO (Google Workspace, Microsoft 365)", + "90-day version history", + "Shared team calendar", + "API access (10k requests/month)", + "Priority support (24h response)" + ] + }, + "enterprise_tier": { + "price": "Custom pricing", + "features": [ + "Everything in Team", + "SAML/OIDC SSO (Okta, Azure AD, custom)", + "SCIM user provisioning", + "Self-hosting option", + "Unlimited version history", + "Audit logs and compliance reports", + "Custom AI model training", + "Dedicated account manager", + "SLA (99.9% uptime, 4h response)", + "Onboarding and training", + "White-label option" + ] + } + }, + "risk_mitigation": { + "technical_risks": [ + { + "risk": "CRDT conflicts in complex multi-module editing", + "mitigation": "Extensive Yjs testing across all node types, dedicated conflict resolution UI, automated conflict simulation tests" + }, + { + "risk": "AI API latency and cost at scale", + "mitigation": "Aggressive caching of AI responses, local model fallback (Ollama), rate limiting per user, usage quotas with graceful degradation" + }, + { + "risk": "Search performance with millions of nodes", + "mitigation": "Meilisearch sharding, pgvector HNSW indexing, read replicas, query result caching, eventual consistency for embeddings" + }, + { + "risk": "Offline sync data corruption or loss", + "mitigation": "Checksums on all sync operations, sync conflict resolution UI, automated backup before sync, integrity verification on reconnect" + }, + { + "risk": "Calendar recurrence complexity (DST, timezone, leap years)", + "mitigation": "Comprehensive test suite with edge cases, use battle-tested rrule library, UTC storage with timezone display, automated regression tests" + }, + { + "risk": "Cross-platform feature parity gaps", + "mitigation": "Shared business logic layer (React Native Web), feature flags per platform, automated cross-platform E2E tests, platform-specific UI adapters" + } + ], + "business_risks": [ + { + "risk": "Market saturation (Notion, Todoist, Google Calendar, Obsidian)", + "mitigation": "Differentiate on unified experience + AI-native features, target power users who feel fragmentation pain, freemium to reduce switching cost" + }, + { + "risk": "AI dependency and vendor lock-in", + "mitigation": "Local model support from day one, transparent AI usage, user control over AI features, multiple provider support (OpenAI, Anthropic, local)" + }, + { + "risk": "Self-hosting cannibalizing cloud revenue", + "mitigation": "Self-hosting only at Enterprise tier, cloud-first features (collaboration, AI), managed hosting option for teams" + }, + { + "risk": "Team productivity app adoption challenges", + "mitigation": "Individual-first design (works great solo), gradual team features, import from competitors, migration assistance for Enterprise" + } + ] + }, + "success_metrics": { + "engagement": [ + "DAU/MAU ratio > 35%", + "Average session duration > 20 minutes", + "Nodes created per user per week > 15 (tasks + events + notes)", + "Cross-module usage (users who use 2+ modules daily) > 60%", + "AI feature usage (at least 1 AI interaction per week) > 40%" + ], + "retention": [ + "Week-1 retention > 65%", + "Week-4 retention > 45%", + "Month-3 retention > 30%", + "Month-12 retention > 20%", + "NPS score > 55" + ], + "performance": [ + "P99 API latency < 200ms", + "Uptime > 99.95%", + "Zero unplanned data loss incidents", + "Sync conflict resolution rate > 95% automatic", + "AI suggestion acceptance rate > 30%" + ], + "business": [ + "Free-to-Pro conversion rate > 5%", + "Team upgrade rate (Pro users upgrading to Team) > 15%", + "Average revenue per user (ARPU) > $12/month", + "Customer acquisition cost (CAC) < $50", + "Net revenue retention (NRR) > 110%" + ] + }, + "agent_development_guidelines": { + "execution_principles": [ + "Phase-by-phase execution: Complete each phase fully before moving to the next. No skipping MVP features.", + "Module-by-module delivery: Finish Notes MVP before starting Tasks, finish Tasks before Calendar integration.", + "Test-driven development: Write tests before implementation. Maintain >80% coverage for critical paths.", + "Documentation-first: Update API docs, component stories, and data model diagrams before coding.", + "Incremental AI integration: Start with simple prompts, gradually add embeddings, knowledge graphs, and smart scheduling.", + "Performance budgeting: Profile after every major feature. No regressions on existing metrics.", + "Security hardening: Implement auth from day one. Never commit secrets. Use environment configs.", + "Collaboration protocol: Use Yjs for real-time features. Test with 3+ concurrent users minimum.", + "Deployment readiness: Every merged PR must be deployable. Feature flags for incomplete work.", + "Cross-platform consistency: Shared logic layer, platform-specific UI adapters, consistent behavior." + ], + "agent_checkpoints": [ + "After Phase 1: Validate monorepo builds, auth flows work, database migrations reversible, offline sync functional", + "After Phase 2: Validate block editor has all basic blocks, notes CRUD complete, search <100ms, bidirectional linking works", + "After Phase 3: Validate task-calendar drag integration, natural language parsing 90%+ accuracy, external calendar sync working", + "After Phase 4: Validate semantic search relevance, AI suggestions accepted >30%, knowledge graph renders 100+ nodes at 60fps", + "After Phase 5: Validate real-time collaboration with 3+ users, RBAC enforced at API level, sharing permissions granular", + "After Phase 6: Validate REST + GraphQL APIs, plugin sandbox secure, desktop <50MB, mobile on both platforms" + ], + "code_generation_rules": [ + "Generate TypeScript with strict types \u2014 no any types except in test mocks", + "Use functional components with hooks \u2014 no class components", + "Prefer composition over inheritance \u2014 use HOCs and render props sparingly", + "Separate business logic from UI \u2014 custom hooks for data operations", + "Use Zod for all runtime validation \u2014 never trust client input", + "Implement optimistic UI updates \u2014 rollback on error with toast notification", + "Add loading and error states to every async operation \u2014 no silent failures", + "Use React.memo and useMemo judiciously \u2014 profile before optimizing", + "Write accessible components \u2014 ARIA labels, keyboard navigation, focus management", + "Internationalize from day one \u2014 i18n keys for all user-facing strings" + ] + } +} \ No newline at end of file diff --git a/yetanothersuite_implementation_plan.md b/yetanothersuite_implementation_plan.md new file mode 100644 index 0000000..1ec5110 --- /dev/null +++ b/yetanothersuite_implementation_plan.md @@ -0,0 +1,953 @@ +# YetAnotherSuite — Implementation Plan + +> **The Unified Productivity Ecosystem — Todo, Calendar, and Notes, Connected by AI** +> +> Platform: Web (PWA), Desktop (Electron/Tauri), Mobile (React Native) | Phases: 6 | Timeline: 24-28 weeks + +--- + +## 1. Vision & Core Concept + +### Vision +A unified workspace where tasks, events, and knowledge naturally interconnect. No more context switching between apps — your todos appear in your calendar, your notes link to your tasks, and AI surfaces the right information at the right time. + +### Problem Statement +Current productivity stacks are fragmented: todos in one app, calendar in another, notes in a third. Users lose context, duplicate effort, and miss connections between their work. YetAnotherSuite eliminates fragmentation by treating tasks, events, and notes as interconnected nodes in a personal knowledge and action graph. + +### Key Differentiators +- Unified data model — tasks, events, and notes share a single graph structure +- AI-powered cross-modal linking (e.g., 'this note relates to this meeting and these tasks') +- Contextual workspace switching — calendar view shows relevant notes, task view shows upcoming deadlines +- Natural language input across all modules ('Schedule meeting with Sarah next Tuesday and create prep notes') +- Local-first with seamless cloud sync — works offline, syncs when connected +- Time-blocking integration — drag tasks directly onto calendar as time blocks +- Bi-directional references — tasks reference notes, notes reference events, events link to tasks + +### Competitive Positioning +Notion (notes) + Todoist (tasks) + Google Calendar (events) = 3 apps, 3 contexts, 3 syncs. YetAnotherSuite = 1 app, 1 context, 1 sync, with AI connecting everything. + +### Target Users +- Knowledge workers managing complex projects +- Executives and managers coordinating teams +- Researchers and academics with time-bound deliverables +- Freelancers juggling multiple clients and deadlines +- Students managing coursework and research + +--- + +## 2. System Architecture + +### Frontend Stack +- **Framework**: React 18+ with TypeScript (strict mode) +- **State Management**: Zustand (global) + TanStack Query (server state) + Jotai (local UI) +- **Editor Engine**: TipTap / ProseMirror (block-based, extensible) +- **Calendar Engine**: Custom React components + date-fns + rrule for recurrence +- **Styling**: Tailwind CSS + Radix UI primitives + shadcn/ui components +- **Realtime Collaboration**: Yjs (CRDT) for all modules +- **Build Tool**: Vite + Turborepo (monorepo) +- **Desktop Wrapper**: Tauri (Rust-based, lightweight, secure) +- **Mobile**: React Native (shared business logic via React Native Web) +- **Testing**: Vitest + React Testing Library + Playwright + MSW (API mocking) + +### Backend Stack +- **Api Gateway**: Node.js + Fastify (or Go + Gin for performance-critical paths) +- **Database**: PostgreSQL 15+ (primary) with JSONB for flexible content +- **Caching**: Redis (sessions, hot data, rate limiting) +- **Search**: Meilisearch (instant) + pgvector (semantic) — hybrid search +- **Realtime**: WebSocket server (Socket.io or native WS with Redis adapter) +- **Queue**: BullMQ (Redis-based) for background jobs (AI processing, sync, exports) +- **Ai Services**: OpenAI/Anthropic API + local fallback (Ollama) + self-hosted embeddings +- **File Storage**: S3-compatible (MinIO for self-hosting) + CDN for assets +- **Vector Database**: pgvector (PostgreSQL extension) for semantic search and recommendations +- **Sync Engine**: Custom sync protocol (based on CRDTs + operational transforms) for offline-first + +### Infrastructure +- **Containerization**: Docker + Docker Compose (dev) + Kubernetes (production) +- **Orchestration**: Helm charts for K8s deployment +- **Ci Cd**: GitHub Actions with matrix builds (Web, Desktop, Mobile) +- **Monitoring**: Prometheus + Grafana (metrics) + Sentry (errors) + LogRocket (session replay) +- **Deployment**: Railway/Render (MVP) → AWS/GCP (scale) with Terraform +- **Cdn**: Cloudflare (global edge caching) +- **Backup**: Automated PostgreSQL backups + S3 versioning + +--- + +## 3. Unified Data Model + +### Philosophy +All entities (tasks, events, notes) are 'Nodes' in a unified graph. They share common properties (title, content, timestamps, metadata) but have type-specific extensions. Relationships are first-class citizens. + +### Core Entities + +#### User +- **Fields**: id (UUID PK), email (unique, indexed), display_name, avatar_url, preferences (JSONB: theme, timezone, notification_settings, default_views), encryption_key (for E2E encrypted notes), created_at, updated_at, last_active_at +- **Relations**: Workspaces (many-to-many via WorkspaceMember), Nodes (one-to-many, owned), SharedNodes (many-to-many via NodeShare), Activities (one-to-many) + +#### Workspace +- **Fields**: id (UUID PK), name, slug (unique per user), description, settings (JSONB: default_view, color_scheme, ai_enabled, retention_policy), owner_id (FK → User), created_at, updated_at +- **Relations**: Members (many-to-many via WorkspaceMember), Nodes (one-to-many), Tags (one-to-many, workspace-scoped), Folders (one-to-many, workspace-scoped), Integrations (one-to-many) + +#### Node (Polymorphic Base) +- **Fields**: id (UUID PK), type (ENUM: 'task', 'event', 'note', 'project', 'goal'), workspace_id (FK → Workspace), owner_id (FK → User), parent_id (FK → Node, self-referencing for hierarchy), title, content (JSONB: ProseMirror doc for notes, structured data for tasks/events), plain_text (generated, for search), status (ENUM: 'active', 'archived', 'deleted'), priority (INTEGER: 1-5, nullable), start_time (TIMESTAMPTZ, for events and task deadlines), end_time (TIMESTAMPTZ, for events and task durations), duration_minutes (INTEGER, computed or explicit), recurrence_rule (TEXT, iCal RRULE format), completion_rate (DECIMAL, for projects/goals), metadata (JSONB: type-specific data), version (INTEGER, for optimistic locking), is_encrypted (BOOLEAN, for E2E notes), created_at, updated_at, completed_at, archived_at +- **Relations**: Parent (self-referencing), Children (self-referencing), Tags (many-to-many via NodeTag), Links (many-to-many via NodeLink, self-referencing), Backlinks (many-to-many via NodeLink, inverse), Embeddings (one-to-many), Activities (one-to-many), Reminders (one-to-many), Attachments (one-to-many) +- **Indexes**: GIN on content (JSONB), GIN on metadata (JSONB), B-tree on type, status, workspace_id, owner_id, BRIN on created_at (time-series optimization), GIST on tsvector (full-text search) + +#### NodeLink (Relationship Graph) +- **Fields**: id (UUID PK), source_id (FK → Node), target_id (FK → Node), link_type (ENUM: 'references', 'blocks', 'relates_to', 'parent_of', 'child_of', 'scheduled_as', 'prepared_for'), strength (DECIMAL: 0-1, AI-computed relevance), is_auto (BOOLEAN, AI-generated vs user-created), context (TEXT, why they're related), created_at +- **Constraints**: UNIQUE(source_id, target_id, link_type), CHECK(source_id != target_id) +- **Indexes**: B-tree on source_id, target_id, B-tree on link_type, is_auto + +#### Tag +- **Fields**: id (UUID PK), name, color (HEX), workspace_id (FK → Workspace), is_system (BOOLEAN, e.g., 'urgent', 'meeting'), created_at +- **Relations**: Nodes (many-to-many via NodeTag), Workspace (many-to-one) + +#### Folder +- **Fields**: id (UUID PK), name, workspace_id (FK → Workspace), parent_id (FK → Folder, self-referencing), view_type (ENUM: 'list', 'board', 'calendar', 'gallery'), filter_config (JSONB: saved filters), sort_config (JSONB: default sort), order_index (INTEGER), created_at +- **Relations**: Nodes (many-to-many via NodeFolder), Parent (self-referencing), Children (self-referencing) + +#### Reminder +- **Fields**: id (UUID PK), node_id (FK → Node), user_id (FK → User), remind_at (TIMESTAMPTZ), notification_type (ENUM: 'push', 'email', 'sms', 'in_app'), status (ENUM: 'pending', 'sent', 'dismissed', 'snoozed'), snooze_until (TIMESTAMPTZ), created_at + +#### Embedding +- **Fields**: id (UUID PK), node_id (FK → Node), chunk_index (INTEGER, for long content), chunk_text (TEXT, the text segment), vector (VECTOR(1536), pgvector), model_version (TEXT, e.g., 'text-embedding-3-large-v1'), created_at +- **Indexes**: HNSW index on vector (for fast similarity search) + +#### Activity +- **Fields**: id (UUID PK), user_id (FK → User), node_id (FK → Node, nullable), workspace_id (FK → Workspace), action_type (ENUM: 'created', 'updated', 'deleted', 'viewed', 'shared', 'linked', 'completed', 'ai_assisted'), metadata (JSONB: before/after snapshots, AI prompt used, etc.), session_id (TEXT, for grouping), created_at +- **Indexes**: BRIN on created_at, B-tree on user_id, workspace_id, action_type + +#### Attachment +- **Fields**: id (UUID PK), node_id (FK → Node), filename, mime_type, size_bytes, storage_key (S3 path), thumbnail_key (S3 path, for images), uploaded_by (FK → User), created_at + +#### WorkspaceMember +- **Fields**: id (UUID PK), workspace_id (FK → Workspace), user_id (FK → User), role (ENUM: 'owner', 'admin', 'editor', 'viewer'), permissions (JSONB: granular overrides), joined_at, last_accessed_at + +#### SyncCheckpoint +- **Fields**: id (UUID PK), user_id (FK → User), device_id (TEXT), last_sync_at (TIMESTAMPTZ), sync_token (TEXT, for delta sync), device_info (JSONB: os, app_version, screen_size), updated_at + +--- + +## 4. Module Specifications + +### Tasks Module +- **Description**: Full-featured task management with projects, subtasks, and time estimates + +**Core Views**: +- **Inbox**: Uncategorized tasks, quick capture +- **Today**: Tasks due today + scheduled events +- **Upcoming**: Calendar-integrated task timeline +- **Projects**: Hierarchical project boards with progress +- **Anytime**: Tasks without specific deadlines +- **Completed**: Archive with search and restore + +**Features**: +- Quick capture with natural language ('Buy milk tomorrow morning') +- Subtasks and checklists within tasks +- Priority levels (P1-P4) with visual urgency indicators +- Time estimates and actual time tracking +- Recurring tasks with flexible patterns +- Drag-and-drop reordering and nesting +- Batch operations (complete, reschedule, tag, assign) +- Focus mode (Pomodoro integration with task context) + +### Calendar Module +- **Description**: Time-blocking calendar with task integration and smart scheduling + +**Core Views**: +- **Day**: Hour-by-hour with task slots +- **Week**: Standard work week view +- **Month**: Overview with density indicators +- **Year**: Long-term planning with goals +- **Schedule**: List view of upcoming events +- **Availability**: Shareable free/busy slots + +**Features**: +- Drag tasks from todo list onto calendar as time blocks +- Smart scheduling suggestions ('You have 2 hours free Thursday afternoon') +- Recurring events with complex patterns (bi-weekly, nth weekday) +- Multiple calendar layers (work, personal, shared) +- External calendar sync (Google, Outlook, Apple iCal) +- Meeting prep auto-linking (find relevant notes for upcoming meetings) +- Travel time buffers and location-based reminders +- Focus time protection (auto-block deep work sessions) + +### Notes Module +- **Description**: AI-native note-taking with bidirectional linking and knowledge graph + +**Core Views**: +- **All Notes**: Chronological list with search +- **Graph**: Visual knowledge graph of all notes +- **Daily Notes**: Date-stamped journal entries +- **Templates**: Reusable note structures +- **Trash**: Soft-deleted notes with recovery + +**Features**: +- Block-based editor with slash commands and markdown +- Bidirectional linking with auto-suggestion ('[[Meeting Notes]]') +- Daily notes with automatic date headings +- Templates with dynamic fields and placeholders +- Web clipper for saving articles and annotating +- AI-powered summarization and expansion +- Semantic search across all notes +- Export to Markdown, PDF, HTML, Notion + +--- + +## 5. Development Phases & Features + +### Phase 1 Foundation +**Timeline**: Weeks 1-4 | **Theme**: Foundation & Core Infrastructure + +#### Monorepo Setup & Design System +- **Description**: Turborepo with shared packages (ui, utils, types, hooks). shadcn/ui base components. Theme system (light/dark/auto). +- **Complexity**: Medium +- **Tech Stack**: Turborepo, pnpm, Tailwind, Radix UI, shadcn/ui +- **Dependencies**: None +- **Acceptance Criteria**: + - Shared packages build independently + - Design tokens (colors, spacing, typography) centralized + - Storybook running with all base components + - Dark mode toggle working globally + +#### Authentication & User Management +- **Description**: JWT-based auth with refresh tokens, OAuth (Google, GitHub, Microsoft), magic links, password reset, profile management. +- **Complexity**: Medium +- **Tech Stack**: Fastify, Passport.js, PostgreSQL, Redis, JWT +- **Dependencies**: Monorepo Setup +- **Acceptance Criteria**: + - All auth flows working end-to-end + - Session management with Redis + - Rate limiting on auth endpoints + - Email verification and password reset + +#### Database Schema & Migrations +- **Description**: Implement full unified schema with migrations, seed data, and test fixtures. Set up pgvector extension. +- **Complexity**: High +- **Tech Stack**: PostgreSQL, pgvector, Prisma ORM, Docker +- **Dependencies**: Monorepo Setup +- **Acceptance Criteria**: + - All entities created with proper constraints + - Migration system reversible + - Seed data for development + - pgvector extension enabled and indexed + +#### API Foundation & Middleware +- **Description**: REST API structure, error handling, validation (Zod), logging, rate limiting, CORS, API versioning. +- **Complexity**: Medium +- **Tech Stack**: Fastify, Zod, Pino, Helmet +- **Dependencies**: Database Schema, Authentication +- **Acceptance Criteria**: + - Consistent API response format + - Request validation on all endpoints + - Structured logging with correlation IDs + - Rate limiting per user/IP + +#### Offline-First Sync Engine +- **Description**: CRDT-based sync protocol with IndexedDB local storage, background sync, conflict resolution UI. +- **Complexity**: High +- **Tech Stack**: Yjs, IndexedDB, Service Workers, Background Sync API +- **Dependencies**: API Foundation +- **Acceptance Criteria**: + - Create/edit/delete notes offline, sync on reconnect + - Conflict resolution UI for simultaneous edits + - Sync status indicator in UI + - Data integrity verified across devices + +### Phase 2 Notes Mvp +**Timeline**: Weeks 5-8 | **Theme**: Notes Module MVP + +#### Block-Based Editor +- **Description**: Notion-like editor with slash commands, markdown shortcuts, rich embeds, drag-and-drop blocks. +- **Complexity**: High +- **Tech Stack**: TipTap, ProseMirror, React, tippy.js +- **Dependencies**: Monorepo Setup, Offline-First Sync +- **Acceptance Criteria**: + - All basic block types (paragraph, heading, list, code, quote, divider) + - Slash menu with 15+ commands + - Markdown shortcuts (## for H2, - for list) + - Drag-and-drop reordering of blocks + +#### Note CRUD & Organization +- **Description**: Create, read, update, delete notes. Folders, tags, favorites, trash. Note list with sorting and filtering. +- **Complexity**: Medium +- **Tech Stack**: PostgreSQL, Prisma, Zustand, TanStack Query +- **Dependencies**: Database Schema, Block-Based Editor +- **Acceptance Criteria**: + - Full CRUD with optimistic UI updates + - Folder hierarchy with drag-and-drop + - Tag management with color coding + - Trash with 30-day retention and restore + +#### Full-Text Search +- **Description**: Instant search across all notes with highlighting, filters (date, type, tag), and search history. +- **Complexity**: Medium +- **Tech Stack**: Meilisearch, PostgreSQL tsvector, React +- **Dependencies**: Note CRUD +- **Acceptance Criteria**: + - Search results in <100ms for 10k notes + - Highlighting of matched terms + - Filter by date range, tags, folders + - Recent searches and suggestions + +#### Bidirectional Linking +- **Description**: [[Wiki-style links]] with auto-completion, backlink panels, and unlinked references suggestions. +- **Complexity**: High +- **Tech Stack**: TipTap plugin, PostgreSQL, React +- **Dependencies**: Block-Based Editor, Note CRUD +- **Acceptance Criteria**: + - Type [[ to trigger note autocomplete + - Backlink panel showing all references to current note + - Unlinked mentions detection (text matching note titles) + - Broken link detection and repair suggestions + +### Phase 3 Todo Calendar +**Timeline**: Weeks 9-14 | **Theme**: Tasks & Calendar Integration + +#### Task Management Core +- **Description**: Full task CRUD with priorities, due dates, subtasks, projects, sections. Inbox, Today, Upcoming views. +- **Complexity**: High +- **Tech Stack**: React, DnD Kit, date-fns, PostgreSQL +- **Dependencies**: Note CRUD, API Foundation +- **Acceptance Criteria**: + - Task creation with natural language parsing + - Subtask nesting (3 levels deep) + - Priority colors and urgency sorting + - Bulk operations (complete, reschedule, move) + +#### Calendar Engine +- **Description**: Full calendar with day/week/month/year views. Event CRUD, recurring events, all-day events, time zones. +- **Complexity**: High +- **Tech Stack**: React, date-fns, rrule, luxon +- **Dependencies**: Task Management Core +- **Acceptance Criteria**: + - All calendar views rendering correctly + - Recurring events with complex patterns + - Timezone handling (user + event timezones) + - All-day and multi-day events + +#### Task-Calendar Integration +- **Description**: Drag tasks onto calendar as time blocks. Tasks shown in calendar views. Calendar events linked to tasks. +- **Complexity**: High +- **Tech Stack**: DnD Kit, React, PostgreSQL, NodeLink +- **Dependencies**: Task Management Core, Calendar Engine +- **Acceptance Criteria**: + - Drag task from list to calendar slot + - Task appears as time block in calendar + - Calendar event can be converted to task + - Bidirectional updates (reschedule in calendar updates task) + +#### Natural Language Input +- **Description**: Parse natural language for tasks and events ('Meeting with Sarah next Tuesday at 3pm for 1 hour'). +- **Complexity**: High +- **Tech Stack**: OpenAI API, compromise.js, chrono-node, custom NLP +- **Dependencies**: Task Management Core, Calendar Engine +- **Acceptance Criteria**: + - Parse 90%+ of common date/time expressions + - Extract duration, participants, location + - Handle relative dates (tomorrow, next week) + - Fallback to manual input when parsing fails + +#### Reminders & Notifications +- **Description**: Push, email, and in-app notifications for tasks and events. Smart reminders (travel time, prep time). +- **Complexity**: Medium +- **Tech Stack**: Web Push API, BullMQ, Redis, Firebase Cloud Messaging +- **Dependencies**: Task Management Core, Calendar Engine +- **Acceptance Criteria**: + - Push notifications delivered reliably + - Email reminders with note context + - Smart reminders (15min before, travel time) + - Notification preferences per workspace + +#### External Calendar Sync +- **Description**: Sync with Google Calendar, Outlook, Apple iCal. Two-way or one-way sync options. +- **Complexity**: High +- **Tech Stack**: Google Calendar API, Microsoft Graph API, iCal parser, BullMQ +- **Dependencies**: Calendar Engine +- **Acceptance Criteria**: + - Import events from external calendars + - Export Suite events to external calendars + - Conflict detection and resolution + - Sync frequency configurable (real-time, hourly, daily) + +### Phase 4 Ai Intelligence +**Timeline**: Weeks 15-18 | **Theme**: AI-Powered Intelligence Layer + +#### Semantic Search & Embeddings +- **Description**: Vector-based semantic search across all content. Find notes/tasks/events by meaning, not just keywords. +- **Complexity**: High +- **Tech Stack**: OpenAI text-embedding-3-large, pgvector, HNSW index, React +- **Dependencies**: Full-Text Search, Note CRUD, Task Management Core +- **Acceptance Criteria**: + - Semantic search results relevant to query intent + - Hybrid search (keyword + semantic) ranking + - Embeddings updated within 5s of content change + - Search across all modules (notes, tasks, events) + +#### AI Writing Assistant +- **Description**: Inline AI for expanding, summarizing, rewriting, translating, and answering questions about content. +- **Complexity**: High +- **Tech Stack**: OpenAI GPT-4o, SSE streaming, TipTap plugin, React +- **Dependencies**: Block-Based Editor +- **Acceptance Criteria**: + - AI suggestions appear inline with streaming + - Accept/reject/dismiss UI for suggestions + - Context-aware (uses surrounding paragraphs + linked notes) + - Works offline with local model fallback + +#### Smart Linking & Knowledge Graph +- **Description**: AI auto-discovers relationships between all nodes. Visual graph explorer with filtering and clustering. +- **Complexity**: High +- **Tech Stack**: D3.js, OpenAI API, pgvector, Graph algorithms, React +- **Dependencies**: Semantic Search, Bidirectional Linking, Task-Calendar Integration +- **Acceptance Criteria**: + - Auto-suggest 3-5 related items for any node + - Graph view with 100+ nodes rendering at 60fps + - Clustering by workspace, time, or topic + - User can confirm/reject AI-suggested links + +#### Smart Scheduling Assistant +- **Description**: AI suggests optimal times for tasks based on calendar, priorities, energy levels, and deadlines. +- **Complexity**: High +- **Tech Stack**: OpenAI/Anthropic API, Constraint solver, Calendar Engine, React +- **Dependencies**: Task-Calendar Integration, Calendar Engine +- **Acceptance Criteria**: + - Suggest time blocks for unscheduled tasks + - Respect user preferences (morning focus, afternoon meetings) + - Consider task dependencies and deadlines + - One-click accept or modify suggestion + +#### Meeting Prep & Action Extraction +- **Description**: Before meetings, auto-surface relevant notes. After meetings, extract action items and create tasks. +- **Complexity**: High +- **Tech Stack**: OpenAI GPT-4o, NodeLink, Task Management Core, BullMQ +- **Dependencies**: Smart Linking, Task Management Core +- **Acceptance Criteria**: + - Auto-collect notes linked to meeting participants/topic + - Generate meeting prep summary 15min before + - Extract action items from meeting notes + - Create linked tasks with assignees and deadlines + +### Phase 5 Collaboration +**Timeline**: Weeks 19-22 | **Theme**: Collaboration & Team Features + +#### Real-time Collaboration +- **Description**: Multi-user editing on notes, shared task lists, shared calendars. Presence awareness, cursors, comments. +- **Complexity**: High +- **Tech Stack**: Yjs, WebSocket, Redis adapter, React +- **Dependencies**: Offline-First Sync, Notes MVP, Task Management Core +- **Acceptance Criteria**: + - 3+ users editing same note simultaneously + - Cursor positions and selections visible + - Comments and suggestions on specific blocks + - Conflict-free merging with CRDTs + +#### Workspace & Team Management +- **Description**: Workspaces with members, roles (Owner/Admin/Editor/Viewer), permissions, and activity feeds. +- **Complexity**: Medium +- **Tech Stack**: PostgreSQL RLS, CASL, React, Zustand +- **Dependencies**: Authentication, Real-time Collaboration +- **Acceptance Criteria**: + - Role-based access control enforced at API level + - Workspace switching with isolated data + - Member invitation via email/link + - Activity feed showing team actions + +#### Sharing & Permissions +- **Description**: Share individual nodes or folders with granular permissions. Public links with optional passwords. +- **Complexity**: Medium +- **Tech Stack**: PostgreSQL, CASL, React, UUID tokens +- **Dependencies**: Workspace & Team Management +- **Acceptance Criteria**: + - Share via link with view/edit permissions + - Password-protected public links + - Revoke sharing instantly + - Audit log of all share actions + +#### Templates & Automation +- **Description**: Customizable templates for notes, tasks, events. Automation rules (when X, do Y). +- **Complexity**: High +- **Tech Stack**: JSON Schema, Workflow engine, BullMQ, React +- **Dependencies**: Notes MVP, Task Management Core, Calendar Engine +- **Acceptance Criteria**: + - Template gallery with 20+ built-in templates + - User-created templates with dynamic fields + - Automation: 'When task created with tag X, add to project Y' + - Webhook triggers for external integrations + +### Phase 6 Platform Scale +**Timeline**: Weeks 23-28 | **Theme**: Platform, Extensibility & Enterprise + +#### Public API & Webhooks +- **Description**: REST and GraphQL APIs with comprehensive documentation. Webhook events for all mutations. +- **Complexity**: Medium +- **Tech Stack**: Fastify, GraphQL (Mercurius), OpenAPI, Webhook delivery +- **Dependencies**: Workspace & Team Management +- **Acceptance Criteria**: + - REST API covering all CRUD operations + - GraphQL with subscriptions for real-time + - Webhook retry logic with exponential backoff + - API rate limits and usage dashboards + +#### Plugin System +- **Description**: Third-party extensions with sandboxed execution. Plugin marketplace. +- **Complexity**: High +- **Tech Stack**: iframe sandbox, Plugin API, Manifest schema, CodeSandbox API +- **Dependencies**: Public API +- **Acceptance Criteria**: + - Plugin manifest validation and installation + - Sandboxed execution with limited permissions + - Plugin settings UI integration + - Marketplace with ratings and reviews + +#### Desktop & Mobile Apps +- **Description**: Native desktop (Tauri) and mobile (React Native) with full feature parity and offline support. +- **Complexity**: High +- **Tech Stack**: Tauri, React Native, Expo, SQLite (local), Capacitor +- **Dependencies**: Offline-First Sync, All core modules +- **Acceptance Criteria**: + - Desktop app <50MB installer + - Mobile app on iOS and Android + - Full offline functionality on all platforms + - Native notifications and system integrations + +#### SSO & Enterprise Compliance +- **Description**: SAML 2.0, OIDC, SCIM provisioning. Audit logs, data retention, GDPR tools, SOC 2 readiness. +- **Complexity**: Medium +- **Tech Stack**: Passport.js, SAML, SCIM, Audit trail, Encryption +- **Dependencies**: Workspace & Team Management +- **Acceptance Criteria**: + - SAML integration with major IdPs (Okta, Azure AD) + - SCIM user provisioning and deprovisioning + - Complete audit trail exportable as CSV/JSON + - GDPR data export and deletion within 24h + +#### Self-Hosting & On-Premise +- **Description**: Docker-based deployment with license management. Single-tenant option for enterprise. +- **Complexity**: Medium +- **Tech Stack**: Docker Compose, Kubernetes, License API, Terraform +- **Dependencies**: All core modules +- **Acceptance Criteria**: + - One-command Docker deployment + - License validation and renewal + - Automated backups and restore + - Health checks and monitoring endpoints + +#### Advanced Analytics Dashboard +- **Description**: Personal and team productivity insights. Time tracking, completion rates, focus metrics. +- **Complexity**: Medium +- **Tech Stack**: ClickHouse, Metabase, D3.js, React +- **Dependencies**: Activity tracking, Workspace & Team Management +- **Acceptance Criteria**: + - Personal productivity score and trends + - Team workload distribution view + - Time spent by project/category + - Exportable reports (PDF, CSV) + +--- + +## 6. API Design + +### REST Endpoints + +| Method | Path | Description | +|--------|------|-------------| +| GET | `/api/v1/nodes` | List all nodes with filtering by type, workspace, date, status, tags | +| POST | `/api/v1/nodes` | Create new node (task, event, note, project, goal) | +| GET | `/api/v1/nodes/:id` | Get node by ID with links, backlinks, and related content | +| PATCH | `/api/v1/nodes/:id` | Update node (partial, optimistic locking) | +| DELETE | `/api/v1/nodes/:id` | Soft delete node (move to trash) | +| POST | `/api/v1/nodes/:id/restore` | Restore node from trash | +| GET | `/api/v1/nodes/:id/links` | Get all outgoing and incoming links for a node | +| POST | `/api/v1/nodes/:id/links` | Create link between nodes | +| GET | `/api/v1/nodes/:id/related` | AI-suggested related nodes (semantic + graph) | +| POST | `/api/v1/nodes/:id/ai` | AI operations: summarize, expand, rewrite, extract actions, suggest links | +| GET | `/api/v1/search` | Hybrid search (full-text + semantic) across all nodes | +| GET | `/api/v1/workspaces/:id/graph` | Knowledge graph data for visualization (nodes + links) | +| GET | `/api/v1/workspaces/:id/calendar` | Calendar events for a workspace with date range | +| GET | `/api/v1/workspaces/:id/tasks` | Tasks for a workspace with filters and sorting | +| GET | `/api/v1/workspaces/:id/notes` | Notes for a workspace with folder hierarchy | +| GET | `/api/v1/workspaces/:id/activity` | Activity feed for workspace | +| POST | `/api/v1/natural-language` | Parse natural language input into structured node data | +| POST | `/api/v1/sync` | Delta sync endpoint for offline-first clients | +| GET | `/ws/collab/:nodeId` | WebSocket for real-time collaboration on a node | +| GET | `/api/v1/user/me` | Current user profile, preferences, and workspaces | +| PATCH | `/api/v1/user/me` | Update user preferences and settings | +| GET | `/api/v1/user/me/notifications` | User notification feed | +| GET | `/api/v1/integrations/calendars` | List connected external calendars | +| POST | `/api/v1/integrations/calendars/:provider/connect` | Connect external calendar (Google, Outlook, Apple) | + +### GraphQL Schema +``` + + Core Types: User, Workspace, Node, NodeLink, Tag, Folder, Reminder, Activity, Attachment, WorkspaceMember + + Queries: + - nodes(filter: NodeFilter, pagination: Pagination): NodeConnection + - node(id: UUID!): Node + - search(query: String!, type: SearchType, filters: SearchFilters): SearchResultConnection + - relatedNodes(id: UUID!, limit: Int): [NodeLink] + - graph(workspaceId: UUID!, depth: Int): GraphData + - calendar(workspaceId: UUID!, range: DateRange): [Node] + - tasks(workspaceId: UUID!, filters: TaskFilters): [Node] + - notes(workspaceId: UUID!, folderId: UUID): [Node] + - activity(workspaceId: UUID!, limit: Int): [Activity] + + Mutations: + - createNode(input: CreateNodeInput!): Node + - updateNode(id: UUID!, input: UpdateNodeInput!): Node + - deleteNode(id: UUID!): Boolean + - createLink(input: CreateLinkInput!): NodeLink + - deleteLink(id: UUID!): Boolean + - aiAssist(id: UUID!, operation: AIOperation!, context: String): AIResult + - naturalLanguage(input: String!): ParsedNodeData + + Subscriptions: + - nodeUpdated(id: UUID!): Node + - userPresence(workspaceId: UUID!): [UserPresence] + - notificationReceived(userId: UUID!): Notification + +``` + +--- + +## 7. AI Integration Strategy + +### Model Selection +- **OpenAI** — `gpt-4o` (Primary): Writing assistant, summarization, action extraction, natural language parsing +- **Anthropic** — `claude-3-5-sonnet` (Fallback): Long-context analysis, complex reasoning, meeting prep +- **Local** — `llama3.1/phi4 via Ollama` (Offline fallback): Privacy-sensitive operations, offline mode, cost reduction +- **OpenAI** — `text-embedding-3-large` (Primary): Node embeddings for semantic search and recommendations +- **Local** — `nomic-embed-text via Ollama` (Offline fallback): Offline embeddings for local-only content + +### Key Prompts + +**Summarize**: +``` +Summarize the following content in 3-5 bullet points, preserving key insights, action items, and decisions: + +{content} +``` + +**Expand**: +``` +Expand on the following outline/idea with detailed explanations, examples, and connections to related concepts. Maintain the original tone and style: + +{content} +``` + +**Rewrite**: +``` +Rewrite the following text to be {style} (e.g., more concise, more formal, simpler). Preserve all key information: + +{content} +``` + +**Link Suggestions**: +``` +Given this node: +{current_node} + +And these candidate nodes: +{candidates} + +Identify which nodes are semantically related and explain why. Consider content similarity, shared topics, temporal proximity, and participant overlap. Return as JSON array of {{node_id, relevance_score, reason, link_type}}. +``` + +**Tag Generation**: +``` +Generate 3-5 relevant tags for this content. Be specific and use domain-appropriate terminology. Consider existing tags: {existing_tags}: + +{content} +``` + +**Natural Language Parse**: +``` +Parse the following natural language input into structured data. Extract: type (task/event/note), title, description, due_date, duration, priority, participants, location, tags, related_notes. Return as JSON. Input: '{input}' +``` + +**Action Extraction**: +``` +Extract all action items from the following meeting notes or text. For each action item, identify: task description, assignee (if mentioned), deadline (if mentioned), priority. Return as JSON array. + +{content} +``` + +**Meeting Prep**: +``` +The user has a meeting titled '{meeting_title}' with {participants} at {time}. Based on their notes and previous meetings, summarize relevant context, open questions, and suggested talking points. + +Relevant notes: +{related_notes} +``` + +**Smart Schedule**: +``` +Given these unscheduled tasks with priorities and deadlines: +{tasks} + +And this calendar availability: +{availability} + +Suggest optimal time blocks for each task. Consider: task priority, deadline proximity, estimated duration, user energy patterns (morning/evening preference), and meeting prep time. Return as JSON array of {{task_id, suggested_start, suggested_end, reasoning}}. +``` + +### Embedding Pipeline +1. Chunk node content into semantic segments (paragraphs, sections, task descriptions) +2. Generate embeddings for each chunk + full node summary +3. Store in pgvector with metadata (node_id, chunk_index, type, workspace_id) +4. Build HNSW index for fast approximate nearest neighbor search +5. Update embeddings asynchronously on node modification (BullMQ queue) +6. Cache popular embeddings in Redis +7. Re-embed all content monthly with latest model version + +### AI Features +- Inline writing assistant (expand, summarize, rewrite, translate) +- Smart linking suggestions across all modules +- Auto-tagging based on content analysis +- Natural language task/event creation +- Meeting prep auto-collection +- Action item extraction from notes +- Smart scheduling with calendar optimization +- Daily/weekly digest generation +- Duplicate detection and merge suggestions +- Content similarity warnings (avoid redundant notes) + +--- + +## 8. Security & Compliance + +### Authentication +- JWT with refresh token rotation (7-day access, 30-day refresh) +- OAuth 2.0 (Google, GitHub, Microsoft, Apple) +- Magic links (passwordless option) +- WebAuthn/FIDO2 for hardware key support +- SAML 2.0 and OIDC for enterprise SSO +- TOTP-based 2FA (optional for personal, required for teams) + +### Authorization +- RBAC with predefined roles: Owner, Admin, Editor, Viewer +- Resource-level permissions (share individual nodes with custom access) +- Workspace-level access controls with inheritance +- Field-level encryption for sensitive notes (E2E optional) +- Row-level security (RLS) in PostgreSQL +- API-level permission checks (CASL/Ability) +- Audit logging for all permission changes + +### Data Protection +- AES-256 encryption at rest (PostgreSQL TDE) +- TLS 1.3 in transit (HSTS enforced) +- E2E encryption option for sensitive workspaces (keys held by user) +- GDPR data export (complete user data dump in 24h) +- GDPR right to erasure (complete deletion within 30 days) +- Data retention policies configurable per workspace +- Automated backup encryption (AES-256-GCM) +- SOC 2 Type II compliance target (Phase 6) +- Penetration testing quarterly (external firm) + +--- + +## 9. Performance Targets + +| Metric | Target | Measurement | +|--------|--------|-------------| +| Time to First Contentful Paint | < 1.0s | Lighthouse | +| Time to Interactive | < 2.5s | Lighthouse | +| Editor interaction latency | < 30ms | Chrome DevTools | +| Search response time (full-text) | < 50ms | API response time | +| Search response time (semantic) | < 200ms | API response time | +| AI suggestion latency (first token) | < 500ms | SSE stream start | +| Calendar render (month view, 100 events) | < 100ms | React profiler | +| Task list render (1000 tasks) | < 150ms | React profiler | +| Sync reconciliation (100 changes) | < 2s | Offline simulation | +| Concurrent users per API node | > 2000 | Load testing | +| WebSocket message latency | < 50ms | Ping/pong | +| Database query P99 | < 100ms | PostgreSQL logs | + +### Optimization Strategies +- Virtualized rendering for long lists (react-window/react-virtuoso) +- Lazy loading of note content and embeddings (intersection observer) +- CDN for static assets, avatars, and thumbnails (Cloudflare) +- Database connection pooling (PgBouncer, 100 connections) +- Redis caching for hot data (search results, user sessions, workspace configs) +- Query result caching with stale-while-revalidate +- WebSocket connection multiplexing (single connection per user) +- Debounced auto-save (1.5s) with optimistic UI updates +- Service Worker for asset caching and offline support +- Image optimization (WebP/AVIF, responsive sizes) +- Code splitting by module (todo, calendar, notes loaded on demand) +- Tree shaking and dead code elimination +- Database query optimization (composite indexes, query plan analysis) +- Read replicas for search and analytics queries +- GraphQL query complexity analysis and depth limiting + +--- + +## 10. Development Workflow + +### Version Control & Quality +- ESLint + Prettier (strict config, no warnings allowed) +- TypeScript strict mode with noImplicitAny +- Husky pre-commit hooks (lint, type-check, test affected) +- Conventional commits (feat:, fix:, docs:, refactor:, test:, chore:) +- Branch naming: feature/xxx, fix/xxx, refactor/xxx, docs/xxx + +### Testing Strategy +- **Unit Tests**: Vitest for logic, React Testing Library for components, 80% coverage minimum +- **Integration Tests**: API endpoint testing with supertest + test database, 60% coverage +- **E2E Tests**: Playwright for critical user flows (auth, create note, search, calendar drag, sync) +- **Visual Regression**: Chromatic/Storybook for UI component snapshots +- **Performance Tests**: Lighthouse CI + custom benchmarks for editor and calendar +- **Contract Tests**: Pact for API consumer-provider contracts + +### Deployment Pipeline +1. Developer pushes feature branch → triggers CI (lint, type-check, unit tests, build) +2. PR created → automated review (CodeRabbit/PR-Agent) + human review required +3. CI passes → preview deployment generated (Vercel/Railway preview URL) +4. E2E tests run against preview environment +5. Merge to main → auto-deploy to staging environment +6. Staging smoke tests (automated + manual QA checklist) +7. Manual promotion to production with feature flags +8. Production deployment with blue-green strategy (zero downtime) +9. Post-deploy monitoring (error rates, performance metrics) for 30 minutes +10. Automatic rollback if error rate > 0.1% or P95 latency > 2x baseline + +--- + +## 11. Monetization Strategy + +### Free — $0 +- Unlimited personal notes, tasks, and events +- 1 workspace +- Basic AI (20 requests/day) +- 7-day version history +- Local sync only (no cloud) +- Web and mobile access +- Community support + +### Pro — $10/month or $96/year +- Everything in Free +- Unlimited AI requests +- Unlimited workspaces +- Cloud sync across devices +- 30-day version history +- Advanced search (semantic + full-text) +- Knowledge graph view +- External calendar sync +- Web clipper +- Priority email support + +### Team — $18/user/month or $180/user/year +- Everything in Pro +- Real-time collaboration +- Team workspaces with RBAC +- Shared templates and automation +- Admin dashboard and analytics +- SSO (Google Workspace, Microsoft 365) +- 90-day version history +- Shared team calendar +- API access (10k requests/month) +- Priority support (24h response) + +### Enterprise — Custom pricing +- Everything in Team +- SAML/OIDC SSO (Okta, Azure AD, custom) +- SCIM user provisioning +- Self-hosting option +- Unlimited version history +- Audit logs and compliance reports +- Custom AI model training +- Dedicated account manager +- SLA (99.9% uptime, 4h response) +- Onboarding and training +- White-label option + +--- + +## 12. Risk Mitigation + +### Technical Risks +- **CRDT conflicts in complex multi-module editing**: Extensive Yjs testing across all node types, dedicated conflict resolution UI, automated conflict simulation tests +- **AI API latency and cost at scale**: Aggressive caching of AI responses, local model fallback (Ollama), rate limiting per user, usage quotas with graceful degradation +- **Search performance with millions of nodes**: Meilisearch sharding, pgvector HNSW indexing, read replicas, query result caching, eventual consistency for embeddings +- **Offline sync data corruption or loss**: Checksums on all sync operations, sync conflict resolution UI, automated backup before sync, integrity verification on reconnect +- **Calendar recurrence complexity (DST, timezone, leap years)**: Comprehensive test suite with edge cases, use battle-tested rrule library, UTC storage with timezone display, automated regression tests +- **Cross-platform feature parity gaps**: Shared business logic layer (React Native Web), feature flags per platform, automated cross-platform E2E tests, platform-specific UI adapters + +### Business Risks +- **Market saturation (Notion, Todoist, Google Calendar, Obsidian)**: Differentiate on unified experience + AI-native features, target power users who feel fragmentation pain, freemium to reduce switching cost +- **AI dependency and vendor lock-in**: Local model support from day one, transparent AI usage, user control over AI features, multiple provider support (OpenAI, Anthropic, local) +- **Self-hosting cannibalizing cloud revenue**: Self-hosting only at Enterprise tier, cloud-first features (collaboration, AI), managed hosting option for teams +- **Team productivity app adoption challenges**: Individual-first design (works great solo), gradual team features, import from competitors, migration assistance for Enterprise + +--- + +## 13. Success Metrics + +### Engagement +- DAU/MAU ratio > 35% +- Average session duration > 20 minutes +- Nodes created per user per week > 15 (tasks + events + notes) +- Cross-module usage (users who use 2+ modules daily) > 60% +- AI feature usage (at least 1 AI interaction per week) > 40% + +### Retention +- Week-1 retention > 65% +- Week-4 retention > 45% +- Month-3 retention > 30% +- Month-12 retention > 20% +- NPS score > 55 + +### Performance +- P99 API latency < 200ms +- Uptime > 99.95% +- Zero unplanned data loss incidents +- Sync conflict resolution rate > 95% automatic +- AI suggestion acceptance rate > 30% + +### Business +- Free-to-Pro conversion rate > 5% +- Team upgrade rate (Pro users upgrading to Team) > 15% +- Average revenue per user (ARPU) > $12/month +- Customer acquisition cost (CAC) < $50 +- Net revenue retention (NRR) > 110% + +--- + +## 14. Agent Development Guidelines + +### Execution Principles +Phase-by-phase execution: Complete each phase fully before moving to the next. No skipping MVP features. +Module-by-module delivery: Finish Notes MVP before starting Tasks, finish Tasks before Calendar integration. +Test-driven development: Write tests before implementation. Maintain >80% coverage for critical paths. +Documentation-first: Update API docs, component stories, and data model diagrams before coding. +Incremental AI integration: Start with simple prompts, gradually add embeddings, knowledge graphs, and smart scheduling. +Performance budgeting: Profile after every major feature. No regressions on existing metrics. +Security hardening: Implement auth from day one. Never commit secrets. Use environment configs. +Collaboration protocol: Use Yjs for real-time features. Test with 3+ concurrent users minimum. +Deployment readiness: Every merged PR must be deployable. Feature flags for incomplete work. +Cross-platform consistency: Shared logic layer, platform-specific UI adapters, consistent behavior. + +### Agent Checkpoints +- After Phase 1: Validate monorepo builds, auth flows work, database migrations reversible, offline sync functional +- After Phase 2: Validate block editor has all basic blocks, notes CRUD complete, search <100ms, bidirectional linking works +- After Phase 3: Validate task-calendar drag integration, natural language parsing 90%+ accuracy, external calendar sync working +- After Phase 4: Validate semantic search relevance, AI suggestions accepted >30%, knowledge graph renders 100+ nodes at 60fps +- After Phase 5: Validate real-time collaboration with 3+ users, RBAC enforced at API level, sharing permissions granular +- After Phase 6: Validate REST + GraphQL APIs, plugin sandbox secure, desktop <50MB, mobile on both platforms + +### Code Generation Rules +- Generate TypeScript with strict types — no any types except in test mocks +- Use functional components with hooks — no class components +- Prefer composition over inheritance — use HOCs and render props sparingly +- Separate business logic from UI — custom hooks for data operations +- Use Zod for all runtime validation — never trust client input +- Implement optimistic UI updates — rollback on error with toast notification +- Add loading and error states to every async operation — no silent failures +- Use React.memo and useMemo judiciously — profile before optimizing +- Write accessible components — ARIA labels, keyboard navigation, focus management +- Internationalize from day one — i18n keys for all user-facing strings + +--- + +*Plan generated for YetAnotherSuite — Unified Productivity Ecosystem* +*30 Features | 6 Phases | 24-28 Weeks | 12 Core Entities | 5 AI Models | 24 API Endpoints*