diff --git a/.claude/skills/api/SKILL.md b/.claude/skills/api/SKILL.md index da03fcd..48ee41d 100644 --- a/.claude/skills/api/SKILL.md +++ b/.claude/skills/api/SKILL.md @@ -14,14 +14,17 @@ Review the `api/` package for quality, consistency, and every-plugin best practi ``` api/ ├── src/ -│ ├── contract.ts # oRPC route definitions -│ ├── index.ts # Plugin definition (createPlugin) +│ ├── contract.ts # oRPC route definitions +│ ├── index.ts # Plugin definition (createPlugin) │ ├── db/ -│ │ └── schema.ts # Drizzle ORM schema -│ ├── services/ -│ │ └── agent.ts # NEAR AI integration -│ └── store.ts # Database connection -├── plugin.dev.ts # Local dev configuration +│ │ ├── index.ts # Database connection layer +│ │ ├── schema.ts # Drizzle ORM schema +│ │ └── migrations/ # SQL migration files +│ └── services/ +│ ├── index.ts # Service exports +│ └── agent.ts # NEAR AI integration +├── plugin.dev.ts # Local dev configuration +├── drizzle.config.ts # Drizzle config └── package.json ``` @@ -35,40 +38,43 @@ api/ ### 2. Plugin Structure - [ ] Uses `createPlugin()` from every-plugin -- [ ] Variables and secrets properly typed -- [ ] Context schema defined -- [ ] Initialize/shutdown handlers implemented +- [ ] Variables and secrets properly typed with Zod schemas +- [ ] Context schema defined (nearAccountId, role) +- [ ] Initialize returns `{ db, agentService }` +- [ ] Shutdown handler implemented ### 3. Database Schema -- [ ] Tables defined for core features (conversations, messages, key-value store) +- [ ] Tables defined: `conversation`, `message`, `kvStore` - [ ] Proper indexes for query performance - [ ] Relations defined correctly with cascading deletes -- [ ] Timestamps use Date type +- [ ] Per-user isolation via `nearAccountId` ### 4. Services -- [ ] AgentService integrates NEAR AI Cloud +- [ ] AgentService integrates NEAR AI Cloud via OpenAI SDK - [ ] Streaming chat implementation with async generators - [ ] Conversation history management (context window) - [ ] Graceful fallback when API key not configured ### 5. Router Handlers -- [ ] Authentication middleware applied +- [ ] `requireAuth` middleware for protected routes +- [ ] `requireAdmin` middleware for admin routes - [ ] Proper error handling with ORPCError - [ ] Input validation via contract - [ ] Date serialization to ISO strings ### 6. Configuration - [ ] `plugin.dev.ts` matches production config -- [ ] Secrets loaded from environment -- [ ] Default values are sensible +- [ ] Secrets: `API_DATABASE_URL`, `API_DATABASE_AUTH_TOKEN`, `NEAR_AI_API_KEY`, `NEAR_AI_BASE_URL` +- [ ] Variables: `NEAR_AI_MODEL`, `NEAR_AI_BASE_URL` ## Key Files to Check 1. `src/contract.ts` - API contract definitions 2. `src/index.ts` - Plugin implementation 3. `src/db/schema.ts` - Database tables -4. `src/services/agent.ts` - NEAR AI integration -5. `plugin.dev.ts` - Development configuration +4. `src/db/index.ts` - Database connection +5. `src/services/agent.ts` - NEAR AI integration +6. `plugin.dev.ts` - Development configuration ## Output Format diff --git a/.claude/skills/host/SKILL.md b/.claude/skills/host/SKILL.md index eda5162..42ef174 100644 --- a/.claude/skills/host/SKILL.md +++ b/.claude/skills/host/SKILL.md @@ -13,62 +13,91 @@ Review the `host/` package for quality, consistency, and Module Federation best ``` host/ -├── server.ts # HTTP server entry point +├── server.ts # Entry point +├── bootstrap.ts # Remote host loader ├── src/ -│ ├── config.ts # Runtime config loader (bos.config.json) -│ ├── runtime.ts # Plugin initialization -│ ├── routers/ # Route handlers -│ └── auth/ # Better-Auth setup -├── .env.example # Environment template +│ ├── program.ts # Main server program +│ ├── ui.tsx # UI rendering +│ ├── types.ts # Type definitions +│ ├── db/ +│ │ └── schema/ +│ │ └── auth.ts # Auth schema +│ ├── layers/ +│ │ └── index.ts # Effect layers composition +│ ├── lib/ +│ │ └── schemas.ts # Shared schemas +│ ├── services/ +│ │ ├── auth.ts # Better-Auth setup +│ │ ├── config.ts # Runtime config loader (bos.config.json) +│ │ ├── context.ts # Request context +│ │ ├── database.ts # Database connection +│ │ ├── errors.ts # Error types +│ │ ├── federation.server.ts # UI module loading +│ │ ├── plugins.ts # API plugin loading +│ │ └── router.ts # Router creation +│ └── utils/ +│ └── logger.ts # Logging utility +├── migrations/ # Drizzle migrations +├── drizzle.config.ts # Drizzle config +├── rsbuild.config.ts # Build configuration └── package.json -bos.config.json # Central runtime configuration (root level) +bos.config.json # Central runtime configuration (root level) ``` ## Review Checklist ### 1. Server Setup -- [ ] Hono.js configured correctly -- [ ] CORS and security headers -- [ ] Static file serving +- [ ] Hono.js configured correctly in `src/program.ts` +- [ ] CORS configured with `CORS_ORIGIN` or config URLs +- [ ] Health endpoint at `/health` - [ ] Error handling middleware ### 2. Configuration Loading -- [ ] `bos.config.json` parsed correctly +- [ ] `src/services/config.ts` parses `bos.config.json` correctly - [ ] Environment-based URL switching (dev/prod) -- [ ] Secret template injection (`{{VAR_NAME}}`) +- [ ] Secret loading from environment variables - [ ] Variables vs secrets distinction ### 3. Plugin Runtime -- [ ] Uses `createPluginRuntime()` from every-plugin +- [ ] `src/services/plugins.ts` uses every-plugin runtime - [ ] Secrets extracted from environment -- [ ] Plugin URL resolved correctly +- [ ] Plugin URL resolved from config - [ ] Error handling for plugin load failures ### 4. Authentication -- [ ] Better-Auth configured -- [ ] NEAR Protocol auth (better-near-auth) +- [ ] `src/services/auth.ts` uses Better-Auth +- [ ] NEAR Protocol auth via better-near-auth - [ ] Session management -- [ ] Protected routes +- [ ] Auth routes at `/api/auth/*` ### 5. Module Federation -- [ ] UI remote loaded correctly -- [ ] SSR/CSR handling -- [ ] Fallback behavior +- [ ] `src/services/federation.server.ts` loads UI remote +- [ ] SSR rendering via `loadRouterModule` +- [ ] Fallback behavior when module not loaded ### 6. bos.config.json - [ ] All apps configured (host, ui, api) - [ ] Development and production URLs - [ ] API variables include NEAR_AI_MODEL - [ ] API secrets include all required keys +- [ ] Host secrets include auth secrets + +### 7. Effect-TS Architecture +- [ ] Services use Effect Service pattern +- [ ] Layers composed in `src/layers/index.ts` +- [ ] Proper error handling with ConfigError, etc. ## Key Files to Check -1. `server.ts` - Main entry point -2. `src/config.ts` - Configuration loader -3. `src/runtime.ts` - Plugin initialization -4. `src/routers/index.ts` - Route merging -5. `../bos.config.json` - Central config -6. `.env.example` - Required environment variables +1. `server.ts` - Entry point +2. `src/program.ts` - Main server logic +3. `src/services/config.ts` - Configuration loader +4. `src/services/auth.ts` - Authentication setup +5. `src/services/plugins.ts` - Plugin loading +6. `src/services/federation.server.ts` - UI module loading +7. `src/services/router.ts` - Route creation +8. `src/layers/index.ts` - Layer composition +9. `../bos.config.json` - Central config ## Output Format diff --git a/.claude/skills/ui/SKILL.md b/.claude/skills/ui/SKILL.md index bdae1b1..5da75ad 100644 --- a/.claude/skills/ui/SKILL.md +++ b/.claude/skills/ui/SKILL.md @@ -14,11 +14,44 @@ Review the `ui/` package for quality, consistency, and best practices. ``` ui/ ├── src/ -│ ├── components/ # React components (chat) -│ ├── routes/ # TanStack Router file-based routes -│ ├── integrations/ # API client setup -│ └── utils/ # Utilities (orpc client) -├── rsbuild.config.ts # Build configuration +│ ├── router.tsx # Client router +│ ├── router.server.tsx # Server router (SSR) +│ ├── hydrate.tsx # Client hydration entry +│ ├── components/ +│ │ ├── index.ts # Public component exports +│ │ ├── chat/ # Chat feature components +│ │ │ ├── chat-input.tsx +│ │ │ ├── chat-message.tsx +│ │ │ └── chat-page.tsx +│ │ ├── kv/ # Key-value editor +│ │ │ └── kv-editor.tsx +│ │ └── ui/ # shadcn/ui primitives +│ ├── hooks/ +│ │ ├── index.ts +│ │ └── use-client.ts +│ ├── lib/ +│ │ ├── auth-client.ts # better-auth client +│ │ ├── auth-utils.ts # Auth utilities +│ │ ├── session.ts # Session management +│ │ └── utils.ts # General utilities (cn) +│ ├── providers/ +│ │ └── index.tsx # Context providers +│ ├── routes/ # TanStack file-based routes +│ │ ├── __root.tsx +│ │ ├── _layout.tsx +│ │ └── _layout/ +│ │ ├── _authenticated.tsx +│ │ ├── login.tsx +│ │ └── _authenticated/ +│ ├── types/ +│ │ └── index.ts +│ ├── utils/ +│ │ ├── orpc.ts # oRPC client setup +│ │ └── stream.ts # Streaming utilities +│ └── integrations/ +│ └── tanstack-query/ +│ └── devtools.tsx +├── rsbuild.config.ts # Build configuration └── package.json ``` @@ -29,35 +62,47 @@ ui/ - [ ] Props are properly typed with TypeScript - [ ] No unused imports or variables - [ ] Proper error boundaries and loading states +- [ ] Files follow **kebab-case** naming convention ### 2. Route Structure - [ ] Routes follow TanStack Router conventions - [ ] Protected routes use `_authenticated` layout +- [ ] Admin routes use `_authenticated/_admin` layout - [ ] Route components are properly exported ### 3. API Integration - [ ] Uses oRPC client from `utils/orpc.ts` - [ ] TanStack Query for data fetching +- [ ] Streaming via `utils/stream.ts` - [ ] Proper error handling with toast notifications ### 4. Styling - [ ] Semantic color tokens (not hardcoded colors) - [ ] Responsive design patterns - [ ] shadcn/ui components used consistently +- [ ] Tailwind CSS v4 conventions -### 5. Performance +### 5. Module Federation +- [ ] Exports defined in `rsbuild.config.ts` +- [ ] Shared dependencies configured correctly +- [ ] SSR build separate from client build + +### 6. Performance - [ ] Proper use of `useMemo` and `useCallback` - [ ] No unnecessary re-renders - [ ] Lazy loading for heavy components ## Key Files to Check -1. `src/routes/_layout/_authenticated/chat/index.tsx` - Main chat page -2. `src/components/chat/ChatPage.tsx` - Chat page component -3. `src/components/chat/ChatInput.tsx` - Chat input component -4. `src/components/chat/ChatMessage.tsx` - Message display +1. `src/router.tsx` - Client router setup +2. `src/router.server.tsx` - SSR router +3. `src/components/index.ts` - Public exports +4. `src/components/chat/chat-page.tsx` - Chat feature 5. `src/utils/orpc.ts` - API client setup 6. `src/utils/stream.ts` - Streaming utilities +7. `src/lib/auth-client.ts` - Auth client +8. `src/routes/_layout/_authenticated.tsx` - Auth guard +9. `rsbuild.config.ts` - Build configuration ## Output Format diff --git a/host/.env.example b/.env.example similarity index 65% rename from host/.env.example rename to .env.example index 61b593b..1b6ffce 100644 --- a/host/.env.example +++ b/.env.example @@ -1,13 +1,17 @@ -# Better Auth BETTER_AUTH_SECRET= -BETTER_AUTH_URL=http://localhost:3001 -# CORS -CORS_ORIGIN=http://localhost:3001,http://localhost:3002 +# Host Database +HOST_DATABASE_URL=file:./database.db +HOST_DATABASE_AUTH_TOKEN= # for Turso + +# API Plugin Database (path relative to host/) +API_DATABASE_URL=file:../api/api.db +API_DATABASE_AUTH_TOKEN= # for Turso # Host Database HOST_DATABASE_URL=file:./database.db HOST_DATABASE_AUTH_TOKEN= # for Turso + # API Plugin Database (path relative to host/) API_DATABASE_URL=file:../api/api.db API_DATABASE_AUTH_TOKEN= # for Turso diff --git a/.gitignore b/.gitignore index 7920b4a..61f2c83 100644 --- a/.gitignore +++ b/.gitignore @@ -292,9 +292,11 @@ fabric.properties # near .near/data +.bos # db /**/*.db .turbo **/*.sqlite + diff --git a/README.md b/README.md index e8fb3fe..32dfaa2 100644 --- a/README.md +++ b/README.md @@ -13,23 +13,24 @@ Built with React, Hono.js, oRPC, Better-Auth, Module Federation, and NEAR AI Clo git clone https://github.com/NEARBuilders/cyborg.git && cd cyborg bun install -# 2. Create environment files -cp host/.env.example host/.env -cp api/.env.example api/.env +# 2. Create environment file +cp .env.example .env -# 3. Initialize database -bun db:migrate +# 3. Initialize (runs database migrations) +bun init # 4. Start development server bun dev ``` -Visit [http://localhost:3001](http://localhost:3001) to see the application. +> **Note:** You may see some warnings during startup - this is normal and the application will still function correctly. + +Visit [http://localhost:3000](http://localhost:3000) to see the application. ### Enable AI Chat 1. Get an API key from [cloud.near.ai](https://cloud.near.ai) -2. Add to `api/.env`: `NEAR_AI_API_KEY=your_key_here` +2. Add to `.env`: `NEAR_AI_API_KEY=your_key_here` 3. Restart with `bun dev` ## Documentation @@ -102,23 +103,39 @@ All runtime configuration lives in `bos.config.json`: ```json { "account": "example.near", + "create": { + "project": "yourorg/yourproject", + "ui": "yourorg/yourproject/ui", + "api": "yourorg/yourproject/api", + "host": "yourorg/yourproject/host" + }, "app": { "host": { "title": "App Title", - "development": "http://localhost:3001", - "production": "https://example.com" + "description": "App description", + "development": "http://localhost:3000", + "production": "https://example.com", + "secrets": ["HOST_DATABASE_URL", "HOST_DATABASE_AUTH_TOKEN", "BETTER_AUTH_SECRET", "BETTER_AUTH_URL"] }, "ui": { "name": "ui", "development": "http://localhost:3002", - "production": "https://cdn.example.com/ui/remoteEntry.js" + "production": "https://cdn.example.com/ui/remoteEntry.js", + "exposes": { + "App": "./App", + "components": "./components", + "providers": "./providers", + "types": "./types" + } }, "api": { "name": "api", "development": "http://localhost:3014", "production": "https://cdn.example.com/api/remoteEntry.js", - "variables": {}, - "secrets": ["API_DATABASE_URL", "API_DATABASE_AUTH_TOKEN"] + "variables": { + "NEAR_AI_MODEL": "deepseek-ai/DeepSeek-V3.1" + }, + "secrets": ["API_DATABASE_URL", "API_DATABASE_AUTH_TOKEN", "NEAR_AI_API_KEY", "NEAR_AI_BASE_URL"] } } } @@ -130,53 +147,21 @@ All runtime configuration lives in `bos.config.json`: - Update CDN URLs without code changes - Template injection for secrets -## Rate Limiting - -Built-in rate limiting protects against abuse: - -| Endpoint | Limit | Window | -| --------- | ------------- | -------- | -| Chat/AI | 20 requests | 1 minute | -| Key-Value | 100 requests | 1 minute | -| Auth | 100 requests | 1 minute | -| Global | 1000 requests | 1 minute | - -Rate limit headers included in responses: - -- `X-RateLimit-Limit`: Maximum requests allowed -- `X-RateLimit-Remaining`: Requests remaining -- `X-RateLimit-Reset`: Unix timestamp when window resets - ## Health Checks -Two health endpoints are available: +Health endpoint is available: -- `GET /health` - Basic liveness check (always returns 200 if server is running) -- `GET /health/ready` - Readiness check with dependency status - -Example readiness response: - -```json -{ - "status": "ready", - "checks": { - "database": true, - "ai": true - }, - "timestamp": "2025-01-17T12:00:00.000Z" -} -``` - -Use `/health/ready` for load balancer health checks. +- `GET /health` - Basic liveness check (returns "OK" if server is running) ## Available Scripts ```bash # Development -bun dev # All services (API: 3014, UI: 3002, Host: 3001) -bun dev:api # API plugin only +bun dev # All services (API: 3014, UI: 3002, Host: 3000) bun dev:ui # UI remote only +bun dev:api # API plugin only bun dev:host # Host server only +bun dev:proxy # Host with API proxied to production # Production bun build # Build all packages @@ -185,13 +170,14 @@ bun build:ui # Build UI remote → uploads to CDN bun build:host # Build host server # Database +bun init # Initialize database (runs migrations) bun db:migrate # Run migrations bun db:push # Push schema changes bun db:studio # Open Drizzle Studio +bun db:generate # Generate migrations # Testing -bun test # Run all tests -bun typecheck # Type checking +bun typecheck # Type checking all workspaces ``` ## Development Workflow @@ -218,10 +204,9 @@ This project evolved from the [every-plugin template](https://github.com/near-ev ### Authentication & Roles -- **Better-Auth** with admin plugin (`host/src/lib/auth.ts`) +- **Better-Auth** with admin plugin (`host/src/services/auth.ts`) - **User roles** - "user" (default) and "admin" - **Admin routes** - Protected via TanStack Router (`ui/src/routes/_layout/_authenticated/_admin.tsx`) -- **Role management** - Promote users via: `bun run promote-admin ` ### Database diff --git a/api/README.md b/api/README.md index 0feb48c..b7c54e8 100644 --- a/api/README.md +++ b/api/README.md @@ -1,19 +1,19 @@ # api -[every-plugin](https://github.com/near-everything/every-plugin) based API. +[every-plugin](https://github.com/near-everything/every-plugin) based API with NEAR AI Cloud integration. ## Plugin Architecture Built with **every-plugin** framework (Rspack + Module Federation): -``` +```bash ┌─────────────────────────────────────────────────────────┐ │ createPlugin() │ ├─────────────────────────────────────────────────────────┤ -│ variables: { ... } │ -│ secrets: { ... } │ +│ variables: { NEAR_AI_MODEL, NEAR_AI_BASE_URL } │ +│ secrets: { API_DATABASE_URL, NEAR_AI_API_KEY, ... } │ │ contract: oRPC route definitions │ -│ initialize(): Effect → services │ +│ initialize(): Effect → { db, agentService } │ │ createRouter(): handlers using services │ └─────────────────────────────────────────────────────────┘ ↓ @@ -21,45 +21,51 @@ Built with **every-plugin** framework (Rspack + Module Federation): │ Host Integration │ ├─────────────────────────────────────────────────────────┤ │ bos.config.json → plugin URL + secrets │ -│ runtime.ts → createPluginRuntime().usePlugin() │ -│ routers/index.ts → merge plugin.router into AppRouter │ +│ host/src/services/plugins.ts → loadPlugin() │ +│ host/src/services/router.ts → merge plugin router │ └─────────────────────────────────────────────────────────┘ ``` -**Plugin Structure:** - -- `contract.ts` - oRPC contract definition (routes, schemas) -- `index.ts` - Plugin initialization + router handlers -- `db/schema.ts` - Database schema (conversations, messages, KV store) -- `services/` - Business logic (agent service for AI chat) -- `db/migrations/` - Database migrations - -**Extending with more plugins:** +## Directory Structure -Each domain can be its own plugin with independent: - -- Contract definition -- Initialization logic -- Router handlers -- Database schema +``` +api/ +├── src/ +│ ├── contract.ts # oRPC contract definition +│ ├── index.ts # Plugin definition (createPlugin) +│ ├── db/ +│ │ ├── index.ts # Database connection layer +│ │ ├── schema.ts # Drizzle ORM schema +│ │ └── migrations/ # SQL migration files +│ └── services/ +│ ├── index.ts # Service exports +│ └── agent.ts # NEAR AI integration +├── plugin.dev.ts # Local dev configuration +├── drizzle.config.ts # Drizzle Kit config +└── package.json +``` ## Tech Stack - **Framework**: every-plugin + oRPC - **Effects**: Effect-TS for service composition - **Database**: SQLite (libsql) + Drizzle ORM +- **AI**: OpenAI SDK (NEAR AI Cloud compatible) ## Available Scripts -- `bun dev` - Start dev server -- `bun build` - Build plugin +- `bun dev` - Start dev server (port 3014) +- `bun build` - Build plugin (deploys to CDN) - `bun test` - Run tests +- `bun typecheck` - Type checking - `bun db:push` - Push schema to database +- `bun db:generate` - Generate migrations +- `bun db:migrate` - Run migrations - `bun db:studio` - Open Drizzle Studio ## Configuration -**Root config** (`bos.config.json`): +**bos.config.json**: ```json { @@ -67,9 +73,10 @@ Each domain can be its own plugin with independent: "api": { "name": "api", "development": "http://localhost:3014", - "production": "https://", + "production": "https://cdn.example.com/api", "variables": { - "NEAR_AI_MODEL": "deepseek-ai/DeepSeek-V3.1" + "NEAR_AI_MODEL": "deepseek-ai/DeepSeek-V3.1", + "NEAR_AI_BASE_URL": "https://cloud-api.near.ai/v1" }, "secrets": [ "API_DATABASE_URL", @@ -81,3 +88,22 @@ Each domain can be its own plugin with independent: } } ``` + +## API Endpoints + +| Route | Method | Description | +|-------|--------|-------------| +| `/api/ping` | GET | Health check | +| `/api/protected` | GET | Auth test endpoint | +| `/api/admin/stats` | GET | Admin statistics | +| `/api/kv/:key` | GET | Get key-value entry | +| `/api/kv` | POST | Set key-value entry | +| `/api/chat` | POST | Send chat message | +| `/api/chat/stream` | POST | Stream chat response | +| `/api/conversation/:id` | GET | Get conversation history | + +## Database Schema + +- **conversation** - Chat conversations per user +- **message** - Messages within conversations +- **kvStore** - Per-user key-value storage (composite key: `key + nearAccountId`) diff --git a/api/drizzle.config.ts b/api/drizzle.config.ts index 5cee85f..327cd25 100644 --- a/api/drizzle.config.ts +++ b/api/drizzle.config.ts @@ -1,11 +1,11 @@ -import { defineConfig } from "drizzle-kit"; +import { defineConfig } from 'drizzle-kit'; export default defineConfig({ - schema: "./src/db/schema.ts", - out: "./src/db/migrations", - dialect: "turso", + schema: './src/db/schema.ts', + out: './src/db/migrations', + dialect: 'turso', dbCredentials: { - url: process.env.API_DATABASE_URL || "file:./api.db", + url: process.env.API_DATABASE_URL || 'file:./database.db', authToken: process.env.API_DATABASE_AUTH_TOKEN, }, verbose: true, diff --git a/api/package.json b/api/package.json index 5b4493d..58a69db 100644 --- a/api/package.json +++ b/api/package.json @@ -9,27 +9,28 @@ } }, "peerDependencies": { - "typescript": "^5.9.3" + "typescript": "catalog:" }, "dependencies": { - "@libsql/client": "^0.15.15", - "drizzle-kit": "^0.31.8", - "drizzle-orm": "^0.45.1", + "@libsql/client": "catalog:", + "drizzle-kit": "catalog:", + "drizzle-orm": "catalog:", + "effect": "catalog:", "nanoid": "^5.1.6", - "near-kit": "^0.6.3", + "near-kit": "catalog:", "openai": "^6.16.0" }, "devDependencies": { - "@effect/language-service": "^0.41.1", - "@module-federation/node": "^2.7.27", - "@rspack/cli": "^1.7.2", - "@rspack/core": "^1.7.2", + "@effect/language-service": "^0.72.0", + "@module-federation/node": "^2.7.25", + "@rspack/cli": "^1.7.3", + "@rspack/core": "^1.7.3", + "@types/node": "catalog:", "dotenv": "^17.2.3", - "every-plugin": "^0.8.8", - "tsx": "^4.21.0", - "vite-tsconfig-paths": "^5.1.4", - "vitest": "^3.2.4", - "zephyr-rspack-plugin": "^0.1.4" + "every-plugin": "0.8.8", + "vite-tsconfig-paths": "^6.0.5", + "vitest": "catalog:", + "zephyr-rspack-plugin": "^0.1.2" }, "scripts": { "build": "rspack build", @@ -41,7 +42,6 @@ "db:generate": "drizzle-kit generate", "db:migrate": "drizzle-kit migrate", "db:push": "drizzle-kit push", - "db:studio": "drizzle-kit studio", - "db:seed": "tsx src/seed.ts" + "db:studio": "drizzle-kit studio" } } diff --git a/api/vitest.config.ts b/api/vitest.config.ts index 5821b1f..37aa62c 100644 --- a/api/vitest.config.ts +++ b/api/vitest.config.ts @@ -8,6 +8,10 @@ export default defineConfig({ include: ['tests/**/*.test.ts'], exclude: ['node_modules/**', 'dist/**'], testTimeout: 30000, + fileParallelism: false, + sequence: { + hooks: 'stack', + }, }, plugins: [ tsconfigPaths({ diff --git a/bos.config.json b/bos.config.json index 88f1bfe..5391757 100644 --- a/bos.config.json +++ b/bos.config.json @@ -1,27 +1,41 @@ { - "account": "agency.near", + "account": "example.near", + "create": { + "project": "nearbuilders/cyborg", + "ui": "nearbuilders/cyborg/ui", + "api": "nearbuilders/cyborg/api", + "host": "nearbuilders/cyborg/host" + }, "app": { "host": { - "title": "agent", - "description": "template for building NEAR AI applications", - "development": "http://localhost:3001", - "production": "https://" + "title": "NEAR Agent", + "description": "Template for building NEAR AI applications", + "development": "http://localhost:3000", + "production": "https://elliot-braem-1785-host-cyborg-nearbuilders-70f3ffd9f-ze.zephyrcloud.app", + "secrets": [ + "HOST_DATABASE_URL", + "HOST_DATABASE_AUTH_TOKEN", + "BETTER_AUTH_SECRET", + "BETTER_AUTH_URL" + ], + "remote": "https://elliot-braem-1785-host-cyborg-nearbuilders-70f3ffd9f-ze.zephyrcloud.app" }, "ui": { "name": "ui", "development": "http://localhost:3002", - "production": "https://jlwaugh-73-ui-agency-multiversityai-5854da94d-ze.zephyrcloud.app", + "production": "https://elliot-braem-1786-ui-cyborg-nearbuilders-46d98f16b-ze.zephyrcloud.app", "exposes": { "App": "./App", "components": "./components", "providers": "./providers", "types": "./types" - } + }, + "ssr": "https://elliot-braem-1787-ui-cyborg-nearbuilders-3be8dde30-ze.zephyrcloud.app" }, "api": { "name": "api", "development": "http://localhost:3014", - "production": "https://jlwaugh-74-api-agency-multiversityai-18dcc54b0-ze.zephyrcloud.app", + "production": "https://elliot-braem-1788-api-cyborg-nearbuilders-ac0e7b73a-ze.zephyrcloud.app", "variables": { "NEAR_AI_MODEL": "deepseek-ai/DeepSeek-V3.1" }, diff --git a/bun.lock b/bun.lock index 2692ae3..1235ca9 100644 --- a/bun.lock +++ b/bun.lock @@ -5,83 +5,84 @@ "": { "name": "monorepo", "dependencies": { - "@tanstack/router-plugin": "^1.151.1", - "drizzle-kit": "^0.31.8", - "esbuild": "^0.27.2", - "hono": "^4.11.4", - "tsx": "^4.21.0", - "vite-tsconfig-paths": "^6.0.4", - "vitest": "^4.0.17", + "@types/bun": "^1.3.6", }, "devDependencies": { - "@types/node": "^25.0.9", - "turbo": "^2.7.5", + "@types/bun": "latest", + }, + "peerDependencies": { + "typescript": "^5", }, }, "api": { "name": "api", "version": "0.0.1", "dependencies": { - "@libsql/client": "^0.15.15", - "drizzle-kit": "^0.31.8", - "drizzle-orm": "^0.45.1", + "@libsql/client": "catalog:", + "drizzle-kit": "catalog:", + "drizzle-orm": "catalog:", + "effect": "catalog:", "nanoid": "^5.1.6", - "near-kit": "^0.6.3", + "near-kit": "catalog:", "openai": "^6.16.0", }, "devDependencies": { - "@effect/language-service": "^0.41.1", - "@module-federation/node": "^2.7.27", - "@rspack/cli": "^1.7.2", - "@rspack/core": "^1.7.2", + "@effect/language-service": "^0.72.0", + "@module-federation/node": "^2.7.25", + "@rspack/cli": "^1.7.3", + "@rspack/core": "^1.7.3", + "@types/node": "catalog:", "dotenv": "^17.2.3", - "every-plugin": "^0.8.8", - "tsx": "^4.21.0", - "vite-tsconfig-paths": "^5.1.4", - "vitest": "^3.2.4", - "zephyr-rspack-plugin": "^0.1.4", + "every-plugin": "0.8.8", + "vite-tsconfig-paths": "^6.0.5", + "vitest": "catalog:", + "zephyr-rspack-plugin": "^0.1.2", }, "peerDependencies": { - "typescript": "^5.9.3", + "typescript": "catalog:", }, }, "host": { "name": "host", + "version": "1.0.0", "dependencies": { "@hono/node-server": "^1.19.9", "@hot-labs/near-connect": "^0.8.2", - "@libsql/client": "^0.15.15", - "@module-federation/enhanced": "^0.21.6", - "@module-federation/node": "^2.7.27", - "@module-federation/rsbuild-plugin": "^0.21.6", - "@module-federation/runtime": "^0.21.6", - "@module-federation/runtime-core": "^0.21.6", + "@libsql/client": "^0.17.0", + "@module-federation/enhanced": "^0.23.0", + "@module-federation/node": "^2.7.28", + "@module-federation/runtime-core": "^0.23.0", "@orpc/openapi": "^1.13.4", "@orpc/server": "^1.13.4", "@orpc/zod": "^1.13.4", "@t3-oss/env-core": "^0.13.10", - "@tanstack/react-query": "^5.90.19", - "@tanstack/react-router": "^1.151.1", - "better-auth": "^1.4.14", - "better-near-auth": "^0.3.4", + "@tanstack/react-query": "catalog:", + "@tanstack/react-router": "catalog:", + "better-auth": "catalog:", + "better-near-auth": "catalog:", "dotenv": "^17.2.3", "drizzle-kit": "^0.31.8", "drizzle-orm": "^0.45.1", - "every-plugin": "^0.8.8", - "hono": "^4.11.4", - "near-kit": "^0.6.3", - "react": "^19.2.3", - "react-dom": "^19.2.3", + "effect": "catalog:", + "every-plugin": "catalog:", + "hono": "^4.11.6", + "near-kit": "catalog:", + "react": "^19.2.4", + "react-dom": "^19.2.4", }, "devDependencies": { + "@module-federation/rsbuild-plugin": "^0.23.0", "@rsbuild/core": "^1.7.2", "@rsbuild/plugin-react": "^1.4.3", - "@types/node": "^22.19.7", - "@types/react": "^19.2.8", + "@types/node": "^25.0.10", + "@types/react": "^19.2.9", "@types/react-dom": "^19.2.3", "tsx": "^4.21.0", - "typescript": "^5.9.3", - "zephyr-rsbuild-plugin": "^0.1.4", + "typescript": "catalog:", + "vite-tsconfig-paths": "^6.0.5", + "vitest": "^4.0.18", + "web-vitals": "^5.1.0", + "zephyr-rsbuild-plugin": "^0.1.8", }, }, "ui": { @@ -89,11 +90,8 @@ "version": "0.1.0", "dependencies": { "@hot-labs/near-connect": "^0.8.2", - "@orpc/client": "^1.13.4", + "@orpc/client": "^1.12.3", "@orpc/contract": "^1.13.4", - "@orpc/react-query": "^1.13.4", - "@orpc/server": "^1.13.4", - "@orpc/tanstack-query": "^1.13.4", "@radix-ui/react-aspect-ratio": "^1.1.8", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-checkbox": "^1.3.3", @@ -107,59 +105,76 @@ "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-tabs": "^1.1.13", - "@reactflow/background": "^11.3.14", - "@reactflow/controls": "^11.2.14", - "@reactflow/minimap": "^11.7.14", - "@tanstack/react-devtools": "^0.7.11", - "@tanstack/react-query": "^5.90.19", - "@tanstack/react-query-devtools": "^5.91.2", - "@tanstack/react-router": "^1.151.1", - "@tanstack/react-router-devtools": "^1.151.1", + "@tanstack/react-devtools": "^0.9.2", + "@tanstack/react-query": "catalog:", + "@tanstack/react-query-devtools": "^5.91.1", + "@tanstack/react-router": "catalog:", + "@tanstack/react-router-devtools": "^1.157.15", "@tanstack/react-table": "^8.21.3", - "better-auth": "^1.4.14", - "better-near-auth": "^0.3.4", + "better-auth": "catalog:", + "better-near-auth": "catalog:", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^0.544.0", - "near-kit": "^0.6.3", + "lucide-react": "^0.563.0", + "near-kit": "^0.10.0", "next-themes": "^0.4.6", "react": "^19.2.3", "react-dom": "^19.2.3", - "reactflow": "^11.11.4", "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tw-animate-css": "^1.4.0", - "zustand": "^5.0.10", + "zustand": "^5.0.9", }, "devDependencies": { - "@module-federation/enhanced": "^0.21.6", - "@module-federation/rsbuild-plugin": "^0.21.6", - "@rsbuild/core": "^1.7.2", - "@rsbuild/plugin-react": "^1.4.3", - "@tailwindcss/postcss": "^4.1.18", - "@tanstack/router-plugin": "^1.151.1", + "@module-federation/enhanced": "^0.23.0", + "@module-federation/node": "^2.7.26", + "@module-federation/rsbuild-plugin": "^0.23.0", + "@rsbuild/core": "^1.6.12", + "@rsbuild/plugin-react": "^1.4.2", + "@tailwindcss/postcss": "^4.1.17", + "@tanstack/router-plugin": "^1.157.15", "@testing-library/dom": "^10.4.1", - "@testing-library/react": "^16.3.1", - "@types/node": "^22.19.7", - "@types/react": "^19.2.8", - "@types/react-dom": "^19.2.3", - "jsdom": "^27.4.0", - "tailwindcss": "^4.1.18", - "typescript": "^5.9.3", - "vitest": "^3.2.4", - "web-vitals": "^5.1.0", - "zephyr-rsbuild-plugin": "^0.1.4", + "@testing-library/react": "^16.3.2", + "@types/node": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "every-plugin": "catalog:", + "jsdom": "^27.2.0", + "tailwindcss": "^4.1.17", + "typescript": "catalog:", + "vitest": "catalog:", + "zephyr-rsbuild-plugin": "^0.1.2", }, "peerDependencies": { - "@hot-labs/near-connect": "^0.8.2", + "@hot-labs/near-connect": "^0.8.x", "@tanstack/react-query": "^5.x", "@tanstack/react-router": "^1.x", - "near-kit": "^0.6.x", - "react": "^19.0.0", - "react-dom": "^19.0.0", + "near-kit": "^0.10.0", + "react": "^19.2.0", + "react-dom": "^19.2.0", }, }, }, + "catalog": { + "@hot-labs/near-connect": "^0.8.2", + "@libsql/client": "^0.17.0", + "@tanstack/react-query": "^5.90.11", + "@tanstack/react-router": "^1.153.2", + "@types/node": "^25.0.3", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "better-auth": "^1.4.15", + "better-near-auth": "^0.3.4", + "drizzle-kit": "^0.31.8", + "drizzle-orm": "^0.45.1", + "effect": "^3.19.15", + "every-plugin": "0.8.8", + "near-kit": "^0.10.0", + "react": "^19.2.3", + "react-dom": "^19.2.3", + "typescript": "^5.9.3", + "vitest": "^4.0.17", + }, "packages": { "@acemir/cssom": ["@acemir/cssom@0.9.31", "", {}, "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA=="], @@ -211,9 +226,9 @@ "@babel/types": ["@babel/types@7.28.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg=="], - "@better-auth/core": ["@better-auth/core@1.4.14", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.8", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-2zskCRAd+oaMwgf4joC/tJVuKl+BUB9OhH6nhDHJsoe69Xkxaf/XyRpKpU7Cjeth8SVAUNKaCInF21zBBrj6Ow=="], + "@better-auth/core": ["@better-auth/core@1.4.17", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.3.5" }, "peerDependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "better-call": "1.1.8", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" } }, "sha512-WSaEQDdUO6B1CzAmissN6j0lx9fM9lcslEYzlApB5UzFaBeAOHNUONTdglSyUs6/idiZBoRvt0t/qMXCgIU8ug=="], - "@better-auth/telemetry": ["@better-auth/telemetry@1.4.14", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.14" } }, "sha512-tIOvLT9vwPhbxT4rJIsHjxqcjlTX/eHHs0gXrKM90Dot71DqM9Cwse9C5IHQxJ1WLfPhc62laby4fbgcu5XSIA=="], + "@better-auth/telemetry": ["@better-auth/telemetry@1.4.17", "", { "dependencies": { "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.4.17" } }, "sha512-R1BC4e/bNjQbXu7lG6ubpgmsPj7IMqky5DvMlzAtnAJWJhh99pMh/n6w5gOHa0cqDZgEAuj75IPTxv+q3YiInA=="], "@better-auth/utils": ["@better-auth/utils@0.3.0", "", {}, "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw=="], @@ -227,7 +242,7 @@ "@csstools/css-parser-algorithms": ["@csstools/css-parser-algorithms@3.0.5", "", { "peerDependencies": { "@csstools/css-tokenizer": "^3.0.4" } }, "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ=="], - "@csstools/css-syntax-patches-for-csstree": ["@csstools/css-syntax-patches-for-csstree@1.0.25", "", {}, "sha512-g0Kw9W3vjx5BEBAF8c5Fm2NcB/Fs8jJXh85aXqwEXiL+tqtOut07TWgyaGzAAfTM+gKckrrncyeGEZPcaRgm2Q=="], + "@csstools/css-syntax-patches-for-csstree": ["@csstools/css-syntax-patches-for-csstree@1.0.26", "", {}, "sha512-6boXK0KkzT5u5xOgF6TKB+CLq9SOpEGmkZw0g5n9/7yg85wab3UzSxB8TxhLJ31L4SGJ6BCFRw/iftTha1CJXA=="], "@csstools/css-tokenizer": ["@csstools/css-tokenizer@3.0.4", "", {}, "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw=="], @@ -235,7 +250,7 @@ "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], - "@effect/language-service": ["@effect/language-service@0.41.1", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-BZaFkF1JdoTIJuzT7mNfUnfQG2MLxkQtn5b9y1z0BZUIcNfs5p7yR0ekYfTkPkt+TVD+9HE12VC1SsG5DReKww=="], + "@effect/language-service": ["@effect/language-service@0.72.0", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-MWkyTPCXSs5Q3OIBWR3q24SA+ipkdWW7EBJBt6EPUzlzZxjJLXtLBhXpMoCFheSEM0FTWOHT4BRLh5lufsmjVw=="], "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], @@ -247,59 +262,59 @@ "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "@exodus/bytes": ["@exodus/bytes@1.8.0", "", { "peerDependencies": { "@exodus/crypto": "^1.0.0-rc.4" }, "optionalPeers": ["@exodus/crypto"] }, "sha512-8JPn18Bcp8Uo1T82gR8lh2guEOa5KKU/IEKvvdp0sgmi7coPBWf1Doi1EXsGZb2ehc8ym/StJCjffYV+ne7sXQ=="], + "@exodus/bytes": ["@exodus/bytes@1.10.0", "", { "peerDependencies": { "@noble/hashes": "^1.8.0 || ^2.0.0" }, "optionalPeers": ["@noble/hashes"] }, "sha512-tf8YdcbirXdPnJ+Nd4UN1EXnz+IP2DI45YVEr3vvzcVTOyrApkmIB4zvOQVd3XPr7RXnfBtAx+PXImXOIU0Ajg=="], "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], @@ -329,10 +344,26 @@ "@jsonjoy.com/base64": ["@jsonjoy.com/base64@1.1.2", "", { "peerDependencies": { "tslib": "2" } }, "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA=="], - "@jsonjoy.com/buffers": ["@jsonjoy.com/buffers@1.2.1", "", { "peerDependencies": { "tslib": "2" } }, "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA=="], + "@jsonjoy.com/buffers": ["@jsonjoy.com/buffers@17.65.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-eBrIXd0/Ld3p9lpDDlMaMn6IEfWqtHMD+z61u0JrIiPzsV1r7m6xDZFRxJyvIFTEO+SWdYF9EiQbXZGd8BzPfA=="], "@jsonjoy.com/codegen": ["@jsonjoy.com/codegen@1.0.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g=="], + "@jsonjoy.com/fs-core": ["@jsonjoy.com/fs-core@4.56.10", "", { "dependencies": { "@jsonjoy.com/fs-node-builtins": "4.56.10", "@jsonjoy.com/fs-node-utils": "4.56.10", "thingies": "^2.5.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-PyAEA/3cnHhsGcdY+AmIU+ZPqTuZkDhCXQ2wkXypdLitSpd6d5Ivxhnq4wa2ETRWFVJGabYynBWxIijOswSmOw=="], + + "@jsonjoy.com/fs-fsa": ["@jsonjoy.com/fs-fsa@4.56.10", "", { "dependencies": { "@jsonjoy.com/fs-core": "4.56.10", "@jsonjoy.com/fs-node-builtins": "4.56.10", "@jsonjoy.com/fs-node-utils": "4.56.10", "thingies": "^2.5.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-/FVK63ysNzTPOnCCcPoPHt77TOmachdMS422txM4KhxddLdbW1fIbFMYH0AM0ow/YchCyS5gqEjKLNyv71j/5Q=="], + + "@jsonjoy.com/fs-node": ["@jsonjoy.com/fs-node@4.56.10", "", { "dependencies": { "@jsonjoy.com/fs-core": "4.56.10", "@jsonjoy.com/fs-node-builtins": "4.56.10", "@jsonjoy.com/fs-node-utils": "4.56.10", "@jsonjoy.com/fs-print": "4.56.10", "@jsonjoy.com/fs-snapshot": "4.56.10", "glob-to-regex.js": "^1.0.0", "thingies": "^2.5.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-7R4Gv3tkUdW3dXfXiOkqxkElxKNVdd8BDOWC0/dbERd0pXpPY+s2s1Mino+aTvkGrFPiY+mmVxA7zhskm4Ue4Q=="], + + "@jsonjoy.com/fs-node-builtins": ["@jsonjoy.com/fs-node-builtins@4.56.10", "", { "peerDependencies": { "tslib": "2" } }, "sha512-uUnKz8R0YJyKq5jXpZtkGV9U0pJDt8hmYcLRrPjROheIfjMXsz82kXMgAA/qNg0wrZ1Kv+hrg7azqEZx6XZCVw=="], + + "@jsonjoy.com/fs-node-to-fsa": ["@jsonjoy.com/fs-node-to-fsa@4.56.10", "", { "dependencies": { "@jsonjoy.com/fs-fsa": "4.56.10", "@jsonjoy.com/fs-node-builtins": "4.56.10", "@jsonjoy.com/fs-node-utils": "4.56.10" }, "peerDependencies": { "tslib": "2" } }, "sha512-oH+O6Y4lhn9NyG6aEoFwIBNKZeYy66toP5LJcDOMBgL99BKQMUf/zWJspdRhMdn/3hbzQsZ8EHHsuekbFLGUWw=="], + + "@jsonjoy.com/fs-node-utils": ["@jsonjoy.com/fs-node-utils@4.56.10", "", { "dependencies": { "@jsonjoy.com/fs-node-builtins": "4.56.10" }, "peerDependencies": { "tslib": "2" } }, "sha512-8EuPBgVI2aDPwFdaNQeNpHsyqPi3rr+85tMNG/lHvQLiVjzoZsvxA//Xd8aB567LUhy4QS03ptT+unkD/DIsNg=="], + + "@jsonjoy.com/fs-print": ["@jsonjoy.com/fs-print@4.56.10", "", { "dependencies": { "@jsonjoy.com/fs-node-utils": "4.56.10", "tree-dump": "^1.1.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-JW4fp5mAYepzFsSGrQ48ep8FXxpg4niFWHdF78wDrFGof7F3tKDJln72QFDEn/27M1yHd4v7sKHHVPh78aWcEw=="], + + "@jsonjoy.com/fs-snapshot": ["@jsonjoy.com/fs-snapshot@4.56.10", "", { "dependencies": { "@jsonjoy.com/buffers": "^17.65.0", "@jsonjoy.com/fs-node-utils": "4.56.10", "@jsonjoy.com/json-pack": "^17.65.0", "@jsonjoy.com/util": "^17.65.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-DkR6l5fj7+qj0+fVKm/OOXMGfDFCGXLfyHkORH3DF8hxkpDgIHbhf/DwncBMs2igu/ST7OEkexn1gIqoU6Y+9g=="], + "@jsonjoy.com/json-pack": ["@jsonjoy.com/json-pack@1.21.0", "", { "dependencies": { "@jsonjoy.com/base64": "^1.1.2", "@jsonjoy.com/buffers": "^1.2.0", "@jsonjoy.com/codegen": "^1.0.0", "@jsonjoy.com/json-pointer": "^1.0.2", "@jsonjoy.com/util": "^1.9.0", "hyperdyperid": "^1.2.0", "thingies": "^2.5.0", "tree-dump": "^1.1.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg=="], "@jsonjoy.com/json-pointer": ["@jsonjoy.com/json-pointer@1.0.2", "", { "dependencies": { "@jsonjoy.com/codegen": "^1.0.0", "@jsonjoy.com/util": "^1.9.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg=="], @@ -341,17 +372,15 @@ "@leichtgewicht/ip-codec": ["@leichtgewicht/ip-codec@2.0.5", "", {}, "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="], - "@libsql/client": ["@libsql/client@0.15.15", "", { "dependencies": { "@libsql/core": "^0.15.14", "@libsql/hrana-client": "^0.7.0", "js-base64": "^3.7.5", "libsql": "^0.5.22", "promise-limit": "^2.7.0" } }, "sha512-twC0hQxPNHPKfeOv3sNT6u2pturQjLcI+CnpTM0SjRpocEGgfiZ7DWKXLNnsothjyJmDqEsBQJ5ztq9Wlu470w=="], + "@libsql/client": ["@libsql/client@0.17.0", "", { "dependencies": { "@libsql/core": "^0.17.0", "@libsql/hrana-client": "^0.9.0", "js-base64": "^3.7.5", "libsql": "^0.5.22", "promise-limit": "^2.7.0" } }, "sha512-TLjSU9Otdpq0SpKHl1tD1Nc9MKhrsZbCFGot3EbCxRa8m1E5R1mMwoOjKMMM31IyF7fr+hPNHLpYfwbMKNusmg=="], - "@libsql/core": ["@libsql/core@0.15.15", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-C88Z6UKl+OyuKKPwz224riz02ih/zHYI3Ho/LAcVOgjsunIRZoBw7fjRfaH9oPMmSNeQfhGklSG2il1URoOIsA=="], + "@libsql/core": ["@libsql/core@0.17.0", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-hnZRnJHiS+nrhHKLGYPoJbc78FE903MSDrFJTbftxo+e52X+E0Y0fHOCVYsKWcg6XgB7BbJYUrz/xEkVTSaipw=="], "@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.22", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA=="], "@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.22", "", { "os": "darwin", "cpu": "x64" }, "sha512-ny2HYWt6lFSIdNFzUFIJ04uiW6finXfMNJ7wypkAD8Pqdm6nAByO+Fdqu8t7sD0sqJGeUCiOg480icjyQ2/8VA=="], - "@libsql/hrana-client": ["@libsql/hrana-client@0.7.0", "", { "dependencies": { "@libsql/isomorphic-fetch": "^0.3.1", "@libsql/isomorphic-ws": "^0.1.5", "js-base64": "^3.7.5", "node-fetch": "^3.3.2" } }, "sha512-OF8fFQSkbL7vJY9rfuegK1R7sPgQ6kFMkDamiEccNUvieQ+3urzfDFI616oPl8V7T9zRmnTkSjMOImYCAVRVuw=="], - - "@libsql/isomorphic-fetch": ["@libsql/isomorphic-fetch@0.3.1", "", {}, "sha512-6kK3SUK5Uu56zPq/Las620n5aS9xJq+jMBcNSOmjhNf/MUvdyji4vrMTqD7ptY7/4/CAVEAYDeotUz60LNQHtw=="], + "@libsql/hrana-client": ["@libsql/hrana-client@0.9.0", "", { "dependencies": { "@libsql/isomorphic-ws": "^0.1.5", "cross-fetch": "^4.0.0", "js-base64": "^3.7.5", "node-fetch": "^3.3.2" } }, "sha512-pxQ1986AuWfPX4oXzBvLwBnfgKDE5OMhAdR/5cZmRaB4Ygz5MecQybvwZupnRz341r2CtFmbk/BhSu7k2Lm+Jw=="], "@libsql/isomorphic-ws": ["@libsql/isomorphic-ws@0.1.5", "", { "dependencies": { "@types/ws": "^8.5.4", "ws": "^8.13.0" } }, "sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg=="], @@ -371,39 +400,39 @@ "@module-federation/automatic-vendor-federation": ["@module-federation/automatic-vendor-federation@1.2.1", "", { "dependencies": { "find-package-json": "^1.2.0" }, "peerDependencies": { "webpack": "^5.0.0-beta.16" } }, "sha512-73wxkXM7pbRZ6GGM90JP5IPTPvY3fvrhQyTVdMCUx85cQRWqnbzbibcsz3pkOMOeXyYAO4tXXsG13yNaEEGhJA=="], - "@module-federation/bridge-react-webpack-plugin": ["@module-federation/bridge-react-webpack-plugin@0.21.6", "", { "dependencies": { "@module-federation/sdk": "0.21.6", "@types/semver": "7.5.8", "semver": "7.6.3" } }, "sha512-lJMmdhD4VKVkeg8RHb+Jwe6Ou9zKVgjtb1inEURDG/sSS2ksdZA8pVKLYbRPRbdmjr193Y8gJfqFbI2dqoyc/g=="], + "@module-federation/bridge-react-webpack-plugin": ["@module-federation/bridge-react-webpack-plugin@0.23.0", "", { "dependencies": { "@module-federation/sdk": "0.23.0", "@types/semver": "7.5.8", "semver": "7.6.3" } }, "sha512-miZmMCl7OS1CH2tQbqijWK85qThg4TBDkI25Vx4G2du4ehg47mPKfeuft6/KWV/eJ7ZS4C534Oq/6lom1ncTOQ=="], - "@module-federation/cli": ["@module-federation/cli@0.21.6", "", { "dependencies": { "@module-federation/dts-plugin": "0.21.6", "@module-federation/sdk": "0.21.6", "chalk": "3.0.0", "commander": "11.1.0", "jiti": "2.4.2" }, "bin": { "mf": "bin/mf.js" } }, "sha512-qNojnlc8pTyKtK7ww3i/ujLrgWwgXqnD5DcDPsjADVIpu7STaoaVQ0G5GJ7WWS/ajXw6EyIAAGW/AMFh4XUxsQ=="], + "@module-federation/cli": ["@module-federation/cli@0.23.0", "", { "dependencies": { "@module-federation/dts-plugin": "0.23.0", "@module-federation/sdk": "0.23.0", "chalk": "3.0.0", "commander": "11.1.0", "jiti": "2.4.2" }, "bin": { "mf": "bin/mf.js" } }, "sha512-5OfdKUslS/kb6pycJPOtutMzIXSdmYcLoTSjhrWD7/68qFt2SGV7JD1l0RAhq3+fTuXryxctusTl4or2vCgBJw=="], - "@module-federation/data-prefetch": ["@module-federation/data-prefetch@0.21.6", "", { "dependencies": { "@module-federation/runtime": "0.21.6", "@module-federation/sdk": "0.21.6", "fs-extra": "9.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-8HD7ZhtWZ9vl6i3wA7M8cEeCRdtvxt09SbMTfqIPm+5eb/V4ijb8zGTYSRhNDb5RCB+BAixaPiZOWKXJ63/rVw=="], + "@module-federation/data-prefetch": ["@module-federation/data-prefetch@0.23.0", "", { "dependencies": { "@module-federation/runtime": "0.23.0", "@module-federation/sdk": "0.23.0", "fs-extra": "9.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-oTzdHo8xe0t1pA6KvTeEZAMcnvMRgE2rUwUrgFuGUqbQoTdndEt/A1X9eayJ5s/8ARDT5hoam4LcZYXpXPYbjg=="], - "@module-federation/dts-plugin": ["@module-federation/dts-plugin@0.21.6", "", { "dependencies": { "@module-federation/error-codes": "0.21.6", "@module-federation/managers": "0.21.6", "@module-federation/sdk": "0.21.6", "@module-federation/third-party-dts-extractor": "0.21.6", "adm-zip": "^0.5.10", "ansi-colors": "^4.1.3", "axios": "^1.12.0", "chalk": "3.0.0", "fs-extra": "9.1.0", "isomorphic-ws": "5.0.0", "koa": "3.0.3", "lodash.clonedeepwith": "4.5.0", "log4js": "6.9.1", "node-schedule": "2.1.1", "rambda": "^9.1.0", "ws": "8.18.0" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["vue-tsc"] }, "sha512-YIsDk8/7QZIWn0I1TAYULniMsbyi2LgKTi9OInzVmZkwMC6644x/ratTWBOUDbdY1Co+feNkoYeot1qIWv2L7w=="], + "@module-federation/dts-plugin": ["@module-federation/dts-plugin@0.23.0", "", { "dependencies": { "@module-federation/error-codes": "0.23.0", "@module-federation/managers": "0.23.0", "@module-federation/sdk": "0.23.0", "@module-federation/third-party-dts-extractor": "0.23.0", "adm-zip": "^0.5.10", "ansi-colors": "^4.1.3", "axios": "^1.12.0", "chalk": "3.0.0", "fs-extra": "9.1.0", "isomorphic-ws": "5.0.0", "koa": "3.0.3", "lodash.clonedeepwith": "4.5.0", "log4js": "6.9.1", "node-schedule": "2.1.1", "rambda": "^9.1.0", "ws": "8.18.0" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["vue-tsc"] }, "sha512-DIA2ht2SkGgdRWSVnxBGBS4XqeSiWIFPwyULZVZ0TTYr/47betlSVSRU6CTPokalrlryzMhEiqcvYJPCkOVP5w=="], - "@module-federation/enhanced": ["@module-federation/enhanced@0.21.6", "", { "dependencies": { "@module-federation/bridge-react-webpack-plugin": "0.21.6", "@module-federation/cli": "0.21.6", "@module-federation/data-prefetch": "0.21.6", "@module-federation/dts-plugin": "0.21.6", "@module-federation/error-codes": "0.21.6", "@module-federation/inject-external-runtime-core-plugin": "0.21.6", "@module-federation/managers": "0.21.6", "@module-federation/manifest": "0.21.6", "@module-federation/rspack": "0.21.6", "@module-federation/runtime-tools": "0.21.6", "@module-federation/sdk": "0.21.6", "btoa": "^1.2.1", "schema-utils": "^4.3.0", "upath": "2.0.1" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24", "webpack": "^5.0.0" }, "optionalPeers": ["typescript", "vue-tsc", "webpack"], "bin": { "mf": "bin/mf.js" } }, "sha512-8PFQxtmXc6ukBC4CqGIoc96M2Ly9WVwCPu4Ffvt+K/SB6rGbeFeZoYAwREV1zGNMJ5v5ly6+AHIEOBxNuSnzSg=="], + "@module-federation/enhanced": ["@module-federation/enhanced@0.23.0", "", { "dependencies": { "@module-federation/bridge-react-webpack-plugin": "0.23.0", "@module-federation/cli": "0.23.0", "@module-federation/data-prefetch": "0.23.0", "@module-federation/dts-plugin": "0.23.0", "@module-federation/error-codes": "0.23.0", "@module-federation/inject-external-runtime-core-plugin": "0.23.0", "@module-federation/managers": "0.23.0", "@module-federation/manifest": "0.23.0", "@module-federation/rspack": "0.23.0", "@module-federation/runtime-tools": "0.23.0", "@module-federation/sdk": "0.23.0", "btoa": "^1.2.1", "schema-utils": "^4.3.0", "upath": "2.0.1" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24", "webpack": "^5.0.0" }, "optionalPeers": ["typescript", "vue-tsc", "webpack"], "bin": { "mf": "bin/mf.js" } }, "sha512-GPfipQc0/rgwYp48hkru0cqvjtRKPVC/ZlUFptrbr2LTLM5mxW3ig1rggUAH2QSQoNvDuhY/kqG8u71MZROi3w=="], - "@module-federation/error-codes": ["@module-federation/error-codes@0.21.6", "", {}, "sha512-MLJUCQ05KnoVl8xd6xs9a5g2/8U+eWmVxg7xiBMeR0+7OjdWUbHwcwgVFatRIwSZvFgKHfWEiI7wsU1q1XbTRQ=="], + "@module-federation/error-codes": ["@module-federation/error-codes@0.23.0", "", {}, "sha512-CzcKOPKh/qB1wPkVBC0iEK/Cg4jRAS1DnZsTx7b3JUCIXDcIaRq/XkTdo+EQ0cAsF5Os9lQ0f50O9DC/uFC8eA=="], - "@module-federation/inject-external-runtime-core-plugin": ["@module-federation/inject-external-runtime-core-plugin@0.21.6", "", { "peerDependencies": { "@module-federation/runtime-tools": "0.21.6" } }, "sha512-DJQne7NQ988AVi3QB8byn12FkNb+C2lBeU1NRf8/WbL0gmHsr6kW8hiEJCm8LYaURwtsQqtsEV7i+8+51qjSmQ=="], + "@module-federation/inject-external-runtime-core-plugin": ["@module-federation/inject-external-runtime-core-plugin@0.23.0", "", { "peerDependencies": { "@module-federation/runtime-tools": "0.23.0" } }, "sha512-xxQrqtjbAUHY826ZtpvqgzANXhEibbloaiAOLZXhfIJd9wbYzK9m9zcHmIKOc5PQ5p1bBI5OJ+9XxXQmSBAtuw=="], - "@module-federation/managers": ["@module-federation/managers@0.21.6", "", { "dependencies": { "@module-federation/sdk": "0.21.6", "find-pkg": "2.0.0", "fs-extra": "9.1.0" } }, "sha512-BeV6m2/7kF5MDVz9JJI5T8h8lMosnXkH2bOxxFewcra7ZjvDOgQu7WIio0mgk5l1zjNPvnEVKhnhrenEdcCiWg=="], + "@module-federation/managers": ["@module-federation/managers@0.23.0", "", { "dependencies": { "@module-federation/sdk": "0.23.0", "find-pkg": "2.0.0", "fs-extra": "9.1.0" } }, "sha512-Stqu04QUiYBhWLW+0+EoZ4e5pFrrTxcEI4StJ7jOPtn2Ll6ImvGWk2KVNfbTjz0TRhIx5rl2wc+YPnYJ9tdVag=="], - "@module-federation/manifest": ["@module-federation/manifest@0.21.6", "", { "dependencies": { "@module-federation/dts-plugin": "0.21.6", "@module-federation/managers": "0.21.6", "@module-federation/sdk": "0.21.6", "chalk": "3.0.0", "find-pkg": "2.0.0" } }, "sha512-yg93+I1qjRs5B5hOSvjbjmIoI2z3th8/yst9sfwvx4UDOG1acsE3HHMyPN0GdoIGwplC/KAnU5NmUz4tREUTGQ=="], + "@module-federation/manifest": ["@module-federation/manifest@0.23.0", "", { "dependencies": { "@module-federation/dts-plugin": "0.23.0", "@module-federation/managers": "0.23.0", "@module-federation/sdk": "0.23.0", "chalk": "3.0.0", "find-pkg": "2.0.0" } }, "sha512-tzeq67oeTXM+ukzaC2qcaft5Gvu8T/hYiFGE/jopOOTVH8glTebKDg+xOABcN+EeP6UDmf6vDVq7dYmXTC6e/w=="], - "@module-federation/node": ["@module-federation/node@2.7.27", "", { "dependencies": { "@module-federation/enhanced": "0.22.1", "@module-federation/runtime": "0.22.1", "@module-federation/sdk": "0.22.1", "btoa": "1.2.1", "encoding": "^0.1.13", "node-fetch": "2.7.0" }, "peerDependencies": { "react": "^16||^17||^18||^19", "react-dom": "^16||^17||^18||^19", "webpack": "^5.40.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-Lv/H5g6vd7tADx/fCfhv0LyKVPWaJEquMdQaf0aTSnWgatg2ljPZrOoBdNMA68T5Ll+3kbUiDXuQb4ODmjdEgw=="], + "@module-federation/node": ["@module-federation/node@2.7.28", "", { "dependencies": { "@module-federation/enhanced": "0.23.0", "@module-federation/runtime": "0.23.0", "@module-federation/sdk": "0.23.0", "btoa": "1.2.1", "encoding": "^0.1.13", "node-fetch": "2.7.0" }, "peerDependencies": { "react": "^16||^17||^18||^19", "react-dom": "^16||^17||^18||^19", "webpack": "^5.40.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-AoYSak1bgUUs1COcbf330ONRqmNJ5pSSMLjeOVLyRjROCsoXwSnIiWVxSTi0MENHd3B6k+T0oFPQWi9nRKK3lQ=="], - "@module-federation/rsbuild-plugin": ["@module-federation/rsbuild-plugin@0.21.6", "", { "dependencies": { "@module-federation/enhanced": "0.21.6", "@module-federation/node": "2.7.25", "@module-federation/sdk": "0.21.6", "fs-extra": "11.3.0" }, "peerDependencies": { "@rsbuild/core": "^1.3.21" }, "optionalPeers": ["@rsbuild/core"] }, "sha512-Whbj8wy9p/YPea+yN0oW1PbPq3qYG9uZzPZ0UfNHswpZE7fpPUu/kGjmTosRpkMAWMraPH4bCh03y3Masz9eVQ=="], + "@module-federation/rsbuild-plugin": ["@module-federation/rsbuild-plugin@0.23.0", "", { "dependencies": { "@module-federation/enhanced": "0.23.0", "@module-federation/node": "2.7.28", "@module-federation/sdk": "0.23.0", "fs-extra": "11.3.0" }, "peerDependencies": { "@rsbuild/core": "^1.3.21" }, "optionalPeers": ["@rsbuild/core"] }, "sha512-Kwk/GoCVEd4u6RH6i4dj7na9gZmHZD4JPBoTwLVgo5zM9HuouIjSfOVBrcbJG4TgVZB4n4F+O02tbJpWxPY57w=="], - "@module-federation/rspack": ["@module-federation/rspack@0.21.6", "", { "dependencies": { "@module-federation/bridge-react-webpack-plugin": "0.21.6", "@module-federation/dts-plugin": "0.21.6", "@module-federation/inject-external-runtime-core-plugin": "0.21.6", "@module-federation/managers": "0.21.6", "@module-federation/manifest": "0.21.6", "@module-federation/runtime-tools": "0.21.6", "@module-federation/sdk": "0.21.6", "btoa": "1.2.1" }, "peerDependencies": { "@rspack/core": ">=0.7", "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["typescript", "vue-tsc"] }, "sha512-SB+z1P+Bqe3R6geZje9dp0xpspX6uash+zO77nodmUy8PTTBlkL7800Cq2FMLKUdoTZHJTBVXf0K6CqQWSlItg=="], + "@module-federation/rspack": ["@module-federation/rspack@0.23.0", "", { "dependencies": { "@module-federation/bridge-react-webpack-plugin": "0.23.0", "@module-federation/dts-plugin": "0.23.0", "@module-federation/inject-external-runtime-core-plugin": "0.23.0", "@module-federation/managers": "0.23.0", "@module-federation/manifest": "0.23.0", "@module-federation/runtime-tools": "0.23.0", "@module-federation/sdk": "0.23.0", "btoa": "1.2.1" }, "peerDependencies": { "@rspack/core": ">=0.7", "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["typescript", "vue-tsc"] }, "sha512-Le1ep9NTgEGpbYhFsko/HkHS3To/jpEQ0Wvkugxix7pxA8ynhJCpflD2y+iN8CCfGq+Y49dACAmqLvifPc5OfA=="], - "@module-federation/runtime": ["@module-federation/runtime@0.21.6", "", { "dependencies": { "@module-federation/error-codes": "0.21.6", "@module-federation/runtime-core": "0.21.6", "@module-federation/sdk": "0.21.6" } }, "sha512-+caXwaQqwTNh+CQqyb4mZmXq7iEemRDrTZQGD+zyeH454JAYnJ3s/3oDFizdH6245pk+NiqDyOOkHzzFQorKhQ=="], + "@module-federation/runtime": ["@module-federation/runtime@0.23.0", "", { "dependencies": { "@module-federation/error-codes": "0.23.0", "@module-federation/runtime-core": "0.23.0", "@module-federation/sdk": "0.23.0" } }, "sha512-ZHJcfM1O8RqYVrlIbhyeQ3S6gJW3mqHso3/QY7cKs1za+UvOgB8aTsDwq7Fv+aJZWSmtGzWa4zbSuxthyucw3g=="], - "@module-federation/runtime-core": ["@module-federation/runtime-core@0.21.6", "", { "dependencies": { "@module-federation/error-codes": "0.21.6", "@module-federation/sdk": "0.21.6" } }, "sha512-5Hd1Y5qp5lU/aTiK66lidMlM/4ji2gr3EXAtJdreJzkY+bKcI5+21GRcliZ4RAkICmvdxQU5PHPL71XmNc7Lsw=="], + "@module-federation/runtime-core": ["@module-federation/runtime-core@0.23.0", "", { "dependencies": { "@module-federation/error-codes": "0.23.0", "@module-federation/sdk": "0.23.0" } }, "sha512-+Orumtyg6Q2v19Gz15P3kDmRf4Q6KEpv8DggKWHdM8AX4xyVT8dMRJxdIxaVddbIYTd7aL7o2U3LLK6EjUe4UA=="], "@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.22.0", "", { "dependencies": { "@module-federation/runtime": "0.22.0", "@module-federation/webpack-bundler-runtime": "0.22.0" } }, "sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA=="], - "@module-federation/sdk": ["@module-federation/sdk@0.22.1", "", {}, "sha512-e+xcroeeZwb1lXK0tM6E7YmGr8lYHm3QzplWVM/q0Hs8SlvQMcM9Lv+JF6y9UQmhVSaMKW40PyPyqL0Y1rIeVw=="], + "@module-federation/sdk": ["@module-federation/sdk@0.23.0", "", {}, "sha512-1+DICHIF1z6yggtsZypmcn1gL35iitiSDXcsaqWynK4v5aw9MBRUS4zP3kG7eQDFTMmIo+rGbPN37AUsOq/RRQ=="], - "@module-federation/third-party-dts-extractor": ["@module-federation/third-party-dts-extractor@0.21.6", "", { "dependencies": { "find-pkg": "2.0.0", "fs-extra": "9.1.0", "resolve": "1.22.8" } }, "sha512-Il6x4hLsvCgZNk1DFwuMBNeoxD1BsZ5AW2BI/nUgu0k5FiAvfcz1OFawRFEHtaM/kVrCsymMOW7pCao90DaX3A=="], + "@module-federation/third-party-dts-extractor": ["@module-federation/third-party-dts-extractor@0.23.0", "", { "dependencies": { "find-pkg": "2.0.0", "fs-extra": "9.1.0", "resolve": "1.22.8" } }, "sha512-/oiLf6QQblhQKuHf89Wd475nUva+PWz5G01wxldy4lXaSTvz5XayCCBDek2SX8Gs4XnqATCm6IriAQ+ORzsgmQ=="], "@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.22.0", "", { "dependencies": { "@module-federation/runtime": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA=="], @@ -563,97 +592,85 @@ "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], - "@reactflow/background": ["@reactflow/background@11.3.14", "", { "dependencies": { "@reactflow/core": "11.11.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-Gewd7blEVT5Lh6jqrvOgd4G6Qk17eGKQfsDXgyRSqM+CTwDqRldG2LsWN4sNeno6sbqVIC2fZ+rAUBFA9ZEUDA=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.56.0", "", { "os": "android", "cpu": "arm" }, "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw=="], - "@reactflow/controls": ["@reactflow/controls@11.2.14", "", { "dependencies": { "@reactflow/core": "11.11.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-MiJp5VldFD7FrqaBNIrQ85dxChrG6ivuZ+dcFhPQUwOK3HfYgX2RHdBua+gx+40p5Vw5It3dVNp/my4Z3jF0dw=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.56.0", "", { "os": "android", "cpu": "arm64" }, "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q=="], - "@reactflow/core": ["@reactflow/core@11.11.4", "", { "dependencies": { "@types/d3": "^7.4.0", "@types/d3-drag": "^3.0.1", "@types/d3-selection": "^3.0.3", "@types/d3-zoom": "^3.0.1", "classcat": "^5.0.3", "d3-drag": "^3.0.0", "d3-selection": "^3.0.0", "d3-zoom": "^3.0.0", "zustand": "^4.4.1" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-H4vODklsjAq3AMq6Np4LE12i1I4Ta9PrDHuBR9GmL8uzTt2l2jh4CiQbEMpvMDcp7xi4be0hgXj+Ysodde/i7Q=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.56.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w=="], - "@reactflow/minimap": ["@reactflow/minimap@11.7.14", "", { "dependencies": { "@reactflow/core": "11.11.4", "@types/d3-selection": "^3.0.3", "@types/d3-zoom": "^3.0.1", "classcat": "^5.0.3", "d3-selection": "^3.0.0", "d3-zoom": "^3.0.0", "zustand": "^4.4.1" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-mpwLKKrEAofgFJdkhwR5UQ1JYWlcAAL/ZU/bctBkuNTT1yqV+y0buoNVImsRehVYhJwffSWeSHaBR5/GJjlCSQ=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.56.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g=="], - "@reactflow/node-resizer": ["@reactflow/node-resizer@2.2.14", "", { "dependencies": { "@reactflow/core": "11.11.4", "classcat": "^5.0.4", "d3-drag": "^3.0.0", "d3-selection": "^3.0.0", "zustand": "^4.4.1" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-fwqnks83jUlYr6OHcdFEedumWKChTHRGw/kbCxj0oqBd+ekfs+SIp4ddyNU0pdx96JIm5iNFS0oNrmEiJbbSaA=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.56.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ=="], - "@reactflow/node-toolbar": ["@reactflow/node-toolbar@1.3.14", "", { "dependencies": { "@reactflow/core": "11.11.4", "classcat": "^5.0.3", "zustand": "^4.4.1" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-rbynXQnH/xFNu4P9H+hVqlEUafDCkEoCy0Dg9mG22Sg+rY/0ck6KkrAQrYrTgXusd+cEJOMK0uOOFCK2/5rSGQ=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.56.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.55.1", "", { "os": "android", "cpu": "arm" }, "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.56.0", "", { "os": "linux", "cpu": "arm" }, "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.55.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.56.0", "", { "os": "linux", "cpu": "arm" }, "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.55.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.56.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.55.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.56.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.55.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.55.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw=="], + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.55.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.56.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.55.1", "", { "os": "linux", "cpu": "arm" }, "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg=="], + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.56.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.55.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.55.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.56.0", "", { "os": "linux", "cpu": "none" }, "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.56.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ=="], - "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.56.0", "", { "os": "linux", "cpu": "x64" }, "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.55.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.56.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA=="], - "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.55.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw=="], + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.56.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.56.0", "", { "os": "none", "cpu": "arm64" }, "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.55.1", "", { "os": "linux", "cpu": "none" }, "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.56.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.55.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.56.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.55.1", "", { "os": "linux", "cpu": "x64" }, "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg=="], + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.56.0", "", { "os": "win32", "cpu": "x64" }, "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.55.1", "", { "os": "linux", "cpu": "x64" }, "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w=="], - - "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.55.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg=="], - - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.55.1", "", { "os": "none", "cpu": "arm64" }, "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw=="], - - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.55.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g=="], - - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.55.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA=="], - - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg=="], - - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.55.1", "", { "os": "win32", "cpu": "x64" }, "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw=="], + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.56.0", "", { "os": "win32", "cpu": "x64" }, "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g=="], "@rsbuild/core": ["@rsbuild/core@1.7.2", "", { "dependencies": { "@rspack/core": "~1.7.1", "@rspack/lite-tapable": "~1.1.0", "@swc/helpers": "^0.5.18", "core-js": "~3.47.0", "jiti": "^2.6.1" }, "bin": { "rsbuild": "bin/rsbuild.js" } }, "sha512-VAFO6cM+cyg2ntxNW6g3tB2Jc5J5mpLjLluvm7VtW2uceNzyUlVv41o66Yp1t1ikxd3ljtqegViXem62JqzveA=="], "@rsbuild/plugin-react": ["@rsbuild/plugin-react@1.4.3", "", { "dependencies": { "@rspack/plugin-react-refresh": "^1.5.3", "react-refresh": "^0.18.0" }, "peerDependencies": { "@rsbuild/core": "^1.0.0 || ^2.0.0-0" } }, "sha512-Uf9FkKk2TqYDbsypXHgjdivPmEoYFvBTHJT5fPmjCf0Sc3lR2BHtlc0WMdZTCKUJ5jTxREygMs9LbnehX98L8g=="], - "@rspack/binding": ["@rspack/binding@1.7.2", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.7.2", "@rspack/binding-darwin-x64": "1.7.2", "@rspack/binding-linux-arm64-gnu": "1.7.2", "@rspack/binding-linux-arm64-musl": "1.7.2", "@rspack/binding-linux-x64-gnu": "1.7.2", "@rspack/binding-linux-x64-musl": "1.7.2", "@rspack/binding-wasm32-wasi": "1.7.2", "@rspack/binding-win32-arm64-msvc": "1.7.2", "@rspack/binding-win32-ia32-msvc": "1.7.2", "@rspack/binding-win32-x64-msvc": "1.7.2" } }, "sha512-bVssRQ39TgGA2RxKEbhUBKYRHln9sbBi0motHmqSU53aMnIkiLXjcj7tZC5dK7Okl2SrHM5KCYK9eG4UodDfdA=="], + "@rspack/binding": ["@rspack/binding@1.7.3", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.7.3", "@rspack/binding-darwin-x64": "1.7.3", "@rspack/binding-linux-arm64-gnu": "1.7.3", "@rspack/binding-linux-arm64-musl": "1.7.3", "@rspack/binding-linux-x64-gnu": "1.7.3", "@rspack/binding-linux-x64-musl": "1.7.3", "@rspack/binding-wasm32-wasi": "1.7.3", "@rspack/binding-win32-arm64-msvc": "1.7.3", "@rspack/binding-win32-ia32-msvc": "1.7.3", "@rspack/binding-win32-x64-msvc": "1.7.3" } }, "sha512-N943pbPktJPymiYZWZMZMVX/PeSU42cWGpBly82N+ibNCX/Oo4yKWE0v+TyIJm5JaUFhtF2NpvzRbrjg/6skqw=="], - "@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.7.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EsmfzNZnuEhVPMX5jWATCHT2UCCBh6iqq448xUMmASDiKVbIOhUTN1ONTV+aMERYl7BgMNJn0iTis6ot2GWKIg=="], + "@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.7.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sXha3xG2KDkXLVjrmnw5kGhBriH2gFd9KAyD2ZBq0sH/gNIvqEaWhAFoO1YtrKU6rCgiSBrs0frfGc6DEqWfTA=="], - "@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.7.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-lQLq0eNzFDzR31XD0H5oTG0y8cBoNF9hJ2gt1GgqMlYvaY+pMEeh7s4rTX1/M0c4gHpLudp86SsDuDJ53BwnaQ=="], + "@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.7.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-AUWMBgaPo7NgpW7arlw9laj9ZQxg7EjC5pnSCRH4BVPV+8egdoPCn5DZk05M25m73crKnGl8c7CrwTRNZeaPrw=="], - "@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.7.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-rtrsygVbDYw55ukdIk3NEwNQWkUemfRgeNOUvZ0k/6p7eP16020VPDvIqvcmyPtBhwFmz5vfo57GnBLisjM/kw=="], + "@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.7.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-SodEX3+1/GLz0LobX9cY1QdjJ1NftSEh4C2vGpr71iA3MS9HyXuw4giqSeRQ4DpCybqpdS/3RLjVqFQEfGpcnw=="], - "@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.7.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zhh6ycumTHI7V/VOOT6DolvBe5RFG+Np/e5hhlhjEFtskraO9rkWg8knE9Ssu6a6Qdj4nGscqOj9ENNpc6gb+A=="], + "@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.7.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-ydD2fNdEy+G7EYJ/a3FfdFZPfrLj/UnZocCNlZTTSHEhu+jURdQk0hwV11CvL+sjnKU5e/8IVMGUzhu3Gu8Ghg=="], - "@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.7.2", "", { "os": "linux", "cpu": "x64" }, "sha512-ON9hy6OTpBOmmFp/51RPa0r9bDbZ3wTTubT54V+yhHuB+eSrlXQIOQScUGCGoGgqp6sLTwKjv2yy7YLyzd1gCA=="], + "@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.7.3", "", { "os": "linux", "cpu": "x64" }, "sha512-adnDbUqafSAI6/N6vZ+iONSo1W3yUpnNtJqP3rVp7+YdABhUpbOhtaY37qpIJ3uFajXctYFyISPrb4MWl1M9Yg=="], - "@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.7.2", "", { "os": "linux", "cpu": "x64" }, "sha512-+2nnjwaSOStgLKtY5O7I3yfkwTkhiJLQ35CwQqWKRw+g1E4OFIKpXBfl34JDtrF/2DeS7sVVyLeuC25+43n9/A=="], + "@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.7.3", "", { "os": "linux", "cpu": "x64" }, "sha512-5jnjdODk5HCUFPN6rTaFukynDU4Fn9eCL+4TSp6mqo6YAnfnJEuzDjfetA8t3aQFcAs7WriQfNwvdcA4HvYtbA=="], - "@rspack/binding-wasm32-wasi": ["@rspack/binding-wasm32-wasi@1.7.2", "", { "dependencies": { "@napi-rs/wasm-runtime": "1.0.7" }, "cpu": "none" }, "sha512-TU/aLBpm9CTR/RTLF27WlvBKGyju6gpiNTRd3XRbX2JfY3UBNUQN/Ev+gQMVeOj55y9Fruzou42/w9ncTKA0Dw=="], + "@rspack/binding-wasm32-wasi": ["@rspack/binding-wasm32-wasi@1.7.3", "", { "dependencies": { "@napi-rs/wasm-runtime": "1.0.7" }, "cpu": "none" }, "sha512-WLQK0ksUzMkVeGoHAMIxenmeEU5tMvFDK36Aip7VRj7T6vZTcAwvbMwc38QrIAvlG7dqWoxgPQi35ba1igNNDw=="], - "@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.7.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-RReQN3AUu46XUZnOy5L/vSj5J+tcl/bzSnGQ2KetZ7dUOjGCC6c0Ki3EiklVM5OC1Agytz0Rz7cJqHJ+HaQbsA=="], + "@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.7.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-RAetPeY45g2NW6fID46VTV7mwY4Lqyw/flLbvCG28yrVOSkekw1KMCr1k335O3VNeqD+5dZDi1n+mwiAx/KMmA=="], - "@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.7.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-EytrfT2sfUCnRMtXfSNv7AR65DWuY3dX/Bsn1TTin7CC6+RFEAP9nzHtCMISvFPp+c5bveok0/eY8j/f4LZ/Gg=="], + "@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.7.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-X3c1B609DxzW++FdWf7kkoXWwsC/DUEJ1N1qots4T0P2G2V+pDQfjdTRSC0YQ75toAvwZqpwGzToQJ9IwQ4Ayw=="], - "@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.7.2", "", { "os": "win32", "cpu": "x64" }, "sha512-zLFt6cr55fjbIy6HT1xS2yLVmtvRjyZ0TbcRum7Ipp+s23gyGHVYNRuDMj34AHnhbCcX/XrxDTzCc4ba6xtYTw=="], + "@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.7.3", "", { "os": "win32", "cpu": "x64" }, "sha512-f6AvZbJGIg+7NggHXv0+lyMzvIUfeCxcB5DNbo3H5AalIgwkoFpcBXLBqgMVIbqA0yNyP06eiK98rpzc9ulQQg=="], - "@rspack/cli": ["@rspack/cli@1.7.2", "", { "dependencies": { "@discoveryjs/json-ext": "^0.5.7", "@rspack/dev-server": "~1.1.5", "exit-hook": "^4.0.0", "webpack-bundle-analyzer": "4.10.2" }, "peerDependencies": { "@rspack/core": "^1.0.0-alpha || ^1.x" }, "bin": { "rspack": "bin/rspack.js" } }, "sha512-X0Z67n0qu2sDodpJticfV1PHRS6T4Pszwp6KwgVv75sMeaHP0hc3A79B/W2SN2mT7DRVp57Cd99MoNmM3OOgLQ=="], + "@rspack/cli": ["@rspack/cli@1.7.3", "", { "dependencies": { "@discoveryjs/json-ext": "^0.5.7", "@rspack/dev-server": "~1.1.5", "exit-hook": "^4.0.0", "webpack-bundle-analyzer": "4.10.2" }, "peerDependencies": { "@rspack/core": "^1.0.0-alpha || ^1.x" }, "bin": { "rspack": "bin/rspack.js" } }, "sha512-6fb+cd1RjCK3ByN8oq7dIXZWFkbI7+y7VGlIvt/Nl2roGnL3IzXhEbyQzmXv9X+/fZ/pEKHWEyH05Rnqs3+VUQ=="], - "@rspack/core": ["@rspack/core@1.7.2", "", { "dependencies": { "@module-federation/runtime-tools": "0.22.0", "@rspack/binding": "1.7.2", "@rspack/lite-tapable": "1.1.0" }, "peerDependencies": { "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@swc/helpers"] }, "sha512-Pm06phSQqbthbzl92KdnbXmwcnYRv3Ef86uE6hoADqVjsmt2WvJwNjpqgs0S6n+s9UL6QzxqaaAaKg5qeBT+3g=="], + "@rspack/core": ["@rspack/core@1.7.3", "", { "dependencies": { "@module-federation/runtime-tools": "0.22.0", "@rspack/binding": "1.7.3", "@rspack/lite-tapable": "1.1.0" }, "peerDependencies": { "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@swc/helpers"] }, "sha512-GUiTRTz6+gbfM2g3ixXqrvPSeHmyAFu/qHEZZjbYFeDtZhpy1gVaVAHiZfaaIIm+vRlNi7JmULWFZQFKwpQB9Q=="], "@rspack/dev-server": ["@rspack/dev-server@1.1.5", "", { "dependencies": { "chokidar": "^3.6.0", "http-proxy-middleware": "^2.0.9", "p-retry": "^6.2.0", "webpack-dev-server": "5.2.2", "ws": "^8.18.0" }, "peerDependencies": { "@rspack/core": "*" } }, "sha512-cwz0qc6iqqoJhyWqxP7ZqE2wyYNHkBMQUXxoQ0tNoZ4YNRkDyQ4HVJ/3oPSmMKbvJk/iJ16u7xZmwG6sK47q/A=="], @@ -715,55 +732,55 @@ "@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.18", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "postcss": "^8.4.41", "tailwindcss": "4.1.18" } }, "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g=="], - "@tanstack/devtools": ["@tanstack/devtools@0.7.0", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/keyboard": "^1.3.3", "@solid-primitives/resize-observer": "^2.1.3", "@tanstack/devtools-client": "0.0.3", "@tanstack/devtools-event-bus": "0.3.3", "@tanstack/devtools-ui": "0.4.4", "clsx": "^2.1.1", "goober": "^2.1.16", "solid-js": "^1.9.9" } }, "sha512-AlAoCqJhWLg9GBEaoV1g/j+X/WA1aJSWOsekxeuZpYeS2hdVuKAjj04KQLUMJhtLfNl2s2E+TCj7ZRtWyY3U4w=="], + "@tanstack/devtools": ["@tanstack/devtools@0.10.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/keyboard": "^1.3.3", "@solid-primitives/resize-observer": "^2.1.3", "@tanstack/devtools-client": "0.0.5", "@tanstack/devtools-event-bus": "0.4.0", "@tanstack/devtools-ui": "0.4.4", "clsx": "^2.1.1", "goober": "^2.1.16", "solid-js": "^1.9.9" } }, "sha512-M2HnKtaNf3Z8JDTNDq+X7/1gwOqSwTnCyC0GR+TYiRZM9mkY9GpvTqp6p6bx3DT8onu2URJiVxgHD9WK2e3MNQ=="], - "@tanstack/devtools-client": ["@tanstack/devtools-client@0.0.3", "", { "dependencies": { "@tanstack/devtools-event-client": "^0.3.3" } }, "sha512-kl0r6N5iIL3t9gGDRAv55VRM3UIyMKVH83esRGq7xBjYsRLe/BeCIN2HqrlJkObUXQMKhy7i8ejuGOn+bDqDBw=="], + "@tanstack/devtools-client": ["@tanstack/devtools-client@0.0.5", "", { "dependencies": { "@tanstack/devtools-event-client": "^0.4.0" } }, "sha512-hsNDE3iu4frt9cC2ppn1mNRnLKo2uc1/1hXAyY9z4UYb+o40M2clFAhiFoo4HngjfGJDV3x18KVVIq7W4Un+zA=="], - "@tanstack/devtools-event-bus": ["@tanstack/devtools-event-bus@0.3.3", "", { "dependencies": { "ws": "^8.18.3" } }, "sha512-lWl88uLAz7ZhwNdLH6A3tBOSEuBCrvnY9Fzr5JPdzJRFdM5ZFdyNWz1Bf5l/F3GU57VodrN0KCFi9OA26H5Kpg=="], + "@tanstack/devtools-event-bus": ["@tanstack/devtools-event-bus@0.4.0", "", { "dependencies": { "ws": "^8.18.3" } }, "sha512-1t+/csFuDzi+miDxAOh6Xv7VDE80gJEItkTcAZLjV5MRulbO/W8ocjHLI2Do/p2r2/FBU0eKCRTpdqvXaYoHpQ=="], - "@tanstack/devtools-event-client": ["@tanstack/devtools-event-client@0.3.5", "", {}, "sha512-RL1f5ZlfZMpghrCIdzl6mLOFLTuhqmPNblZgBaeKfdtk5rfbjykurv+VfYydOFXj0vxVIoA2d/zT7xfD7Ph8fw=="], + "@tanstack/devtools-event-client": ["@tanstack/devtools-event-client@0.4.0", "", {}, "sha512-RPfGuk2bDZgcu9bAJodvO2lnZeHuz4/71HjZ0bGb/SPg8+lyTA+RLSKQvo7fSmPSi8/vcH3aKQ8EM9ywf1olaw=="], "@tanstack/devtools-ui": ["@tanstack/devtools-ui@0.4.4", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "solid-js": "^1.9.9" } }, "sha512-5xHXFyX3nom0UaNfiOM92o6ziaHjGo3mcSGe2HD5Xs8dWRZNpdZ0Smd0B9ddEhy0oB+gXyMzZgUJb9DmrZV0Mg=="], - "@tanstack/history": ["@tanstack/history@1.151.1", "", {}, "sha512-Z/eymNBuUGHYIea7nNX3xR5feqx418ChlwWOKklVpCVzEQ5Q3kNTUw+WK4HYUKxF+1uXFN01Dbuhhl7SmW1LJA=="], + "@tanstack/history": ["@tanstack/history@1.154.14", "", {}, "sha512-xyIfof8eHBuub1CkBnbKNKQXeRZC4dClhmzePHVOEel4G7lk/dW+TQ16da7CFdeNLv6u6Owf5VoBQxoo6DFTSA=="], - "@tanstack/query-core": ["@tanstack/query-core@5.90.19", "", {}, "sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA=="], + "@tanstack/query-core": ["@tanstack/query-core@5.90.20", "", {}, "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg=="], "@tanstack/query-devtools": ["@tanstack/query-devtools@5.92.0", "", {}, "sha512-N8D27KH1vEpVacvZgJL27xC6yPFUy0Zkezn5gnB3L3gRCxlDeSuiya7fKge8Y91uMTnC8aSxBQhcK6ocY7alpQ=="], - "@tanstack/react-devtools": ["@tanstack/react-devtools@0.7.11", "", { "dependencies": { "@tanstack/devtools": "0.7.0" }, "peerDependencies": { "@types/react": ">=16.8", "@types/react-dom": ">=16.8", "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-a2Lmz8x+JoDrsU6f7uKRcyyY+k8mA/n5mb9h7XJ3Fz/y3+sPV9t7vAW1s5lyNkQyyDt6V1Oim99faLthoJSxMw=="], + "@tanstack/react-devtools": ["@tanstack/react-devtools@0.9.2", "", { "dependencies": { "@tanstack/devtools": "0.10.3" }, "peerDependencies": { "@types/react": ">=16.8", "@types/react-dom": ">=16.8", "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-JNXvBO3jgq16GzTVm7p65n5zHNfMhnqF6Bm7CawjoqZrjEakxbM6Yvy63aKSIpbrdf+Wun2Xn8P0qD+vp56e1g=="], - "@tanstack/react-query": ["@tanstack/react-query@5.90.19", "", { "dependencies": { "@tanstack/query-core": "5.90.19" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ=="], + "@tanstack/react-query": ["@tanstack/react-query@5.90.20", "", { "dependencies": { "@tanstack/query-core": "5.90.20" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-vXBxa+qeyveVO7OA0jX1z+DeyCA4JKnThKv411jd5SORpBKgkcVnYKCiBgECvADvniBX7tobwBmg01qq9JmMJw=="], "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.91.2", "", { "dependencies": { "@tanstack/query-devtools": "5.92.0" }, "peerDependencies": { "@tanstack/react-query": "^5.90.14", "react": "^18 || ^19" } }, "sha512-ZJ1503ay5fFeEYFUdo7LMNFzZryi6B0Cacrgr2h1JRkvikK1khgIq6Nq2EcblqEdIlgB/r7XDW8f8DQ89RuUgg=="], - "@tanstack/react-router": ["@tanstack/react-router@1.151.1", "", { "dependencies": { "@tanstack/history": "1.151.1", "@tanstack/react-store": "^0.8.0", "@tanstack/router-core": "1.151.1", "isbot": "^5.1.22", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-343gO0W5HrYH4TEhZIvnjqbrLHHfIk0/OE0+fWgWh/Ke0dVTMOuEc1EAIgEpMqZgnsma+4gqIroqjivYd9rR2A=="], + "@tanstack/react-router": ["@tanstack/react-router@1.157.15", "", { "dependencies": { "@tanstack/history": "1.154.14", "@tanstack/react-store": "^0.8.0", "@tanstack/router-core": "1.157.15", "isbot": "^5.1.22", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-dVHX3Ann1rxLkXCrB9ctNKveGOrkmlKMo5fDIaaPCqqkDN/aC1gZ9O93i0OQVPUNekpkdXijmpHkxw12WqMTRQ=="], - "@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.151.1", "", { "dependencies": { "@tanstack/router-devtools-core": "1.151.1" }, "peerDependencies": { "@tanstack/react-router": "^1.151.1", "@tanstack/router-core": "^1.151.1", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["@tanstack/router-core"] }, "sha512-JoRtzzuUw9LaCq2Rv9QjPgCaMU54Go0638qmhCvZLYwWrBjOwvuGq9KhrOJEhJOi9vViqw8HiGFRPoEHEGe7pA=="], + "@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.157.15", "", { "dependencies": { "@tanstack/router-devtools-core": "1.157.15" }, "peerDependencies": { "@tanstack/react-router": "^1.157.15", "@tanstack/router-core": "^1.157.15", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["@tanstack/router-core"] }, "sha512-WNxsQaoVz1MDINKbWJ7xGYg0xyG9UAnRq7cYNFypDFyX6gqfiQUTxpFMVZfaw1sv+/fI/6E+hd7WChu1rrfBqQ=="], "@tanstack/react-store": ["@tanstack/react-store@0.8.0", "", { "dependencies": { "@tanstack/store": "0.8.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-1vG9beLIuB7q69skxK9r5xiLN3ztzIPfSQSs0GfeqWGO2tGIyInZx0x1COhpx97RKaONSoAb8C3dxacWksm1ow=="], "@tanstack/react-table": ["@tanstack/react-table@8.21.3", "", { "dependencies": { "@tanstack/table-core": "8.21.3" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww=="], - "@tanstack/router-core": ["@tanstack/router-core@1.151.1", "", { "dependencies": { "@tanstack/history": "1.151.1", "@tanstack/store": "^0.8.0", "cookie-es": "^2.0.0", "seroval": "^1.4.1", "seroval-plugins": "^1.4.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-RNH/jkxqPhCCEMZ3LTGQXJGzQKMATAfHRT2oquFD9T4BqBW4IMeZoeptEPV4So8j3lK33tn0IDkyg6Jzyq0JcQ=="], + "@tanstack/router-core": ["@tanstack/router-core@1.157.15", "", { "dependencies": { "@tanstack/history": "1.154.14", "@tanstack/store": "^0.8.0", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-KaYz6s+wYcg92kRQ7HXlTJLhBaBXOYiiqRBv5tsRbKRIqqhWNyeGz5+NfDwaYFHg5XLSDs3DvN0elMtxcj4dTg=="], - "@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.151.1", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "tiny-invariant": "^1.3.3" }, "peerDependencies": { "@tanstack/router-core": "^1.151.1", "csstype": "^3.0.10" }, "optionalPeers": ["csstype"] }, "sha512-1tWGZ/0BFEDfJho7kQPysK4hkZVcf0bwu72ZytP9FH8l/yOCWifytxrEXbCGYEmNjluZrEnShN9nc9dWY09O+w=="], + "@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.157.15", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "tiny-invariant": "^1.3.3" }, "peerDependencies": { "@tanstack/router-core": "^1.157.15", "csstype": "^3.0.10" }, "optionalPeers": ["csstype"] }, "sha512-udqDYuJUtVfPmk/4yhtOZl1dYlze/rMqaj3v/jQRS8TeGqWYal48Q18hM3A5Bd2YqORvaAkOQsI7JWKYnvxCiQ=="], - "@tanstack/router-generator": ["@tanstack/router-generator@1.151.1", "", { "dependencies": { "@tanstack/router-core": "1.151.1", "@tanstack/router-utils": "1.143.11", "@tanstack/virtual-file-routes": "1.145.4", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-MB+UCsG9bsQfHqA3eDcW0ZjfYp1fkgboU4cs4k4zieSs4qqxL4rW2Bq0U1G8nV8UL7I6+sWecWGpV+ThbpHlqw=="], + "@tanstack/router-generator": ["@tanstack/router-generator@1.157.15", "", { "dependencies": { "@tanstack/router-core": "1.157.15", "@tanstack/router-utils": "1.154.7", "@tanstack/virtual-file-routes": "1.154.7", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-zGac6tyRFz/X86fk9/CAmS6z8lyZf4p9lhAqLBCKVkFiFPmU4eAJp1ODvs81EtV0uJdRL1/rb+uvgHLGUsmQ0g=="], - "@tanstack/router-plugin": ["@tanstack/router-plugin@1.151.1", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.151.1", "@tanstack/router-generator": "1.151.1", "@tanstack/router-utils": "1.143.11", "@tanstack/virtual-file-routes": "1.145.4", "babel-dead-code-elimination": "^1.0.11", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.151.1", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"] }, "sha512-AkWk2L5pCouWrVBGEY1rvuSIRIwbTxi7myQXoIZOJ6enR8w03qhJQpWWj5JX4mhipDQs2nOljIrnR68nPlWIxg=="], + "@tanstack/router-plugin": ["@tanstack/router-plugin@1.157.15", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.157.15", "@tanstack/router-generator": "1.157.15", "@tanstack/router-utils": "1.154.7", "@tanstack/virtual-file-routes": "1.154.7", "babel-dead-code-elimination": "^1.0.11", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.157.15", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"] }, "sha512-EpRYRb35//sVJ8GPBhthqfPt9HNhx1xAaejiQ8i4vkG37et6qaSGAO+Woq91WjnpmxMYs4+sNJpGioPuVLBBqQ=="], - "@tanstack/router-utils": ["@tanstack/router-utils@1.143.11", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "ansis": "^4.1.0", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-N24G4LpfyK8dOlnP8BvNdkuxg1xQljkyl6PcrdiPSA301pOjatRT1y8wuCCJZKVVD8gkd0MpCZ0VEjRMGILOtA=="], + "@tanstack/router-utils": ["@tanstack/router-utils@1.154.7", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "ansis": "^4.1.0", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-61bGx32tMKuEpVRseu2sh1KQe8CfB7793Mch/kyQt0EP3tD7X0sXmimCl3truRiDGUtI0CaSoQV1NPjAII1RBA=="], "@tanstack/store": ["@tanstack/store@0.8.0", "", {}, "sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ=="], "@tanstack/table-core": ["@tanstack/table-core@8.21.3", "", {}, "sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg=="], - "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.145.4", "", {}, "sha512-CI75JrfqSluhdGwLssgVeQBaCphgfkMQpi8MCY3UJX1hoGzXa8kHYJcUuIFMOLs1q7zqHy++EVVtMK03osR5wQ=="], + "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.154.7", "", {}, "sha512-cHHDnewHozgjpI+MIVp9tcib6lYEQK5MyUr0ChHpHFGBl8Xei55rohFK0I0ve/GKoHeioaK42Smd8OixPp6CTg=="], "@testing-library/dom": ["@testing-library/dom@10.4.1", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "picocolors": "1.1.1", "pretty-format": "^27.0.2" } }, "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg=="], - "@testing-library/react": ["@testing-library/react@16.3.1", "", { "dependencies": { "@babel/runtime": "^7.12.5" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw=="], + "@testing-library/react": ["@testing-library/react@16.3.2", "", { "dependencies": { "@babel/runtime": "^7.12.5" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g=="], "@toon-format/toon": ["@toon-format/toon@0.9.0", "", {}, "sha512-BaMhGh1+/z8ceDrF2xL9Drd42hijbUJlivm/1goPR26RgCYsqlMkHbg48hx9a5UjZC7oZqxWPJ6ju5qvALi6Ag=="], @@ -775,74 +792,14 @@ "@types/bonjour": ["@types/bonjour@3.5.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ=="], + "@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], + "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], "@types/connect": ["@types/connect@3.4.38", "", { "dependencies": { "@types/node": "*" } }, "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug=="], "@types/connect-history-api-fallback": ["@types/connect-history-api-fallback@1.5.4", "", { "dependencies": { "@types/express-serve-static-core": "*", "@types/node": "*" } }, "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw=="], - "@types/d3": ["@types/d3@7.4.3", "", { "dependencies": { "@types/d3-array": "*", "@types/d3-axis": "*", "@types/d3-brush": "*", "@types/d3-chord": "*", "@types/d3-color": "*", "@types/d3-contour": "*", "@types/d3-delaunay": "*", "@types/d3-dispatch": "*", "@types/d3-drag": "*", "@types/d3-dsv": "*", "@types/d3-ease": "*", "@types/d3-fetch": "*", "@types/d3-force": "*", "@types/d3-format": "*", "@types/d3-geo": "*", "@types/d3-hierarchy": "*", "@types/d3-interpolate": "*", "@types/d3-path": "*", "@types/d3-polygon": "*", "@types/d3-quadtree": "*", "@types/d3-random": "*", "@types/d3-scale": "*", "@types/d3-scale-chromatic": "*", "@types/d3-selection": "*", "@types/d3-shape": "*", "@types/d3-time": "*", "@types/d3-time-format": "*", "@types/d3-timer": "*", "@types/d3-transition": "*", "@types/d3-zoom": "*" } }, "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww=="], - - "@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="], - - "@types/d3-axis": ["@types/d3-axis@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw=="], - - "@types/d3-brush": ["@types/d3-brush@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A=="], - - "@types/d3-chord": ["@types/d3-chord@3.0.6", "", {}, "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg=="], - - "@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="], - - "@types/d3-contour": ["@types/d3-contour@3.0.6", "", { "dependencies": { "@types/d3-array": "*", "@types/geojson": "*" } }, "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg=="], - - "@types/d3-delaunay": ["@types/d3-delaunay@6.0.4", "", {}, "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw=="], - - "@types/d3-dispatch": ["@types/d3-dispatch@3.0.7", "", {}, "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA=="], - - "@types/d3-drag": ["@types/d3-drag@3.0.7", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ=="], - - "@types/d3-dsv": ["@types/d3-dsv@3.0.7", "", {}, "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g=="], - - "@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="], - - "@types/d3-fetch": ["@types/d3-fetch@3.0.7", "", { "dependencies": { "@types/d3-dsv": "*" } }, "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA=="], - - "@types/d3-force": ["@types/d3-force@3.0.10", "", {}, "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw=="], - - "@types/d3-format": ["@types/d3-format@3.0.4", "", {}, "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="], - - "@types/d3-geo": ["@types/d3-geo@3.1.0", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ=="], - - "@types/d3-hierarchy": ["@types/d3-hierarchy@3.1.7", "", {}, "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg=="], - - "@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="], - - "@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="], - - "@types/d3-polygon": ["@types/d3-polygon@3.0.2", "", {}, "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA=="], - - "@types/d3-quadtree": ["@types/d3-quadtree@3.0.6", "", {}, "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg=="], - - "@types/d3-random": ["@types/d3-random@3.0.3", "", {}, "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ=="], - - "@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="], - - "@types/d3-scale-chromatic": ["@types/d3-scale-chromatic@3.1.0", "", {}, "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ=="], - - "@types/d3-selection": ["@types/d3-selection@3.0.11", "", {}, "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="], - - "@types/d3-shape": ["@types/d3-shape@3.1.8", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w=="], - - "@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="], - - "@types/d3-time-format": ["@types/d3-time-format@4.0.3", "", {}, "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg=="], - - "@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="], - - "@types/d3-transition": ["@types/d3-transition@3.0.9", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg=="], - - "@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="], - "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], @@ -855,8 +812,6 @@ "@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.8", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA=="], - "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="], - "@types/http-errors": ["@types/http-errors@2.0.5", "", {}, "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="], "@types/http-proxy": ["@types/http-proxy@1.17.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw=="], @@ -865,7 +820,7 @@ "@types/mime": ["@types/mime@1.3.5", "", {}, "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="], - "@types/node": ["@types/node@25.0.9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw=="], + "@types/node": ["@types/node@25.0.10", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg=="], "@types/node-forge": ["@types/node-forge@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw=="], @@ -873,7 +828,7 @@ "@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="], - "@types/react": ["@types/react@19.2.8", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg=="], + "@types/react": ["@types/react@19.2.9", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA=="], "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], @@ -891,19 +846,19 @@ "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], - "@vitest/expect": ["@vitest/expect@4.0.17", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.17", "@vitest/utils": "4.0.17", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-mEoqP3RqhKlbmUmntNDDCJeTDavDR+fVYkSOw8qRwJFaW/0/5zA9zFeTrHqNtcmwh6j26yMmwx2PqUDPzt5ZAQ=="], + "@vitest/expect": ["@vitest/expect@4.0.18", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ=="], - "@vitest/mocker": ["@vitest/mocker@4.0.17", "", { "dependencies": { "@vitest/spy": "4.0.17", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ=="], + "@vitest/mocker": ["@vitest/mocker@4.0.18", "", { "dependencies": { "@vitest/spy": "4.0.18", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.0.17", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-Ah3VAYmjcEdHg6+MwFE17qyLqBHZ+ni2ScKCiW2XrlSBV4H3Z7vYfPfz7CWQ33gyu76oc0Ai36+kgLU3rfF4nw=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.0.18", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw=="], - "@vitest/runner": ["@vitest/runner@4.0.17", "", { "dependencies": { "@vitest/utils": "4.0.17", "pathe": "^2.0.3" } }, "sha512-JmuQyf8aMWoo/LmNFppdpkfRVHJcsgzkbCA+/Bk7VfNH7RE6Ut2qxegeyx2j3ojtJtKIbIGy3h+KxGfYfk28YQ=="], + "@vitest/runner": ["@vitest/runner@4.0.18", "", { "dependencies": { "@vitest/utils": "4.0.18", "pathe": "^2.0.3" } }, "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw=="], - "@vitest/snapshot": ["@vitest/snapshot@4.0.17", "", { "dependencies": { "@vitest/pretty-format": "4.0.17", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-npPelD7oyL+YQM2gbIYvlavlMVWUfNNGZPcu0aEUQXt7FXTuqhmgiYupPnAanhKvyP6Srs2pIbWo30K0RbDtRQ=="], + "@vitest/snapshot": ["@vitest/snapshot@4.0.18", "", { "dependencies": { "@vitest/pretty-format": "4.0.18", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA=="], - "@vitest/spy": ["@vitest/spy@4.0.17", "", {}, "sha512-I1bQo8QaP6tZlTomQNWKJE6ym4SHf3oLS7ceNjozxxgzavRAgZDc06T7kD8gb9bXKEgcLNt00Z+kZO6KaJ62Ew=="], + "@vitest/spy": ["@vitest/spy@4.0.18", "", {}, "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw=="], - "@vitest/utils": ["@vitest/utils@4.0.17", "", { "dependencies": { "@vitest/pretty-format": "4.0.17", "tinyrainbow": "^3.0.3" } }, "sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w=="], + "@vitest/utils": ["@vitest/utils@4.0.18", "", { "dependencies": { "@vitest/pretty-format": "4.0.18", "tinyrainbow": "^3.0.3" } }, "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA=="], "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], @@ -987,17 +942,17 @@ "at-least-node": ["at-least-node@1.0.0", "", {}, "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="], - "axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="], + "axios": ["axios@1.13.3", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-ERT8kdX7DZjtUm7IitEyV7InTHAF42iJuMArIiDIV5YtPanJkgw4hw5Dyg9fh0mihdWNn1GKaeIWErfe56UQ1g=="], "axios-retry": ["axios-retry@4.5.0", "", { "dependencies": { "is-retry-allowed": "^2.2.0" }, "peerDependencies": { "axios": "0.x || 1.x" } }, "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ=="], "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="], - "baseline-browser-mapping": ["baseline-browser-mapping@2.9.15", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.9.18", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA=="], "batch": ["batch@0.6.1", "", {}, "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw=="], - "better-auth": ["better-auth@1.4.14", "", { "dependencies": { "@better-auth/core": "1.4.14", "@better-auth/telemetry": "1.4.14", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.8", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.1.12" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start-server": "^1.0.0", "@tanstack/solid-start-server": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start-server", "@tanstack/solid-start-server", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-gDpOmWOilhnLIBuv/7/6HoaXLtCDR7iUEjkvYCunJhUWZng53kZ2jivxtekhYC0j4+VSG6AZTihPIaoKrlztlA=="], + "better-auth": ["better-auth@1.4.17", "", { "dependencies": { "@better-auth/core": "1.4.17", "@better-auth/telemetry": "1.4.17", "@better-auth/utils": "0.3.0", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.0.0", "@noble/hashes": "^2.0.0", "better-call": "1.1.8", "defu": "^6.1.4", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1", "zod": "^4.3.5" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-VmHGQyKsEahkEs37qguROKg/6ypYpNF13D7v/lkbO7w7Aivz0Bv2h+VyUkH4NzrGY0QBKXi1577mGhDCVwp0ew=="], "better-call": ["better-call@1.1.8", "", { "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", "rou3": "^0.7.10", "set-cookie-parser": "^2.7.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-XMQ2rs6FNXasGNfMjzbyroSwKwYbZ/T3IxruSS6U2MJRsSYh3wYtG3o6H00ZlKZ/C/UPOAD97tqgQJNsxyeTXw=="], @@ -1019,24 +974,22 @@ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + "bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], + "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], - "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], - "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], - "caniuse-lite": ["caniuse-lite@1.0.30001764", "", {}, "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g=="], + "caniuse-lite": ["caniuse-lite@1.0.30001766", "", {}, "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA=="], - "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], "chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="], - "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="], - "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], @@ -1047,8 +1000,6 @@ "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], - "classcat": ["classcat@5.0.5", "", {}, "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w=="], - "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], @@ -1087,33 +1038,17 @@ "cron-parser": ["cron-parser@4.9.0", "", { "dependencies": { "luxon": "^3.2.1" } }, "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q=="], + "cross-fetch": ["cross-fetch@4.1.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw=="], + "css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="], "cssstyle": ["cssstyle@5.3.7", "", { "dependencies": { "@asamuzakjp/css-color": "^4.1.1", "@csstools/css-syntax-patches-for-csstree": "^1.0.21", "css-tree": "^3.1.0", "lru-cache": "^11.2.4" } }, "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ=="], "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], - "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="], - - "d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="], - - "d3-drag": ["d3-drag@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" } }, "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg=="], - - "d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="], - - "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="], - - "d3-selection": ["d3-selection@3.0.0", "", {}, "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="], - - "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="], - - "d3-transition": ["d3-transition@3.0.1", "", { "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", "d3-ease": "1 - 3", "d3-interpolate": "1 - 3", "d3-timer": "1 - 3" }, "peerDependencies": { "d3-selection": "2 - 3" } }, "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="], - - "d3-zoom": ["d3-zoom@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "2 - 3", "d3-transition": "2 - 3" } }, "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="], - "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], - "data-urls": ["data-urls@6.0.0", "", { "dependencies": { "whatwg-mimetype": "^4.0.0", "whatwg-url": "^15.0.0" } }, "sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA=="], + "data-urls": ["data-urls@6.0.1", "", { "dependencies": { "whatwg-mimetype": "^5.0.0", "whatwg-url": "^15.1.0" } }, "sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ=="], "date-format": ["date-format@4.0.14", "", {}, "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg=="], @@ -1123,8 +1058,6 @@ "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="], - "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], - "deep-equal": ["deep-equal@1.0.1", "", {}, "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw=="], "default-browser": ["default-browser@5.4.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg=="], @@ -1169,9 +1102,9 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "effect": ["effect@3.19.14", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-3vwdq0zlvQOxXzXNKRIPKTqZNMyGCdaFUBfMPqpsyzZDre67kgC1EEHDV4EoQTovJ4w5fmJW756f86kkuz7WFA=="], + "effect": ["effect@3.19.15", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-vzMmgfZKLcojmUjBdlQx+uaKryO7yULlRxjpDnHdnvcp1NPHxJyoM6IOXBLlzz2I/uPtZpGKavt5hBv7IvGZkA=="], - "electron-to-chromium": ["electron-to-chromium@1.5.267", "", {}, "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw=="], + "electron-to-chromium": ["electron-to-chromium@1.5.279", "", {}, "sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg=="], "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], @@ -1193,7 +1126,7 @@ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], - "esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], + "esbuild": ["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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], @@ -1319,7 +1252,7 @@ "homedir-polyfill": ["homedir-polyfill@1.0.3", "", { "dependencies": { "parse-passwd": "^1.0.0" } }, "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA=="], - "hono": ["hono@4.11.4", "", {}, "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA=="], + "hono": ["hono@4.11.6", "", {}, "sha512-ofIiiHyl34SV6AuhE3YT2mhO5HRWokce+eUYE82TsP6z0/H3JeJcjVWEMSIAiw2QkjDOEpES/lYsg8eEbsLtdw=="], "host": ["host@workspace:host"], @@ -1389,7 +1322,7 @@ "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], - "isbot": ["isbot@5.1.32", "", {}, "sha512-VNfjM73zz2IBZmdShMfAUg10prm6t7HFUQmNAEOAVS4YH92ZrZcvkMcGX6cIgBJAzWDzPent/EeAtYEHNPNPBQ=="], + "isbot": ["isbot@5.1.34", "", {}, "sha512-aCMIBSKd/XPRYdiCQTLC8QHH4YT8B3JUADu+7COgYIZPvkeoMcUHMRjZLM9/7V8fCj+l7FSREc1lOPNjzogo/A=="], "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], @@ -1425,7 +1358,7 @@ "koa-compose": ["koa-compose@4.1.0", "", {}, "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="], - "kysely": ["kysely@0.28.9", "", {}, "sha512-3BeXMoiOhpOwu62CiVpO6lxfq4eS6KMYfQdMsN/2kUCRNuF2YiEr7u0HLHaQU+O4Xu8YXE3bHVkwaQ85i72EuA=="], + "kysely": ["kysely@0.28.10", "", {}, "sha512-ksNxfzIW77OcZ+QWSAPC7yDqUSaIVwkTWnTPNiIy//vifNbwsSgQ57OkkncHxxpcBHM3LRfLAZVEh7kjq5twVA=="], "launch-editor": ["launch-editor@2.12.0", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.3" } }, "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg=="], @@ -1463,11 +1396,9 @@ "long-timeout": ["long-timeout@0.1.1", "", {}, "sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w=="], - "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], - - "lru-cache": ["lru-cache@11.2.4", "", {}, "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg=="], + "lru-cache": ["lru-cache@11.2.5", "", {}, "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw=="], - "lucide-react": ["lucide-react@0.544.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw=="], + "lucide-react": ["lucide-react@0.563.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA=="], "luxon": ["luxon@3.7.2", "", {}, "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew=="], @@ -1481,7 +1412,7 @@ "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], - "memfs": ["memfs@4.53.0", "", { "dependencies": { "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", "thingies": "^2.5.0", "tree-dump": "^1.0.3", "tslib": "^2.0.0" } }, "sha512-TKFRsKjJA30iAc9ZeGH/77v5nLcNUD0GBOL/tAj4O63RPIKNxGDZ54ZyuQM4KjEKEj7gfer/Ta1xAzB+HrEnrA=="], + "memfs": ["memfs@4.56.10", "", { "dependencies": { "@jsonjoy.com/fs-core": "4.56.10", "@jsonjoy.com/fs-fsa": "4.56.10", "@jsonjoy.com/fs-node": "4.56.10", "@jsonjoy.com/fs-node-builtins": "4.56.10", "@jsonjoy.com/fs-node-to-fsa": "4.56.10", "@jsonjoy.com/fs-node-utils": "4.56.10", "@jsonjoy.com/fs-print": "4.56.10", "@jsonjoy.com/fs-snapshot": "4.56.10", "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", "thingies": "^2.5.0", "tree-dump": "^1.0.3", "tslib": "^2.0.0" } }, "sha512-eLvzyrwqLHnLYalJP7YZ3wBe79MXktMdfQbvMrVD80K+NhrIukCVBvgP30zTJYEEDh9hZ/ep9z0KOdD7FSHo7w=="], "merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="], @@ -1513,7 +1444,7 @@ "nanostores": ["nanostores@1.1.0", "", {}, "sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA=="], - "near-kit": ["near-kit@0.6.3", "", { "dependencies": { "@napi-rs/keyring": "^1.2.0", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "@scure/base": "^2.0.0", "@scure/bip32": "^2.0.1", "@scure/bip39": "^2.0.1", "@zorsh/zorsh": "^0.4.0", "tar": "^7.5.2", "zod": "^4.1.12" }, "peerDependencies": { "@hot-labs/near-connect": ">=0.6.0", "@near-wallet-selector/core": ">=8.0.0" }, "optionalPeers": ["@hot-labs/near-connect", "@near-wallet-selector/core"] }, "sha512-3OibK7+2iODvwb+E9Cualz9HsH+hKdh6Q6WwhhGSjrKKurOslkcCOA1Bz7EK5sU7p+SZItJ53rI+eyQ0wQteNg=="], + "near-kit": ["near-kit@0.10.0", "", { "dependencies": { "@napi-rs/keyring": "^1.2.0", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "@scure/base": "^2.0.0", "@scure/bip32": "^2.0.1", "@scure/bip39": "^2.0.1", "@zorsh/zorsh": "^0.4.0", "tar": "^7.5.6", "zod": "^4.3.6" }, "peerDependencies": { "@hot-labs/near-connect": ">=0.6.0", "@near-wallet-selector/core": ">=8.0.0" }, "optionalPeers": ["@hot-labs/near-connect", "@near-wallet-selector/core"] }, "sha512-P/UEXT8gSbdZgeEFc7lMIOmUvkCwczmypDS5vU/7gUdcFG8S77ZymBzn8dkyxxLeVA2wFkwVpAPmzJEEX9m4ug=="], "near-sign-verify": ["near-sign-verify@0.4.5", "", { "dependencies": { "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "@scure/base": "^2.0.0", "@zorsh/zorsh": "^0.3.3" } }, "sha512-AOcPcKywejmKgCdQN4j77EyanK8AsIoZQzZnpKSk9wQMmxEi/97+GbDMb4p0TSAJEOuumfJRtJ5V5VYp+2qbKg=="], @@ -1575,15 +1506,13 @@ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], - "prettier": ["prettier@3.8.0", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA=="], + "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], "pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="], @@ -1615,9 +1544,9 @@ "raw-body": ["raw-body@2.5.3", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "unpipe": "~1.0.0" } }, "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA=="], - "react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="], + "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="], - "react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="], + "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="], "react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], @@ -1629,8 +1558,6 @@ "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], - "reactflow": ["reactflow@11.11.4", "", { "dependencies": { "@reactflow/background": "11.3.14", "@reactflow/controls": "11.2.14", "@reactflow/core": "11.11.4", "@reactflow/minimap": "11.7.14", "@reactflow/node-resizer": "2.2.14", "@reactflow/node-toolbar": "1.3.14" }, "peerDependencies": { "react": ">=17", "react-dom": ">=17" } }, "sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og=="], - "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], @@ -1651,7 +1578,7 @@ "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - "rollup": ["rollup@4.55.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.55.1", "@rollup/rollup-android-arm64": "4.55.1", "@rollup/rollup-darwin-arm64": "4.55.1", "@rollup/rollup-darwin-x64": "4.55.1", "@rollup/rollup-freebsd-arm64": "4.55.1", "@rollup/rollup-freebsd-x64": "4.55.1", "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", "@rollup/rollup-linux-arm-musleabihf": "4.55.1", "@rollup/rollup-linux-arm64-gnu": "4.55.1", "@rollup/rollup-linux-arm64-musl": "4.55.1", "@rollup/rollup-linux-loong64-gnu": "4.55.1", "@rollup/rollup-linux-loong64-musl": "4.55.1", "@rollup/rollup-linux-ppc64-gnu": "4.55.1", "@rollup/rollup-linux-ppc64-musl": "4.55.1", "@rollup/rollup-linux-riscv64-gnu": "4.55.1", "@rollup/rollup-linux-riscv64-musl": "4.55.1", "@rollup/rollup-linux-s390x-gnu": "4.55.1", "@rollup/rollup-linux-x64-gnu": "4.55.1", "@rollup/rollup-linux-x64-musl": "4.55.1", "@rollup/rollup-openbsd-x64": "4.55.1", "@rollup/rollup-openharmony-arm64": "4.55.1", "@rollup/rollup-win32-arm64-msvc": "4.55.1", "@rollup/rollup-win32-ia32-msvc": "4.55.1", "@rollup/rollup-win32-x64-gnu": "4.55.1", "@rollup/rollup-win32-x64-msvc": "4.55.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A=="], + "rollup": ["rollup@4.56.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.56.0", "@rollup/rollup-android-arm64": "4.56.0", "@rollup/rollup-darwin-arm64": "4.56.0", "@rollup/rollup-darwin-x64": "4.56.0", "@rollup/rollup-freebsd-arm64": "4.56.0", "@rollup/rollup-freebsd-x64": "4.56.0", "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", "@rollup/rollup-linux-arm-musleabihf": "4.56.0", "@rollup/rollup-linux-arm64-gnu": "4.56.0", "@rollup/rollup-linux-arm64-musl": "4.56.0", "@rollup/rollup-linux-loong64-gnu": "4.56.0", "@rollup/rollup-linux-loong64-musl": "4.56.0", "@rollup/rollup-linux-ppc64-gnu": "4.56.0", "@rollup/rollup-linux-ppc64-musl": "4.56.0", "@rollup/rollup-linux-riscv64-gnu": "4.56.0", "@rollup/rollup-linux-riscv64-musl": "4.56.0", "@rollup/rollup-linux-s390x-gnu": "4.56.0", "@rollup/rollup-linux-x64-gnu": "4.56.0", "@rollup/rollup-linux-x64-musl": "4.56.0", "@rollup/rollup-openbsd-x64": "4.56.0", "@rollup/rollup-openharmony-arm64": "4.56.0", "@rollup/rollup-win32-arm64-msvc": "4.56.0", "@rollup/rollup-win32-ia32-msvc": "4.56.0", "@rollup/rollup-win32-x64-gnu": "4.56.0", "@rollup/rollup-win32-x64-msvc": "4.56.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg=="], "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], @@ -1671,17 +1598,17 @@ "selfsigned": ["selfsigned@2.4.1", "", { "dependencies": { "@types/node-forge": "^1.3.0", "node-forge": "^1" } }, "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q=="], - "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], "serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="], - "seroval": ["seroval@1.4.2", "", {}, "sha512-N3HEHRCZYn3cQbsC4B5ldj9j+tHdf4JZoYPlcI4rRYu0Xy4qN8MQf1Z08EibzB0WpgRG5BGK08FTrmM66eSzKQ=="], + "seroval": ["seroval@1.5.0", "", {}, "sha512-OE4cvmJ1uSPrKorFIH9/w/Qwuvi/IMcGbv5RKgcJ/zjA/IohDLU6SVaxFN9FwajbP7nsX0dQqMDes1whk3y+yw=="], - "seroval-plugins": ["seroval-plugins@1.4.2", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-X7p4MEDTi+60o2sXZ4bnDBhgsUYDSkQEvzYZuJyFqWg9jcoPsHts5nrg5O956py2wyt28lUrBxk0M0/wU8URpA=="], + "seroval-plugins": ["seroval-plugins@1.5.0", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-EAHqADIQondwRZIdeW2I636zgsODzoBDwb3PT/+7TLDWyw1Dy/Xv7iGUIEXXav7usHDE9HVhOU61irI3EnyyHA=="], - "serve-index": ["serve-index@1.9.1", "", { "dependencies": { "accepts": "~1.3.4", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "~1.0.3", "http-errors": "~1.6.2", "mime-types": "~2.1.17", "parseurl": "~1.3.2" } }, "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw=="], + "serve-index": ["serve-index@1.9.2", "", { "dependencies": { "accepts": "~1.3.8", "batch": "0.6.1", "debug": "2.6.9", "escape-html": "~1.0.3", "http-errors": "~1.8.0", "mime-types": "~2.1.35", "parseurl": "~1.3.3" } }, "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ=="], "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], @@ -1707,7 +1634,7 @@ "sockjs": ["sockjs@0.3.24", "", { "dependencies": { "faye-websocket": "^0.11.3", "uuid": "^8.3.2", "websocket-driver": "^0.7.4" } }, "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ=="], - "solid-js": ["solid-js@1.9.10", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.3.0", "seroval-plugins": "~1.3.0" } }, "sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew=="], + "solid-js": ["solid-js@1.9.11", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-WEJtcc5mkh/BnHA6Yrg4whlF8g6QwpmXXRg4P2ztPmcKeHHlH4+djYecBLhSpecZY2RRECXYUwIc/C2r3yzQ4Q=="], "sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="], @@ -1735,8 +1662,6 @@ "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="], - "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], @@ -1751,7 +1676,7 @@ "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], - "tar": ["tar@7.5.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-ENg5JUHUm2rDD7IvKNFGzyElLXNjachNLp6RaGf4+JOgxXHkqA+gq81ZAMCUmtMtqBsoU62lcp6S27g1LCYGGQ=="], + "tar": ["tar@7.5.6", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA=="], "terser": ["terser@5.46.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg=="], @@ -1771,12 +1696,8 @@ "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], - "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], - "tinyrainbow": ["tinyrainbow@3.0.3", "", {}, "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q=="], - "tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="], - "tldts": ["tldts@7.0.19", "", { "dependencies": { "tldts-core": "^7.0.19" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA=="], "tldts-core": ["tldts-core@7.0.19", "", {}, "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A=="], @@ -1801,20 +1722,6 @@ "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="], - "turbo": ["turbo@2.7.5", "", { "optionalDependencies": { "turbo-darwin-64": "2.7.5", "turbo-darwin-arm64": "2.7.5", "turbo-linux-64": "2.7.5", "turbo-linux-arm64": "2.7.5", "turbo-windows-64": "2.7.5", "turbo-windows-arm64": "2.7.5" }, "bin": { "turbo": "bin/turbo" } }, "sha512-7Imdmg37joOloTnj+DPrab9hIaQcDdJ5RwSzcauo/wMOSAgO+A/I/8b3hsGGs6PWQz70m/jkPgdqWsfNKtwwDQ=="], - - "turbo-darwin-64": ["turbo-darwin-64@2.7.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-nN3wfLLj4OES/7awYyyM7fkU8U8sAFxsXau2bYJwAWi6T09jd87DgHD8N31zXaJ7LcpyppHWPRI2Ov9MuZEwnQ=="], - - "turbo-darwin-arm64": ["turbo-darwin-arm64@2.7.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-wCoDHMiTf3FgLAbZHDDx/unNNonSGhsF5AbbYODbxnpYyoKDpEYacUEPjZD895vDhNvYCH0Nnk24YsP4n/cD6g=="], - - "turbo-linux-64": ["turbo-linux-64@2.7.5", "", { "os": "linux", "cpu": "x64" }, "sha512-KKPvhOmJMmzWj/yjeO4LywkQ85vOJyhru7AZk/+c4B6OUh/odQ++SiIJBSbTG2lm1CuV5gV5vXZnf/2AMlu3Zg=="], - - "turbo-linux-arm64": ["turbo-linux-arm64@2.7.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-8PIva4L6BQhiPikUTds9lSFSHXVDAsEvV6QUlgwPsXrtXVQMVi6Sv9p+IxtlWQFvGkdYJUgX9GnK2rC030Xcmw=="], - - "turbo-windows-64": ["turbo-windows-64@2.7.5", "", { "os": "win32", "cpu": "x64" }, "sha512-rupskv/mkIUgQXzX/wUiK00mKMorQcK8yzhGFha/D5lm05FEnLx8dsip6rWzMcVpvh+4GUMA56PgtnOgpel2AA=="], - - "turbo-windows-arm64": ["turbo-windows-arm64@2.7.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-G377Gxn6P42RnCzfMyDvsqQV7j69kVHKlhz9J4RhtJOB5+DyY4yYh/w0oTIxZQ4JRMmhjwLu3w9zncMoQ6nNDw=="], - "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], "type-fest": ["type-fest@5.4.1", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-xygQcmneDyzsEuKZrFbRMne5HDqMs++aFzefrJTgEIKjQ3rekM+RPfFCVq2Gp1VIDqddoYeppCj4Pcb+RZW0GQ=="], @@ -1853,11 +1760,9 @@ "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], - "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="], + "vite-tsconfig-paths": ["vite-tsconfig-paths@6.0.5", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" } }, "sha512-f/WvY6ekHykUF1rWJUAbCU7iS/5QYDIugwpqJA+ttwKbxSbzNlqlE8vZSrsnxNQciUW+z6lvhlXMaEyZn9MSig=="], - "vite-tsconfig-paths": ["vite-tsconfig-paths@6.0.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3", "vite": "*" } }, "sha512-iIsEJ+ek5KqRTK17pmxtgIxXtqr3qDdE6OxrP9mVeGhVDNXRJTKN/l9oMbujTQNzMLe6XZ8qmpztfbkPu2TiFQ=="], - - "vitest": ["vitest@4.0.17", "", { "dependencies": { "@vitest/expect": "4.0.17", "@vitest/mocker": "4.0.17", "@vitest/pretty-format": "4.0.17", "@vitest/runner": "4.0.17", "@vitest/snapshot": "4.0.17", "@vitest/spy": "4.0.17", "@vitest/utils": "4.0.17", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.17", "@vitest/browser-preview": "4.0.17", "@vitest/browser-webdriverio": "4.0.17", "@vitest/ui": "4.0.17", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-FQMeF0DJdWY0iOnbv466n/0BudNdKj1l5jYgl5JVTwjSsZSlqyXFt/9+1sEyhR6CLowbZpV7O1sCHrzBhucKKg=="], + "vitest": ["vitest@4.0.18", "", { "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", "@vitest/pretty-format": "4.0.18", "@vitest/runner": "4.0.18", "@vitest/snapshot": "4.0.18", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.18", "@vitest/browser-preview": "4.0.18", "@vitest/browser-webdriverio": "4.0.18", "@vitest/ui": "4.0.18", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ=="], "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="], @@ -1909,75 +1814,57 @@ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - "zephyr-agent": ["zephyr-agent@0.1.4", "", { "dependencies": { "@toon-format/toon": "^0.9.0", "axios": "^1.12.0", "axios-retry": "^4.5.0", "debug": "^4.3.4", "eventsource": "^4.0.0", "git-url-parse": "^15.0.0", "is-ci": "^4.1.0", "jose": "^5.10.0", "node-persist": "^4.0.1", "open": "^10.1.0", "proper-lockfile": "^4.1.2", "tslib": "^2.8.1", "zephyr-edge-contract": "0.1.4" } }, "sha512-/etHBEPr0BiGMKA8uSwsrzE5ofOgkl4QcYNOKIT0Bv7KTK8nevMcK52PdR/c5PAEMxfw5ewuZA7/TxGPecj4+g=="], + "zephyr-agent": ["zephyr-agent@0.1.8", "", { "dependencies": { "@toon-format/toon": "^0.9.0", "axios": "^1.12.0", "axios-retry": "^4.5.0", "debug": "^4.3.4", "eventsource": "^4.0.0", "git-url-parse": "^15.0.0", "is-ci": "^4.1.0", "jose": "^5.10.0", "node-persist": "^4.0.1", "open": "^10.1.0", "proper-lockfile": "^4.1.2", "tslib": "^2.8.1", "zephyr-edge-contract": "0.1.8" }, "peerDependencies": { "https-proxy-agent": "^7.0.6" } }, "sha512-rEuzsN/wEKYTReBjIjqXWpo7DxzVcvprMSEGyiLyWXewWA7ECmYoK8/6pJjpIidgcuGrl9kFE0Y9aYe6lV1jWQ=="], - "zephyr-edge-contract": ["zephyr-edge-contract@0.1.4", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-g/4oz95ajrqAap1Sfc6Av6Vy+FVez4AMxEk5X5rJGShSRvGyCXc8W7uKjYFxMlx9nf3iZ94h+NcXv2qyOUewXA=="], + "zephyr-edge-contract": ["zephyr-edge-contract@0.1.8", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-raJQmMdJvlrxnlL2L5/6Mlrru3sw0WCcsHcNWukBoLHN6KbR73G3qyTiyCDOJHnP3pWHcKZrtUXtk9sFmKj/UQ=="], - "zephyr-rsbuild-plugin": ["zephyr-rsbuild-plugin@0.1.4", "", { "dependencies": { "zephyr-rspack-plugin": "0.1.4" }, "peerDependencies": { "@rsbuild/core": "^1.0.0" } }, "sha512-/YRkBIPw71Y21C+FpSCEKtD175ruGBFF9+BMvzNUePefqvVAonPESeqt3M4IdMuV+Q26dSKsShY5qAOXUHt8Wg=="], + "zephyr-rsbuild-plugin": ["zephyr-rsbuild-plugin@0.1.8", "", { "dependencies": { "zephyr-rspack-plugin": "0.1.8" }, "peerDependencies": { "@rsbuild/core": "^1.0.0" } }, "sha512-Orn7tcyT6GNYQ5Y+GidflJg/L7jHXeYTOfT403AkV1Qf3aQW0rZ28wHbxX4w1MAzY3SimobUWSCx9NQbyiZUjQ=="], - "zephyr-rspack-plugin": ["zephyr-rspack-plugin@0.1.4", "", { "dependencies": { "tslib": "^2.8.1", "zephyr-agent": "0.1.4", "zephyr-xpack-internal": "0.1.4" }, "peerDependencies": { "@rspack/core": "^1.0.0" } }, "sha512-rozsBpVIO7Tnd4J8TAcTk3k7h5SzOOeRX9rVVEelDzhwbJ22bTtFfLDxgzQ6vclAbpxdmW28jYrmgCKXoF/s0Q=="], + "zephyr-rspack-plugin": ["zephyr-rspack-plugin@0.1.8", "", { "dependencies": { "tslib": "^2.8.1", "zephyr-agent": "0.1.8", "zephyr-xpack-internal": "0.1.8" }, "peerDependencies": { "@rspack/core": "^1.0.0" } }, "sha512-DMO1Lo7VX449ZCURE6wTypIuLNaCUJNWOHE/Ny7at0L3hph17fazwRSn6M5DW9rcLqG8nsAPqYzJJCBg4K7wpA=="], - "zephyr-xpack-internal": ["zephyr-xpack-internal@0.1.4", "", { "dependencies": { "@module-federation/automatic-vendor-federation": "^1.2.1", "tslib": "^2.8.1", "zephyr-agent": "0.1.4", "zephyr-edge-contract": "0.1.4" } }, "sha512-qN6WtSey/hQM2vt9OPU2hK3VwgMBS2g2ykVCl+dvcz9rnbCg3HHRkHxERnE7u58C96nUBj4TnN3Fd05iirJItA=="], + "zephyr-xpack-internal": ["zephyr-xpack-internal@0.1.8", "", { "dependencies": { "@module-federation/automatic-vendor-federation": "^1.2.1", "tslib": "^2.8.1", "zephyr-agent": "0.1.8", "zephyr-edge-contract": "0.1.8" } }, "sha512-xdSsZr5rDebKkINsOp99WeIe1YhhU4VkAWkLxHk1onNnjMxDuBPzo37lmPUBYLLrImdlD91sNWFZxop1jnHDdg=="], - "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], "zustand": ["zustand@5.0.10", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-U1AiltS1O9hSy3rul+Ub82ut2fqIAefiSuwECWt6jlMVUGejvf+5omLcRBSzqbRagSM3hQZbtzdeRc6QVScXTg=="], + "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - "@better-auth/core/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], + "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@better-auth/core/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], - "@libsql/hrana-client/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], + "@jsonjoy.com/fs-snapshot/@jsonjoy.com/json-pack": ["@jsonjoy.com/json-pack@17.65.0", "", { "dependencies": { "@jsonjoy.com/base64": "17.65.0", "@jsonjoy.com/buffers": "17.65.0", "@jsonjoy.com/codegen": "17.65.0", "@jsonjoy.com/json-pointer": "17.65.0", "@jsonjoy.com/util": "17.65.0", "hyperdyperid": "^1.2.0", "thingies": "^2.5.0", "tree-dump": "^1.1.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-e0SG/6qUCnVhHa0rjDJHgnXnbsacooHVqQHxspjvlYQSkHm+66wkHw6Gql+3u/WxI/b1VsOdUi0M+fOtkgKGdQ=="], + + "@jsonjoy.com/fs-snapshot/@jsonjoy.com/util": ["@jsonjoy.com/util@17.65.0", "", { "dependencies": { "@jsonjoy.com/buffers": "17.65.0", "@jsonjoy.com/codegen": "17.65.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-cWiEHZccQORf96q2y6zU3wDeIVPeidmGqd9cNKJRYoVHTV0S1eHPy5JTbHpMnGfDvtvujQwQozOqgO9ABu6h0w=="], - "@module-federation/bridge-react-webpack-plugin/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], + "@jsonjoy.com/json-pack/@jsonjoy.com/buffers": ["@jsonjoy.com/buffers@1.2.1", "", { "peerDependencies": { "tslib": "2" } }, "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA=="], - "@module-federation/bridge-react-webpack-plugin/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "@jsonjoy.com/util/@jsonjoy.com/buffers": ["@jsonjoy.com/buffers@1.2.1", "", { "peerDependencies": { "tslib": "2" } }, "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA=="], - "@module-federation/cli/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], + "@libsql/hrana-client/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], "@module-federation/cli/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], "@module-federation/cli/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], - "@module-federation/data-prefetch/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], - "@module-federation/data-prefetch/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], - "@module-federation/dts-plugin/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], - "@module-federation/dts-plugin/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], "@module-federation/dts-plugin/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], - "@module-federation/enhanced/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.21.6", "", { "dependencies": { "@module-federation/runtime": "0.21.6", "@module-federation/webpack-bundler-runtime": "0.21.6" } }, "sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q=="], - - "@module-federation/enhanced/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], + "@module-federation/enhanced/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.23.0", "", { "dependencies": { "@module-federation/runtime": "0.23.0", "@module-federation/webpack-bundler-runtime": "0.23.0" } }, "sha512-TzUaU/X+mVHHilz8WApivSLjMZaBhydQrrMtrWCK4yUNfIjC/SmnGrdhmZE3qFxXezk4iit60KKS+xxZ+2udPg=="], - "@module-federation/inject-external-runtime-core-plugin/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.21.6", "", { "dependencies": { "@module-federation/runtime": "0.21.6", "@module-federation/webpack-bundler-runtime": "0.21.6" } }, "sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q=="], - - "@module-federation/managers/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], + "@module-federation/inject-external-runtime-core-plugin/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.23.0", "", { "dependencies": { "@module-federation/runtime": "0.23.0", "@module-federation/webpack-bundler-runtime": "0.23.0" } }, "sha512-TzUaU/X+mVHHilz8WApivSLjMZaBhydQrrMtrWCK4yUNfIjC/SmnGrdhmZE3qFxXezk4iit60KKS+xxZ+2udPg=="], "@module-federation/managers/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], - "@module-federation/manifest/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], - - "@module-federation/node/@module-federation/enhanced": ["@module-federation/enhanced@0.22.1", "", { "dependencies": { "@module-federation/bridge-react-webpack-plugin": "0.22.1", "@module-federation/cli": "0.22.1", "@module-federation/data-prefetch": "0.22.1", "@module-federation/dts-plugin": "0.22.1", "@module-federation/error-codes": "0.22.1", "@module-federation/inject-external-runtime-core-plugin": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/manifest": "0.22.1", "@module-federation/rspack": "0.22.1", "@module-federation/runtime-tools": "0.22.1", "@module-federation/sdk": "0.22.1", "btoa": "^1.2.1", "schema-utils": "^4.3.0", "upath": "2.0.1" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24", "webpack": "^5.0.0" }, "optionalPeers": ["typescript", "vue-tsc", "webpack"], "bin": { "mf": "bin/mf.js" } }, "sha512-0xUEmo1omhtSqFFtSec9tuUAwZ8rYUmqGngarBK8yaQXBa/g7NO7IZUN5rlRFzAvUh3Jl+Xyaq2qApTWEcpFwg=="], - - "@module-federation/node/@module-federation/runtime": ["@module-federation/runtime@0.22.1", "", { "dependencies": { "@module-federation/error-codes": "0.22.1", "@module-federation/runtime-core": "0.22.1", "@module-federation/sdk": "0.22.1" } }, "sha512-oFC5hHFSYDKquEO5+BA2pnEpFn6+Ky7eJyJlbo2KHBq7kVHbi+1i2b74H1mKjmF8Q66Q/PZQxF5GhcB2ehxVjg=="], - - "@module-federation/rsbuild-plugin/@module-federation/node": ["@module-federation/node@2.7.25", "", { "dependencies": { "@module-federation/enhanced": "0.21.6", "@module-federation/runtime": "0.21.6", "@module-federation/sdk": "0.21.6", "btoa": "1.2.1", "encoding": "^0.1.13", "node-fetch": "2.7.0" }, "peerDependencies": { "react": "^16||^17||^18||^19", "react-dom": "^16||^17||^18||^19", "webpack": "^5.40.0" }, "optionalPeers": ["react", "react-dom"] }, "sha512-/u4f+GYRZfHpSvdt5n40lMCS9Cmve7N3JlDreaFXz8xrWDNOp2wvMgiVGpndo5J4iQdtLjpavWStahGQ05B2cQ=="], - - "@module-federation/rsbuild-plugin/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], - - "@module-federation/rspack/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.21.6", "", { "dependencies": { "@module-federation/runtime": "0.21.6", "@module-federation/webpack-bundler-runtime": "0.21.6" } }, "sha512-fnP+ZOZTFeBGiTAnxve+axGmiYn2D60h86nUISXjXClK3LUY1krUfPgf6MaD4YDJ4i51OGXZWPekeMe16pkd8Q=="], - - "@module-federation/rspack/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], - - "@module-federation/runtime/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], - - "@module-federation/runtime-core/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], + "@module-federation/rspack/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.23.0", "", { "dependencies": { "@module-federation/runtime": "0.23.0", "@module-federation/webpack-bundler-runtime": "0.23.0" } }, "sha512-TzUaU/X+mVHHilz8WApivSLjMZaBhydQrrMtrWCK4yUNfIjC/SmnGrdhmZE3qFxXezk4iit60KKS+xxZ+2udPg=="], "@module-federation/runtime-tools/@module-federation/runtime": ["@module-federation/runtime@0.22.0", "", { "dependencies": { "@module-federation/error-codes": "0.22.0", "@module-federation/runtime-core": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA=="], @@ -2053,18 +1940,6 @@ "@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], - "@reactflow/background/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], - - "@reactflow/controls/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], - - "@reactflow/core/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], - - "@reactflow/minimap/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], - - "@reactflow/node-resizer/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], - - "@reactflow/node-toolbar/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], @@ -2077,23 +1952,19 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "@vitest/expect/chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], + "@tanstack/router-generator/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "@tanstack/router-plugin/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "api/vite-tsconfig-paths": ["vite-tsconfig-paths@5.1.4", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" }, "optionalPeers": ["vite"] }, "sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w=="], - - "api/vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="], - - "better-auth/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], - - "better-call/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], + "better-auth/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "better-near-auth/near-kit": ["near-kit@0.7.0", "", { "dependencies": { "@napi-rs/keyring": "^1.2.0", "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "@scure/base": "^2.0.0", "@scure/bip32": "^2.0.1", "@scure/bip39": "^2.0.1", "@zorsh/zorsh": "^0.4.0", "tar": "^7.5.2", "zod": "^4.1.12" }, "peerDependencies": { "@hot-labs/near-connect": ">=0.6.0", "@near-wallet-selector/core": ">=8.0.0" }, "optionalPeers": ["@hot-labs/near-connect", "@near-wallet-selector/core"] }, "sha512-mqE9i8QRq0DV/mky8RY+tO1kdx+yuQm3X5nuWiJAXqrfVe17SvDoMjyZpDWENSUqempiU22kBQX4OjGod4B96g=="], - "better-near-auth/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], + "better-near-auth/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "body-parser/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -2107,7 +1978,7 @@ "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "drizzle-kit/esbuild": ["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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "data-urls/whatwg-mimetype": ["whatwg-mimetype@5.0.0", "", {}, "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw=="], "esrecurse/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], @@ -2115,7 +1986,7 @@ "every-plugin/@module-federation/runtime-core": ["@module-federation/runtime-core@0.22.1", "", { "dependencies": { "@module-federation/error-codes": "0.22.1", "@module-federation/sdk": "0.22.1" } }, "sha512-bQNECpm3MMHWlCOt1I6b+kgA9vJPKbT4Zz2IvlVgx73Nig6jsXMzkVBybFQIDVLFmjb18Bx9wvOZkQn9iB9GGA=="], - "every-plugin/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], + "every-plugin/effect": ["effect@3.19.14", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" } }, "sha512-3vwdq0zlvQOxXzXNKRIPKTqZNMyGCdaFUBfMPqpsyzZDre67kgC1EEHDV4EoQTovJ4w5fmJW756f86kkuz7WFA=="], "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], @@ -2125,8 +1996,6 @@ "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "host/@types/node": ["@types/node@22.19.7", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw=="], - "hpack.js/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], "http-assert/http-errors": ["http-errors@1.8.1", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.1" } }, "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g=="], @@ -2139,7 +2008,7 @@ "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "near-kit/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], + "near-kit/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "near-sign-verify/@zorsh/zorsh": ["@zorsh/zorsh@0.3.3", "", {}, "sha512-Fu+iihpwuWPki/I93Bnocj4wmsDaOIfplzvbWGY1zvkGkvPq7y+npE2/Sub0bJJ0EB2C6fH/JvHkbH9B+9OIDQ=="], @@ -2161,25 +2030,19 @@ "serve-index/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "serve-index/http-errors": ["http-errors@1.6.3", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.3", "setprototypeof": "1.1.0", "statuses": ">= 1.4.0 < 2" } }, "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A=="], - - "solid-js/seroval": ["seroval@1.3.2", "", {}, "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ=="], - - "solid-js/seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="], + "serve-index/http-errors": ["http-errors@1.8.1", "", { "dependencies": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.1" } }, "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g=="], "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "streamroller/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], - "strip-literal/js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], - "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - "type-is/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], + "tsx/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], - "ui/@types/node": ["@types/node@22.19.7", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw=="], + "type-is/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], - "ui/vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="], + "vite/esbuild": ["esbuild@0.27.2", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.2", "@esbuild/android-arm": "0.27.2", "@esbuild/android-arm64": "0.27.2", "@esbuild/android-x64": "0.27.2", "@esbuild/darwin-arm64": "0.27.2", "@esbuild/darwin-x64": "0.27.2", "@esbuild/freebsd-arm64": "0.27.2", "@esbuild/freebsd-x64": "0.27.2", "@esbuild/linux-arm": "0.27.2", "@esbuild/linux-arm64": "0.27.2", "@esbuild/linux-ia32": "0.27.2", "@esbuild/linux-loong64": "0.27.2", "@esbuild/linux-mips64el": "0.27.2", "@esbuild/linux-ppc64": "0.27.2", "@esbuild/linux-riscv64": "0.27.2", "@esbuild/linux-s390x": "0.27.2", "@esbuild/linux-x64": "0.27.2", "@esbuild/netbsd-arm64": "0.27.2", "@esbuild/netbsd-x64": "0.27.2", "@esbuild/openbsd-arm64": "0.27.2", "@esbuild/openbsd-x64": "0.27.2", "@esbuild/openharmony-arm64": "0.27.2", "@esbuild/sunos-x64": "0.27.2", "@esbuild/win32-arm64": "0.27.2", "@esbuild/win32-ia32": "0.27.2", "@esbuild/win32-x64": "0.27.2" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw=="], "webpack/es-module-lexer": ["es-module-lexer@2.0.0", "", {}, "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw=="], @@ -2237,35 +2100,19 @@ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], - "@module-federation/enhanced/@module-federation/runtime-tools/@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.21.6", "", { "dependencies": { "@module-federation/runtime": "0.21.6", "@module-federation/sdk": "0.21.6" } }, "sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ=="], - - "@module-federation/inject-external-runtime-core-plugin/@module-federation/runtime-tools/@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.21.6", "", { "dependencies": { "@module-federation/runtime": "0.21.6", "@module-federation/sdk": "0.21.6" } }, "sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ=="], + "@jsonjoy.com/fs-snapshot/@jsonjoy.com/json-pack/@jsonjoy.com/base64": ["@jsonjoy.com/base64@17.65.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-Xrh7Fm/M0QAYpekSgmskdZYnFdSGnsxJ/tHaolA4bNwWdG9i65S8m83Meh7FOxyJyQAdo4d4J97NOomBLEfkDQ=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/bridge-react-webpack-plugin": ["@module-federation/bridge-react-webpack-plugin@0.22.1", "", { "dependencies": { "@module-federation/sdk": "0.22.1", "@types/semver": "7.5.8", "semver": "7.6.3" } }, "sha512-jKxU4GC5P/gVTJW1pOheHz+hk7yZiEmsyapNslxpD+ZVv2eN/OI6Om5mKJVtSa5tvrQMw/lVMAaX6UNkd34k0g=="], + "@jsonjoy.com/fs-snapshot/@jsonjoy.com/json-pack/@jsonjoy.com/codegen": ["@jsonjoy.com/codegen@17.65.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-7MXcRYe7n3BG+fo3jicvjB0+6ypl2Y/bQp79Sp7KeSiiCgLqw4Oled6chVv07/xLVTdo3qa1CD0VCCnPaw+RGA=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/cli": ["@module-federation/cli@0.22.1", "", { "dependencies": { "@module-federation/dts-plugin": "0.22.1", "@module-federation/sdk": "0.22.1", "chalk": "3.0.0", "commander": "11.1.0", "jiti": "2.4.2" }, "bin": { "mf": "bin/mf.js" } }, "sha512-/kw1yb/kWuYxmLhvz1mpKTdSAR/O18A/DJLa39Rmayq++DMbQHEwFrYr3BsVRdDcAaX2/R+CyHATvVFNn5EPSg=="], + "@jsonjoy.com/fs-snapshot/@jsonjoy.com/json-pack/@jsonjoy.com/json-pointer": ["@jsonjoy.com/json-pointer@17.65.0", "", { "dependencies": { "@jsonjoy.com/util": "17.65.0" }, "peerDependencies": { "tslib": "2" } }, "sha512-uhTe+XhlIZpWOxgPcnO+iSCDgKKBpwkDVTyYiXX9VayGV8HSFVJM67M6pUE71zdnXF1W0Da21AvnhlmdwYPpow=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/data-prefetch": ["@module-federation/data-prefetch@0.22.1", "", { "dependencies": { "@module-federation/runtime": "0.22.1", "@module-federation/sdk": "0.22.1", "fs-extra": "9.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-6jcZSFuUpU06IWPIaQeoB+HI2NI2BUmiV65oEYsjnwXtLMT8aFTGqN1XCZc0R2V7b5hBa1rSrk/FGCAXnwiFNQ=="], + "@jsonjoy.com/fs-snapshot/@jsonjoy.com/util/@jsonjoy.com/codegen": ["@jsonjoy.com/codegen@17.65.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-7MXcRYe7n3BG+fo3jicvjB0+6ypl2Y/bQp79Sp7KeSiiCgLqw4Oled6chVv07/xLVTdo3qa1CD0VCCnPaw+RGA=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/dts-plugin": ["@module-federation/dts-plugin@0.22.1", "", { "dependencies": { "@module-federation/error-codes": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/sdk": "0.22.1", "@module-federation/third-party-dts-extractor": "0.22.1", "adm-zip": "^0.5.10", "ansi-colors": "^4.1.3", "axios": "^1.12.0", "chalk": "3.0.0", "fs-extra": "9.1.0", "isomorphic-ws": "5.0.0", "koa": "3.0.3", "lodash.clonedeepwith": "4.5.0", "log4js": "6.9.1", "node-schedule": "2.1.1", "rambda": "^9.1.0", "ws": "8.18.0" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["vue-tsc"] }, "sha512-+zdQco9j1wbIhTAlLG5mZ7lSem9X9YnUzZNVSKqKF69Wg/rm220acMPSXJc7W+Nw6DuSp0m9elMA3I31DW7etg=="], + "@module-federation/enhanced/@module-federation/runtime-tools/@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.23.0", "", { "dependencies": { "@module-federation/runtime": "0.23.0", "@module-federation/sdk": "0.23.0" } }, "sha512-HnYVRiCg5nKpJ5LnUxT4iNzvay7fd/ZdubO/AWp4AqW7Y/cVaRFNNhg8cytuIZAha3R73BLYqia/a518K5dSwg=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/error-codes": ["@module-federation/error-codes@0.22.1", "", {}, "sha512-J3Gt4E2U9cSUoAUUrUSp7n1W8v3OT8B6UcVdt+p+fTKKkQ1yhDVWE7SOTgDCA7hiEaO9D6Gahwnn5IbxlH0pTQ=="], + "@module-federation/inject-external-runtime-core-plugin/@module-federation/runtime-tools/@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.23.0", "", { "dependencies": { "@module-federation/runtime": "0.23.0", "@module-federation/sdk": "0.23.0" } }, "sha512-HnYVRiCg5nKpJ5LnUxT4iNzvay7fd/ZdubO/AWp4AqW7Y/cVaRFNNhg8cytuIZAha3R73BLYqia/a518K5dSwg=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/inject-external-runtime-core-plugin": ["@module-federation/inject-external-runtime-core-plugin@0.22.1", "", { "peerDependencies": { "@module-federation/runtime-tools": "0.22.1" } }, "sha512-1+bkU/qbV87sR4QvsCQXtple/DIV1w1nuBKukBWI9UCz8M42ihpDljmdq794n/BC4D9kUk6z0nbA7hjgPcC2hg=="], - - "@module-federation/node/@module-federation/enhanced/@module-federation/managers": ["@module-federation/managers@0.22.1", "", { "dependencies": { "@module-federation/sdk": "0.22.1", "find-pkg": "2.0.0", "fs-extra": "9.1.0" } }, "sha512-9x557xoKjZrNwIp12wYGnizSdDfwEVgorlODVLyUcRe1pT0mx3cKtSxvuvkUle+CylgYLz6b4AFRNEZjYD4oFQ=="], - - "@module-federation/node/@module-federation/enhanced/@module-federation/manifest": ["@module-federation/manifest@0.22.1", "", { "dependencies": { "@module-federation/dts-plugin": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/sdk": "0.22.1", "chalk": "3.0.0", "find-pkg": "2.0.0" } }, "sha512-DQiV24e8xb63tEJQMdRvFx4BwsKtLmGkU+NtR6GrnT2OT0pj6AEva+zr8AkQLH9vDWtzGAr7FFxjJyZbKj2RZQ=="], - - "@module-federation/node/@module-federation/enhanced/@module-federation/rspack": ["@module-federation/rspack@0.22.1", "", { "dependencies": { "@module-federation/bridge-react-webpack-plugin": "0.22.1", "@module-federation/dts-plugin": "0.22.1", "@module-federation/inject-external-runtime-core-plugin": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/manifest": "0.22.1", "@module-federation/runtime-tools": "0.22.1", "@module-federation/sdk": "0.22.1", "btoa": "1.2.1" }, "peerDependencies": { "@rspack/core": ">=0.7", "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["typescript", "vue-tsc"] }, "sha512-dBOUpvtcls+VBCFwWBct6Z6xbxL/XCdeoADzX5CwbVt5ZB9H3qq2Qcj9shwO5M+4KJsfQDBSzkL7gqK7vNFlKA=="], - - "@module-federation/node/@module-federation/enhanced/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.22.1", "", { "dependencies": { "@module-federation/runtime": "0.22.1", "@module-federation/webpack-bundler-runtime": "0.22.1" } }, "sha512-GzqNytPPnQVejl78XFFvtLyj3XNgPu6rSac2EbQkCxV3uzAD3kFQ7SW0VuwXWbQeRTUgt/4Nl/o+BrJXy14lsw=="], - - "@module-federation/node/@module-federation/runtime/@module-federation/error-codes": ["@module-federation/error-codes@0.22.1", "", {}, "sha512-J3Gt4E2U9cSUoAUUrUSp7n1W8v3OT8B6UcVdt+p+fTKKkQ1yhDVWE7SOTgDCA7hiEaO9D6Gahwnn5IbxlH0pTQ=="], - - "@module-federation/node/@module-federation/runtime/@module-federation/runtime-core": ["@module-federation/runtime-core@0.22.1", "", { "dependencies": { "@module-federation/error-codes": "0.22.1", "@module-federation/sdk": "0.22.1" } }, "sha512-bQNECpm3MMHWlCOt1I6b+kgA9vJPKbT4Zz2IvlVgx73Nig6jsXMzkVBybFQIDVLFmjb18Bx9wvOZkQn9iB9GGA=="], - - "@module-federation/rspack/@module-federation/runtime-tools/@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.21.6", "", { "dependencies": { "@module-federation/runtime": "0.21.6", "@module-federation/sdk": "0.21.6" } }, "sha512-7zIp3LrcWbhGuFDTUMLJ2FJvcwjlddqhWGxi/MW3ur1a+HaO8v5tF2nl+vElKmbG1DFLU/52l3PElVcWf/YcsQ=="], + "@module-federation/rspack/@module-federation/runtime-tools/@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.23.0", "", { "dependencies": { "@module-federation/runtime": "0.23.0", "@module-federation/sdk": "0.23.0" } }, "sha512-HnYVRiCg5nKpJ5LnUxT4iNzvay7fd/ZdubO/AWp4AqW7Y/cVaRFNNhg8cytuIZAha3R73BLYqia/a518K5dSwg=="], "@module-federation/runtime-tools/@module-federation/runtime/@module-federation/error-codes": ["@module-federation/error-codes@0.22.0", "", {}, "sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug=="], @@ -2303,187 +2150,177 @@ "@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], - "api/vitest/@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], - - "api/vitest/@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="], - - "api/vitest/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], - - "api/vitest/@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="], - - "api/vitest/@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="], - - "api/vitest/@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="], + "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "api/vitest/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], + "body-parser/type-is/media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], - "api/vitest/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "api/vitest/tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], + "every-plugin/@module-federation/enhanced/@module-federation/bridge-react-webpack-plugin": ["@module-federation/bridge-react-webpack-plugin@0.22.1", "", { "dependencies": { "@module-federation/sdk": "0.22.1", "@types/semver": "7.5.8", "semver": "7.6.3" } }, "sha512-jKxU4GC5P/gVTJW1pOheHz+hk7yZiEmsyapNslxpD+ZVv2eN/OI6Om5mKJVtSa5tvrQMw/lVMAaX6UNkd34k0g=="], - "body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "every-plugin/@module-federation/enhanced/@module-federation/cli": ["@module-federation/cli@0.22.1", "", { "dependencies": { "@module-federation/dts-plugin": "0.22.1", "@module-federation/sdk": "0.22.1", "chalk": "3.0.0", "commander": "11.1.0", "jiti": "2.4.2" }, "bin": { "mf": "bin/mf.js" } }, "sha512-/kw1yb/kWuYxmLhvz1mpKTdSAR/O18A/DJLa39Rmayq++DMbQHEwFrYr3BsVRdDcAaX2/R+CyHATvVFNn5EPSg=="], - "body-parser/type-is/media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], + "every-plugin/@module-federation/enhanced/@module-federation/data-prefetch": ["@module-federation/data-prefetch@0.22.1", "", { "dependencies": { "@module-federation/runtime": "0.22.1", "@module-federation/sdk": "0.22.1", "fs-extra": "9.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-6jcZSFuUpU06IWPIaQeoB+HI2NI2BUmiV65oEYsjnwXtLMT8aFTGqN1XCZc0R2V7b5hBa1rSrk/FGCAXnwiFNQ=="], - "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "every-plugin/@module-federation/enhanced/@module-federation/dts-plugin": ["@module-federation/dts-plugin@0.22.1", "", { "dependencies": { "@module-federation/error-codes": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/sdk": "0.22.1", "@module-federation/third-party-dts-extractor": "0.22.1", "adm-zip": "^0.5.10", "ansi-colors": "^4.1.3", "axios": "^1.12.0", "chalk": "3.0.0", "fs-extra": "9.1.0", "isomorphic-ws": "5.0.0", "koa": "3.0.3", "lodash.clonedeepwith": "4.5.0", "log4js": "6.9.1", "node-schedule": "2.1.1", "rambda": "^9.1.0", "ws": "8.18.0" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["vue-tsc"] }, "sha512-+zdQco9j1wbIhTAlLG5mZ7lSem9X9YnUzZNVSKqKF69Wg/rm220acMPSXJc7W+Nw6DuSp0m9elMA3I31DW7etg=="], - "drizzle-kit/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + "every-plugin/@module-federation/enhanced/@module-federation/error-codes": ["@module-federation/error-codes@0.22.1", "", {}, "sha512-J3Gt4E2U9cSUoAUUrUSp7n1W8v3OT8B6UcVdt+p+fTKKkQ1yhDVWE7SOTgDCA7hiEaO9D6Gahwnn5IbxlH0pTQ=="], - "drizzle-kit/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + "every-plugin/@module-federation/enhanced/@module-federation/inject-external-runtime-core-plugin": ["@module-federation/inject-external-runtime-core-plugin@0.22.1", "", { "peerDependencies": { "@module-federation/runtime-tools": "0.22.1" } }, "sha512-1+bkU/qbV87sR4QvsCQXtple/DIV1w1nuBKukBWI9UCz8M42ihpDljmdq794n/BC4D9kUk6z0nbA7hjgPcC2hg=="], - "drizzle-kit/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + "every-plugin/@module-federation/enhanced/@module-federation/managers": ["@module-federation/managers@0.22.1", "", { "dependencies": { "@module-federation/sdk": "0.22.1", "find-pkg": "2.0.0", "fs-extra": "9.1.0" } }, "sha512-9x557xoKjZrNwIp12wYGnizSdDfwEVgorlODVLyUcRe1pT0mx3cKtSxvuvkUle+CylgYLz6b4AFRNEZjYD4oFQ=="], - "drizzle-kit/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + "every-plugin/@module-federation/enhanced/@module-federation/manifest": ["@module-federation/manifest@0.22.1", "", { "dependencies": { "@module-federation/dts-plugin": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/sdk": "0.22.1", "chalk": "3.0.0", "find-pkg": "2.0.0" } }, "sha512-DQiV24e8xb63tEJQMdRvFx4BwsKtLmGkU+NtR6GrnT2OT0pj6AEva+zr8AkQLH9vDWtzGAr7FFxjJyZbKj2RZQ=="], - "drizzle-kit/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + "every-plugin/@module-federation/enhanced/@module-federation/rspack": ["@module-federation/rspack@0.22.1", "", { "dependencies": { "@module-federation/bridge-react-webpack-plugin": "0.22.1", "@module-federation/dts-plugin": "0.22.1", "@module-federation/inject-external-runtime-core-plugin": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/manifest": "0.22.1", "@module-federation/runtime-tools": "0.22.1", "@module-federation/sdk": "0.22.1", "btoa": "1.2.1" }, "peerDependencies": { "@rspack/core": ">=0.7", "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["typescript", "vue-tsc"] }, "sha512-dBOUpvtcls+VBCFwWBct6Z6xbxL/XCdeoADzX5CwbVt5ZB9H3qq2Qcj9shwO5M+4KJsfQDBSzkL7gqK7vNFlKA=="], - "drizzle-kit/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + "every-plugin/@module-federation/enhanced/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.22.1", "", { "dependencies": { "@module-federation/runtime": "0.22.1", "@module-federation/webpack-bundler-runtime": "0.22.1" } }, "sha512-GzqNytPPnQVejl78XFFvtLyj3XNgPu6rSac2EbQkCxV3uzAD3kFQ7SW0VuwXWbQeRTUgt/4Nl/o+BrJXy14lsw=="], - "drizzle-kit/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + "every-plugin/@module-federation/enhanced/@module-federation/sdk": ["@module-federation/sdk@0.22.1", "", {}, "sha512-e+xcroeeZwb1lXK0tM6E7YmGr8lYHm3QzplWVM/q0Hs8SlvQMcM9Lv+JF6y9UQmhVSaMKW40PyPyqL0Y1rIeVw=="], - "drizzle-kit/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + "every-plugin/@module-federation/runtime-core/@module-federation/error-codes": ["@module-federation/error-codes@0.22.1", "", {}, "sha512-J3Gt4E2U9cSUoAUUrUSp7n1W8v3OT8B6UcVdt+p+fTKKkQ1yhDVWE7SOTgDCA7hiEaO9D6Gahwnn5IbxlH0pTQ=="], - "drizzle-kit/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + "every-plugin/@module-federation/runtime-core/@module-federation/sdk": ["@module-federation/sdk@0.22.1", "", {}, "sha512-e+xcroeeZwb1lXK0tM6E7YmGr8lYHm3QzplWVM/q0Hs8SlvQMcM9Lv+JF6y9UQmhVSaMKW40PyPyqL0Y1rIeVw=="], - "drizzle-kit/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "drizzle-kit/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + "express/type-is/media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], - "drizzle-kit/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "drizzle-kit/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + "hpack.js/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], - "drizzle-kit/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + "hpack.js/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], - "drizzle-kit/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + "http-assert/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], - "drizzle-kit/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + "http-assert/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], - "drizzle-kit/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + "koa/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], - "drizzle-kit/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + "node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - "drizzle-kit/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + "node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], - "drizzle-kit/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "drizzle-kit/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + "serve-index/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "drizzle-kit/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + "serve-index/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], - "drizzle-kit/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + "serve-index/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], - "drizzle-kit/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + "streamroller/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], - "drizzle-kit/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + "streamroller/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], - "drizzle-kit/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], - "every-plugin/@module-federation/enhanced/@module-federation/bridge-react-webpack-plugin": ["@module-federation/bridge-react-webpack-plugin@0.22.1", "", { "dependencies": { "@module-federation/sdk": "0.22.1", "@types/semver": "7.5.8", "semver": "7.6.3" } }, "sha512-jKxU4GC5P/gVTJW1pOheHz+hk7yZiEmsyapNslxpD+ZVv2eN/OI6Om5mKJVtSa5tvrQMw/lVMAaX6UNkd34k0g=="], + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], - "every-plugin/@module-federation/enhanced/@module-federation/cli": ["@module-federation/cli@0.22.1", "", { "dependencies": { "@module-federation/dts-plugin": "0.22.1", "@module-federation/sdk": "0.22.1", "chalk": "3.0.0", "commander": "11.1.0", "jiti": "2.4.2" }, "bin": { "mf": "bin/mf.js" } }, "sha512-/kw1yb/kWuYxmLhvz1mpKTdSAR/O18A/DJLa39Rmayq++DMbQHEwFrYr3BsVRdDcAaX2/R+CyHATvVFNn5EPSg=="], + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], - "every-plugin/@module-federation/enhanced/@module-federation/data-prefetch": ["@module-federation/data-prefetch@0.22.1", "", { "dependencies": { "@module-federation/runtime": "0.22.1", "@module-federation/sdk": "0.22.1", "fs-extra": "9.1.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-6jcZSFuUpU06IWPIaQeoB+HI2NI2BUmiV65oEYsjnwXtLMT8aFTGqN1XCZc0R2V7b5hBa1rSrk/FGCAXnwiFNQ=="], + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], - "every-plugin/@module-federation/enhanced/@module-federation/dts-plugin": ["@module-federation/dts-plugin@0.22.1", "", { "dependencies": { "@module-federation/error-codes": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/sdk": "0.22.1", "@module-federation/third-party-dts-extractor": "0.22.1", "adm-zip": "^0.5.10", "ansi-colors": "^4.1.3", "axios": "^1.12.0", "chalk": "3.0.0", "fs-extra": "9.1.0", "isomorphic-ws": "5.0.0", "koa": "3.0.3", "lodash.clonedeepwith": "4.5.0", "log4js": "6.9.1", "node-schedule": "2.1.1", "rambda": "^9.1.0", "ws": "8.18.0" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["vue-tsc"] }, "sha512-+zdQco9j1wbIhTAlLG5mZ7lSem9X9YnUzZNVSKqKF69Wg/rm220acMPSXJc7W+Nw6DuSp0m9elMA3I31DW7etg=="], + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], - "every-plugin/@module-federation/enhanced/@module-federation/error-codes": ["@module-federation/error-codes@0.22.1", "", {}, "sha512-J3Gt4E2U9cSUoAUUrUSp7n1W8v3OT8B6UcVdt+p+fTKKkQ1yhDVWE7SOTgDCA7hiEaO9D6Gahwnn5IbxlH0pTQ=="], + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], - "every-plugin/@module-federation/enhanced/@module-federation/inject-external-runtime-core-plugin": ["@module-federation/inject-external-runtime-core-plugin@0.22.1", "", { "peerDependencies": { "@module-federation/runtime-tools": "0.22.1" } }, "sha512-1+bkU/qbV87sR4QvsCQXtple/DIV1w1nuBKukBWI9UCz8M42ihpDljmdq794n/BC4D9kUk6z0nbA7hjgPcC2hg=="], + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], - "every-plugin/@module-federation/enhanced/@module-federation/managers": ["@module-federation/managers@0.22.1", "", { "dependencies": { "@module-federation/sdk": "0.22.1", "find-pkg": "2.0.0", "fs-extra": "9.1.0" } }, "sha512-9x557xoKjZrNwIp12wYGnizSdDfwEVgorlODVLyUcRe1pT0mx3cKtSxvuvkUle+CylgYLz6b4AFRNEZjYD4oFQ=="], + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], - "every-plugin/@module-federation/enhanced/@module-federation/manifest": ["@module-federation/manifest@0.22.1", "", { "dependencies": { "@module-federation/dts-plugin": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/sdk": "0.22.1", "chalk": "3.0.0", "find-pkg": "2.0.0" } }, "sha512-DQiV24e8xb63tEJQMdRvFx4BwsKtLmGkU+NtR6GrnT2OT0pj6AEva+zr8AkQLH9vDWtzGAr7FFxjJyZbKj2RZQ=="], + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], - "every-plugin/@module-federation/enhanced/@module-federation/rspack": ["@module-federation/rspack@0.22.1", "", { "dependencies": { "@module-federation/bridge-react-webpack-plugin": "0.22.1", "@module-federation/dts-plugin": "0.22.1", "@module-federation/inject-external-runtime-core-plugin": "0.22.1", "@module-federation/managers": "0.22.1", "@module-federation/manifest": "0.22.1", "@module-federation/runtime-tools": "0.22.1", "@module-federation/sdk": "0.22.1", "btoa": "1.2.1" }, "peerDependencies": { "@rspack/core": ">=0.7", "typescript": "^4.9.0 || ^5.0.0", "vue-tsc": ">=1.0.24" }, "optionalPeers": ["typescript", "vue-tsc"] }, "sha512-dBOUpvtcls+VBCFwWBct6Z6xbxL/XCdeoADzX5CwbVt5ZB9H3qq2Qcj9shwO5M+4KJsfQDBSzkL7gqK7vNFlKA=="], + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], - "every-plugin/@module-federation/enhanced/@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.22.1", "", { "dependencies": { "@module-federation/runtime": "0.22.1", "@module-federation/webpack-bundler-runtime": "0.22.1" } }, "sha512-GzqNytPPnQVejl78XFFvtLyj3XNgPu6rSac2EbQkCxV3uzAD3kFQ7SW0VuwXWbQeRTUgt/4Nl/o+BrJXy14lsw=="], + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], - "every-plugin/@module-federation/runtime-core/@module-federation/error-codes": ["@module-federation/error-codes@0.22.1", "", {}, "sha512-J3Gt4E2U9cSUoAUUrUSp7n1W8v3OT8B6UcVdt+p+fTKKkQ1yhDVWE7SOTgDCA7hiEaO9D6Gahwnn5IbxlH0pTQ=="], + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], - "express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], - "express/type-is/media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], - "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], - "host/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], - "hpack.js/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], - "hpack.js/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + "tsx/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], - "http-assert/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], - "http-assert/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], + "tsx/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], - "koa/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], - "node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + "tsx/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], - "node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], - "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], - "serve-index/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], - "serve-index/http-errors/depd": ["depd@1.1.2", "", {}, "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ=="], + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], - "serve-index/http-errors/inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="], + "type-is/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], - "serve-index/http-errors/setprototypeof": ["setprototypeof@1.1.0", "", {}, "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="], + "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="], - "serve-index/http-errors/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="], + "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.2", "", { "os": "android", "cpu": "arm" }, "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA=="], - "streamroller/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.2", "", { "os": "android", "cpu": "arm64" }, "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA=="], - "streamroller/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.2", "", { "os": "android", "cpu": "x64" }, "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A=="], - "type-is/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg=="], - "ui/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA=="], - "ui/vitest/@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], + "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g=="], - "ui/vitest/@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="], + "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA=="], - "ui/vitest/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], + "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw=="], - "ui/vitest/@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="], + "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw=="], - "ui/vitest/@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="], + "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.2", "", { "os": "linux", "cpu": "ia32" }, "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w=="], - "ui/vitest/@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="], + "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg=="], - "ui/vitest/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], + "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw=="], - "ui/vitest/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ=="], - "ui/vitest/tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], + "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.2", "", { "os": "linux", "cpu": "none" }, "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA=="], - "webpack-dev-middleware/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w=="], - "@module-federation/inject-external-runtime-core-plugin/@module-federation/runtime-tools/@module-federation/webpack-bundler-runtime/@module-federation/sdk": ["@module-federation/sdk@0.21.6", "", {}, "sha512-x6hARETb8iqHVhEsQBysuWpznNZViUh84qV2yE7AD+g7uIzHKiYdoWqj10posbo5XKf/147qgWDzKZoKoEP2dw=="], + "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/bridge-react-webpack-plugin/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/cli/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.2", "", { "os": "none", "cpu": "x64" }, "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/cli/jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="], + "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/data-prefetch/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/dts-plugin/@module-federation/third-party-dts-extractor": ["@module-federation/third-party-dts-extractor@0.22.1", "", { "dependencies": { "find-pkg": "2.0.0", "fs-extra": "9.1.0", "resolve": "1.22.8" } }, "sha512-RhRNIZ9q1ifYW5IW8VAfvf1OnF0ME/uItJ2YWwEB0nsELX34eogvJTx0Y5l+aOhKpdIaCSP4RUUCK4zKzPQ4Yg=="], + "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.2", "", { "os": "none", "cpu": "arm64" }, "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/dts-plugin/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/dts-plugin/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/managers/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ=="], - "@module-federation/node/@module-federation/enhanced/@module-federation/runtime-tools/@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.22.1", "", { "dependencies": { "@module-federation/runtime": "0.22.1", "@module-federation/sdk": "0.22.1" } }, "sha512-+rJ91eJPCIlyDylIwekBxsO33S2AtuiUWdToA6tYFpOTAkTtBk1OW/PpQaLrOpw1Eny9EH8fOXqQMCvGvUbMXA=="], + "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.2", "", { "os": "win32", "cpu": "x64" }, "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ=="], - "every-plugin/@module-federation/enhanced/@module-federation/bridge-react-webpack-plugin/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "webpack-dev-middleware/mime-types/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], "every-plugin/@module-federation/enhanced/@module-federation/cli/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], diff --git a/host/README.md b/host/README.md index f9b2985..547cacc 100644 --- a/host/README.md +++ b/host/README.md @@ -1,127 +1,200 @@ # host -Server host for the application with authentication and Module Federation. +Server host with authentication and Module Federation. Orchestrates UI and API federation. ## Architecture -The host orchestrates two federation systems: +The host orchestrates both UI and API federation: -``` +```bash ┌─────────────────────────────────────────────────────────┐ │ host │ │ │ │ ┌────────────────────────────────────────────────┐ │ -│ │ server.ts │ │ +│ │ src/program.ts │ │ │ │ Hono.js + oRPC handlers │ │ │ └────────────────────────────────────────────────┘ │ │ ↑ ↑ │ +│ │ bos.config.json │ │ +│ │ (single source) │ │ │ ┌────────┴────────┐ ┌────────┴────────┐ │ -│ │ bos.config.json │ │ bos.config.json │ │ │ │ UI Federation │ │ API Plugins │ │ +│ │ (remoteEntry) │ │ (every-plugin) │ │ │ └────────┬────────┘ └────────┬────────┘ │ │ ↓ ↓ │ │ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ Module Fed │ │ every-plugin │ │ -│ │ runtime │ │ runtime │ │ -│ └─────────────────┘ └─────────────────┘ │ -│ ↓ ↓ │ -│ ┌─────────────────┐ ┌─────────────────┐ │ │ │ React app │ │ oRPC router │ │ │ │ (SSR/CSR) │ │ (merged) │ │ │ └─────────────────┘ └─────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` +## Directory Structure + +``` +host/ +├── server.ts # Entry point +├── bootstrap.ts # Remote host loader +├── src/ +│ ├── program.ts # Main server program +│ ├── ui.tsx # UI rendering +│ ├── types.ts # Type definitions +│ ├── db/ +│ │ └── schema/ +│ │ └── auth.ts # Auth schema +│ ├── layers/ +│ │ └── index.ts # Effect layers composition +│ ├── lib/ +│ │ └── schemas.ts # Shared schemas +│ ├── services/ +│ │ ├── auth.ts # Better-Auth setup +│ │ ├── config.ts # Runtime config loader +│ │ ├── context.ts # Request context +│ │ ├── database.ts # Database connection +│ │ ├── errors.ts # Error types +│ │ ├── federation.server.ts # UI module loading +│ │ ├── plugins.ts # API plugin loading +│ │ └── router.ts # Router creation +│ └── utils/ +│ └── logger.ts # Logging utility +├── migrations/ # Drizzle migrations +├── drizzle.config.ts # Drizzle config +└── package.json +``` + ## Configuration -All runtime configuration is in `bos.config.json` at the project root: +All configuration from `bos.config.json`: ```json { - "account": "agency.near", + "account": "example.near", "app": { "host": { - "title": "agent", - "development": "http://localhost:3001", - "production": "https://" + "title": "App Title", + "description": "App description", + "development": "http://localhost:3000", + "production": "https://example.com", + "secrets": ["HOST_DATABASE_URL", "HOST_DATABASE_AUTH_TOKEN", "BETTER_AUTH_SECRET", "BETTER_AUTH_URL"] }, "ui": { "name": "ui", "development": "http://localhost:3002", - "production": "https://", - "exposes": { - "App": "./App", - "components": "./components", - "providers": "./providers", - "types": "./types" - } + "production": "https://cdn.example.com/ui", + "ssr": "https://cdn.example.com/ui-ssr" }, "api": { "name": "api", "development": "http://localhost:3014", - "production": "https://", - "variables": { - "NEAR_AI_MODEL": "deepseek-ai/DeepSeek-V3.1" - }, - "secrets": [ - "API_DATABASE_URL", - "API_DATABASE_AUTH_TOKEN", - "NEAR_AI_API_KEY", - "NEAR_AI_BASE_URL" - ] + "production": "https://cdn.example.com/api", + "secrets": ["API_DATABASE_URL", "API_DATABASE_AUTH_TOKEN", "NEAR_AI_API_KEY"] } } } ``` -**Router Composition** (`routers/index.ts`): +**Environment Variables:** -```typescript -return { - ...baseRouter, // /health, /status - ...plugins.api.router, // plugin routes -} +| Variable | Description | Default | +|----------|-------------|---------| +| `UI_SOURCE` | `local` or `remote` | Based on NODE_ENV | +| `API_SOURCE` | `local` or `remote` | Based on NODE_ENV | +| `API_PROXY` | Proxy API requests to another host URL | - | +| `HOST_DATABASE_URL` | SQLite database URL for auth | `file:./database.db` | +| `HOST_DATABASE_AUTH_TOKEN` | Auth token for remote database | - | +| `BETTER_AUTH_SECRET` | Secret for session encryption | - | +| `BETTER_AUTH_URL` | Base URL for auth endpoints | - | +| `CORS_ORIGIN` | Comma-separated allowed origins | Host + UI URLs | + +### Proxy Mode + +Set `API_PROXY=true` or `API_PROXY=` to proxy all `/api/*` requests to another host instead of loading the API plugin locally. Useful for: + +- Development against production API +- Staging environments +- Testing without running the API server + +```bash +API_PROXY=https://production.example.com bun dev ``` ## Tech Stack - **Server**: Hono.js + @hono/node-server - **API**: oRPC (RPC + OpenAPI) -- **Auth**: Better-Auth + better-near-auth +- **Auth**: Better-Auth + better-near-auth (SIWN) - **Database**: SQLite (libsql) + Drizzle ORM - **Build**: Rsbuild + Module Federation - **Plugins**: every-plugin runtime +- **Effects**: Effect-TS for service composition ## Available Scripts -- `bun dev` - Start dev server (Host: 3001, UI: 3002, API: 3014) -- `bun build` - Build for production -- `bun preview` - Run production server +- `bun dev` - Start dev server (port 3000) +- `bun build` - Build MF bundle for production (outputs `remoteEntry.js`) +- `bun bootstrap` - Run host from remote MF URL (requires `HOST_REMOTE_URL`) +- `bun preview` - Run production server locally +- `bun test` - Run tests +- `bun typecheck` - Type checking - `bun db:migrate` - Run migrations +- `bun db:push` - Push schema changes +- `bun db:generate` - Generate migrations - `bun db:studio` - Open Drizzle Studio -## API Routes +## Remote Host Mode -- `/api/auth/*` - Authentication endpoints (Better-Auth) -- `/api/rpc/*` - RPC endpoint (batching supported) -- `/api/*` - REST API (OpenAPI spec) -- `/health` - Health check +The host can be deployed as a Module Federation remote and loaded dynamically at runtime: -## Adding New Plugins +### Building & Deploying -1. Add plugin to `bos.config.json`: -```json -{ - "app": { - "new-plugin": { - "name": "new-plugin", - "development": "http://localhost:3015", - "production": "https://cdn.example.com/plugin/remoteEntry.js", - "variables": {}, - "secrets": [] - } - } -} +```bash +# Build the MF bundle (deploys to Zephyr, updates bos.config.json) +cd host +bun build +``` + +This produces `dist/remoteEntry.js` and deploys to Zephyr. The Zephyr URL is saved to `bos.config.json → app.host.remote`. + +### Production Deployment (Railway/Docker) + +Use the bootstrap script to run the host from a remote URL: + +```bash +# Set the remote URL +export HOST_REMOTE_URL=https://your-zephyr-url.zephyrcloud.app + +# Run +bun bootstrap +``` + +**Dockerfile example:** +```dockerfile +FROM oven/bun:latest +WORKDIR /app +COPY package.json bun.lockb ./ +RUN bun install +COPY bootstrap.ts ./ +CMD ["bun", "bootstrap"] ``` -2. Plugin router is automatically merged in `routers/index.ts` +**Required Environment Variables:** +- `HOST_REMOTE_URL` - Zephyr URL of the deployed host bundle +- `HOST_DATABASE_URL` - Database connection string +- `BETTER_AUTH_SECRET` - Auth encryption secret +- `BETTER_AUTH_URL` - Base URL for auth endpoints + +### Benefits + +1. **No local host code needed** - Just reference the remote URL +2. **Instant updates** - Deploy new bundle, containers pick it up on restart +3. **Version flexibility** - Pin to specific Zephyr URLs for stability +4. **Same binary everywhere** - Bootstrap script is tiny, all logic lives in the bundle + +## API Routes + +| Route | Description | +|-------|-------------| +| `/health` | Health check | +| `/api/auth/*` | Authentication endpoints (Better-Auth) | +| `/api/rpc/*` | RPC endpoint (batching supported) | +| `/api/*` | REST API (OpenAPI spec at `/api`) | diff --git a/host/bootstrap.ts b/host/bootstrap.ts new file mode 100644 index 0000000..ec35bab --- /dev/null +++ b/host/bootstrap.ts @@ -0,0 +1,81 @@ +#!/usr/bin/env bun +import "dotenv/config"; +import { createInstance, getInstance } from "@module-federation/enhanced/runtime"; +import { setGlobalFederationInstance } from "@module-federation/runtime-core"; + +interface ServerHandle { + ready: Promise; + shutdown: () => Promise; +} + +function getRemoteUrl(): string { + const url = process.env.HOST_REMOTE_URL; + if (!url) { + console.error("❌ HOST_REMOTE_URL environment variable is required"); + console.error(" Set it to the Zephyr URL of your deployed host bundle"); + process.exit(1); + } + return url; +} + +async function bootstrap() { + const remoteUrl = getRemoteUrl(); + + console.log("🚀 Bootstrapping host from remote..."); + console.log(` Remote URL: ${remoteUrl}`); + + let serverHandle: ServerHandle | null = null; + + const shutdown = async () => { + console.log("\n[Bootstrap] Shutting down..."); + if (serverHandle) { + await serverHandle.shutdown(); + } + process.exit(0); + }; + + process.on("SIGINT", () => void shutdown()); + process.on("SIGTERM", () => void shutdown()); + + try { + let mf = getInstance(); + if (!mf) { + mf = createInstance({ + name: "bootstrap-host", + remotes: [], + }); + setGlobalFederationInstance(mf); + } + + const remoteEntryUrl = remoteUrl.endsWith("/remoteEntry.js") + ? remoteUrl + : `${remoteUrl}/remoteEntry.js`; + + console.log(` Loading: ${remoteEntryUrl}`); + + mf.registerRemotes([{ + name: "host", + entry: remoteEntryUrl, + }]); + + console.log(" Loading host/Server module..."); + const hostModule = await mf.loadRemote<{ runServer: () => ServerHandle }>("host/Server"); + + if (!hostModule?.runServer) { + throw new Error("Host module does not export runServer function"); + } + + console.log(" Starting server..."); + serverHandle = hostModule.runServer(); + + await serverHandle.ready; + console.log("✅ Server ready"); + + await new Promise(() => {}); + } catch (error) { + console.error("❌ Failed to bootstrap host:", error); + process.exit(1); + } +} + +bootstrap(); diff --git a/host/index.html b/host/index.html deleted file mode 100644 index 06ead7a..0000000 --- a/host/index.html +++ /dev/null @@ -1,147 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -
- -
-
- -
-
-
-
-
-
-
-
-
-
-
- - diff --git a/host/package.json b/host/package.json index e4eaa45..ad13398 100644 --- a/host/package.json +++ b/host/package.json @@ -1,52 +1,58 @@ { "name": "host", + "version": "1.0.0", "private": true, "type": "module", "scripts": { "dev": "BOS_CONFIG_PATH=../bos.config.json tsx server.ts", - "build": "rsbuild build", + "build": "NODE_ENV=production rsbuild build", + "bootstrap": "tsx bootstrap.ts", "preview": "NODE_ENV=production BOS_CONFIG_PATH=../bos.config.json tsx server.ts", + "test": "NODE_ENV=production BOS_CONFIG_PATH=../bos.config.json vitest run", + "test:watch": "NODE_ENV=production BOS_CONFIG_PATH=../bos.config.json vitest", "typecheck": "tsc --noEmit", "db:push": "drizzle-kit push", "db:studio": "drizzle-kit studio", "db:generate": "drizzle-kit generate", - "db:migrate": "drizzle-kit migrate", - "promote-admin": "tsx src/scripts/promote-admin.ts" + "db:migrate": "drizzle-kit migrate" }, "dependencies": { + "effect": "catalog:", "@hono/node-server": "^1.19.9", "@hot-labs/near-connect": "^0.8.2", - "@libsql/client": "^0.15.15", - "@module-federation/enhanced": "^0.21.6", - "@module-federation/node": "^2.7.27", - "@module-federation/rsbuild-plugin": "^0.21.6", - "@module-federation/runtime": "^0.21.6", - "@module-federation/runtime-core": "^0.21.6", + "@libsql/client": "^0.17.0", + "@module-federation/enhanced": "^0.23.0", + "@module-federation/node": "^2.7.28", + "@module-federation/runtime-core": "^0.23.0", "@orpc/openapi": "^1.13.4", "@orpc/server": "^1.13.4", "@orpc/zod": "^1.13.4", "@t3-oss/env-core": "^0.13.10", - "@tanstack/react-query": "^5.90.19", - "@tanstack/react-router": "^1.151.1", - "better-auth": "^1.4.14", - "better-near-auth": "^0.3.4", + "@tanstack/react-query": "catalog:", + "@tanstack/react-router": "catalog:", + "better-auth": "catalog:", + "better-near-auth": "catalog:", "dotenv": "^17.2.3", "drizzle-kit": "^0.31.8", "drizzle-orm": "^0.45.1", - "every-plugin": "^0.8.8", - "hono": "^4.11.4", - "near-kit": "^0.6.3", - "react": "^19.2.3", - "react-dom": "^19.2.3" + "every-plugin": "catalog:", + "hono": "^4.11.6", + "near-kit": "catalog:", + "react": "^19.2.4", + "react-dom": "^19.2.4" }, "devDependencies": { + "@module-federation/rsbuild-plugin": "^0.23.0", "@rsbuild/core": "^1.7.2", "@rsbuild/plugin-react": "^1.4.3", - "@types/node": "^22.19.7", - "@types/react": "^19.2.8", + "@types/node": "^25.0.10", + "@types/react": "^19.2.9", "@types/react-dom": "^19.2.3", "tsx": "^4.21.0", - "typescript": "^5.9.3", - "zephyr-rsbuild-plugin": "^0.1.4" + "typescript": "catalog:", + "vite-tsconfig-paths": "^6.0.5", + "vitest": "^4.0.18", + "web-vitals": "^5.1.0", + "zephyr-rsbuild-plugin": "^0.1.8" } } diff --git a/host/rsbuild.config.ts b/host/rsbuild.config.ts index 90e08d1..f7952fd 100644 --- a/host/rsbuild.config.ts +++ b/host/rsbuild.config.ts @@ -1,43 +1,22 @@ import fs from "node:fs"; import path from "node:path"; -import { pluginModuleFederation } from "@module-federation/rsbuild-plugin"; +import { ModuleFederationPlugin } from "@module-federation/enhanced/rspack"; import { defineConfig } from "@rsbuild/core"; import { pluginReact } from "@rsbuild/plugin-react"; import { withZephyr } from "zephyr-rsbuild-plugin"; -import pkg from "./package.json"; const __dirname = import.meta.dirname; const isProduction = process.env.NODE_ENV === "production"; -const useRemoteUi = process.env.USE_REMOTE_UI === "true"; const configPath = process.env.BOS_CONFIG_PATH ?? path.resolve(__dirname, "../bos.config.json"); -const bosConfig = JSON.parse(fs.readFileSync(configPath, "utf8")); -const env = isProduction ? "production" : "development"; -const uiUrl = useRemoteUi ? bosConfig.app.ui.production : bosConfig.app.ui[env]; - -function getClientRuntimeConfig() { - return { - env, - title: bosConfig.app.host.title, - hostUrl: bosConfig.app.host[env], - ui: { - name: bosConfig.app.ui.name, - url: uiUrl, - exposes: bosConfig.app.ui.exposes, - }, - apiBase: "/api", - rpcBase: "/api/rpc", - }; -} - -function updateBosConfig(hostUrl: string) { +function updateBosConfig(field: "production" | "remote", url: string) { try { const config = JSON.parse(fs.readFileSync(configPath, "utf8")); - config.app.host.production = hostUrl; - fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n"); - console.log(" ✅ Updated bos.config.json"); + config.app.host[field] = url; + fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`); + console.log(` ✅ Updated bos.config.json: app.host.${field}`); } catch (err) { console.error( " ❌ Failed to update bos.config.json:", @@ -46,46 +25,7 @@ function updateBosConfig(hostUrl: string) { } } -const plugins = [ - pluginReact(), - pluginModuleFederation({ - name: "host", - remotes: {}, - dts: false, - shared: { - react: { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies.react, - }, - "react-dom": { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies["react-dom"], - }, - "@tanstack/react-query": { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies["@tanstack/react-query"], - }, - "@tanstack/react-router": { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies["@tanstack/react-router"], - }, - "@hot-labs/near-connect": { - singleton: true, - eager: false, - requiredVersion: pkg.dependencies["@hot-labs/near-connect"], - }, - "near-kit": { - singleton: true, - eager: false, - requiredVersion: pkg.dependencies["near-kit"], - }, - }, - }), -]; +const plugins = [pluginReact()]; if (isProduction) { plugins.push( @@ -93,7 +33,7 @@ if (isProduction) { hooks: { onDeployComplete: (info: { url: string }) => { console.log("🚀 Host Deployed:", info.url); - updateBosConfig(info.url); + updateBosConfig("remote", info.url); }, }, }) @@ -103,82 +43,59 @@ if (isProduction) { export default defineConfig({ plugins, source: { - define: { - "process.env.NODE_ENV": JSON.stringify( - process.env.NODE_ENV || "development" - ), - "process.env.USE_REMOTE_API": JSON.stringify( - process.env.USE_REMOTE_API || "false" - ), - "process.env.USE_REMOTE_UI": JSON.stringify( - process.env.USE_REMOTE_UI || "false" - ), - "process.env.PUBLIC_ACCOUNT_ID": JSON.stringify(bosConfig.account), - "process.env.BETTER_AUTH_URL": JSON.stringify( - process.env.BETTER_AUTH_URL || - bosConfig.app.host[process.env.NODE_ENV || "development"] - ), - }, entry: { - index: "./src/index.client.tsx", + index: "./src/program.ts", }, }, - html: { - template: "./index.html", - title: bosConfig.app.host.title, - templateParameters: { - title: bosConfig.app.host.title, - description: bosConfig.app.host.description, + resolve: { + alias: { + "@": "./src", }, - inject: "body", - scriptLoading: "defer", - tags: [ - { - tag: "script", - attrs: {}, - children: `window.__RUNTIME_CONFIG__=${JSON.stringify( - getClientRuntimeConfig() - )};`, - head: true, - append: false, - }, - { - tag: "link", - attrs: { - rel: "preload", - href: `${uiUrl}/remoteEntry.js`, - as: "script", - }, - head: true, - append: true, - }, - ], }, dev: { progressBar: false, - client: { - overlay: false, - }, - }, - server: { - port: 3001, - proxy: { - "/api": "http://localhost:3000", - }, - historyApiFallback: true, }, tools: { rspack: { + target: "async-node", + optimization: { + nodeEnv: false, + }, + output: { + uniqueName: "host", + library: { type: "commonjs-module" }, + }, + externals: [ + /^node:/, + /^bun:/, + "@libsql/client", + ], infrastructureLogging: { level: "error", }, stats: "errors-warnings", + plugins: [ + new ModuleFederationPlugin({ + name: "host", + filename: "remoteEntry.js", + dts: false, + runtimePlugins: [require.resolve("@module-federation/node/runtimePlugin")], + library: { type: "commonjs-module" }, + exposes: { + "./Server": "./src/program.ts", + }, + }), + ], }, }, output: { + minify: false, distPath: { root: "dist", }, assetPrefix: "/", + filename: { + js: "[name].js", + }, }, }); diff --git a/host/server.ts b/host/server.ts index 2bf8561..1b204f8 100644 --- a/host/server.ts +++ b/host/server.ts @@ -1,313 +1,4 @@ -import { serve } from '@hono/node-server'; -import { serveStatic } from '@hono/node-server/serve-static'; -import { OpenAPIHandler } from '@orpc/openapi/fetch'; -import { OpenAPIReferencePlugin } from '@orpc/openapi/plugins'; -import { onError } from '@orpc/server'; -import { RPCHandler } from '@orpc/server/fetch'; -import { BatchHandlerPlugin } from '@orpc/server/plugins'; -import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4'; -import { createRsbuild, logger } from '@rsbuild/core'; -import 'dotenv/config'; -import { eq } from 'drizzle-orm'; -import { formatORPCError } from 'every-plugin/errors'; -import { Hono } from 'hono'; -import { cors } from 'hono/cors'; -import { randomBytes } from 'node:crypto'; -import { readFile } from 'node:fs/promises'; -import { resolve } from 'node:path'; -import { z } from 'every-plugin/zod'; -import config from './rsbuild.config'; -import { loadBosConfig, type RuntimeConfig } from './src/config'; -import { db } from './src/db'; -import * as schema from './src/db/schema/auth'; -import { initializeServerFederation } from './src/federation.server'; -import { initializeServerApiClient } from './src/lib/api-client.server'; -import { auth } from './src/lib/auth'; -import { createRouter } from './src/routers'; -import { initializePlugins } from './src/runtime'; -import { renderToStream, createSSRHtml } from './src/ssr'; -import { rateLimitChat, rateLimitKV, rateLimitAuth } from './src/middleware/rate-limit'; +import "dotenv/config"; +import { runServer } from "./src/program"; -const envSchema = z.object({ - BETTER_AUTH_SECRET: z.string().min(32, "BETTER_AUTH_SECRET must be at least 32 characters"), - BETTER_AUTH_URL: z.string().url("BETTER_AUTH_URL must be a valid URL"), - HOST_DATABASE_URL: z.string().min(1, "HOST_DATABASE_URL is required"), - CORS_ORIGIN: z.string().optional(), -}); - -function ensureDevSecrets() { - const isDev = process.env.NODE_ENV !== 'production'; - - if (!process.env.BETTER_AUTH_SECRET && isDev) { - const generated = randomBytes(32).toString('hex'); - process.env.BETTER_AUTH_SECRET = generated; - logger.warn('[Auth] ⚠️ Generated temporary BETTER_AUTH_SECRET for development'); - logger.warn(` For persistence, add to host/.env:`); - logger.warn(` BETTER_AUTH_SECRET=${generated}`); - } -} - -function validateEnv() { - const result = envSchema.safeParse(process.env); - if (!result.success) { - logger.error("❌ Invalid environment variables:"); - result.error.issues.forEach((issue) => { - logger.error(` ${issue.path.join(".")}: ${issue.message}`); - }); - logger.error("\nCheck your .env file against .env.example"); - process.exit(1); - } - logger.info("✅ Environment variables validated"); -} - -function injectRuntimeConfig(html: string, config: RuntimeConfig): string { - const clientConfig = { - env: config.env, - title: config.title, - hostUrl: config.hostUrl, - ui: config.ui, - apiBase: '/api', - rpcBase: '/api/rpc', - }; - const configScript = ``; - const preloadLink = ``; - - return html - .replace('', configScript) - .replace('', preloadLink); -} - -async function createContext(req: Request) { - const session = await auth.api.getSession({ headers: req.headers }); - - // Get NEAR account ID from linked accounts - let nearAccountId: string | null = null; - if (session?.user?.id) { - const nearAccount = await db.query.nearAccount.findFirst({ - where: eq(schema.nearAccount.userId, session.user.id), - }); - nearAccountId = nearAccount?.accountId ?? null; - } - - // Extract role from user - const role = (session?.user as { role?: string })?.role ?? null; - - return { - session, - user: session?.user, - nearAccountId, - role, - }; -} - -async function startServer() { - ensureDevSecrets(); - validateEnv(); - - const port = Number(process.env.PORT) || 3001; - const apiPort = Number(process.env.API_PORT) || 3000; - const isDev = process.env.NODE_ENV !== 'production'; - - const bosConfig = await loadBosConfig(); - const plugins = await initializePlugins(); - const router = createRouter(plugins); - - initializeServerApiClient(router); - - // Setup graceful shutdown handlers - const shutdown = async () => { - console.log('[Plugins] Shutting down plugin runtime...'); - if (plugins.runtime) { - await plugins.runtime.shutdown(); - } - process.exit(0); - }; - - process.on('SIGINT', shutdown); - process.on('SIGTERM', shutdown); - - const rpcHandler = new RPCHandler(router, { - plugins: [new BatchHandlerPlugin()], - interceptors: [onError((error) => formatORPCError(error))], - }); - - const apiHandler = new OpenAPIHandler(router, { - plugins: [ - new OpenAPIReferencePlugin({ - schemaConverters: [new ZodToJsonSchemaConverter()], - specGenerateOptions: { - info: { - title: bosConfig.title, - version: '1.0.0', - }, - servers: [{ url: `${bosConfig.hostUrl}/api` }], - }, - }), - ], - interceptors: [onError((error) => formatORPCError(error))], - }); - - const apiApp = new Hono(); - - // Configure CORS origins - const corsOrigins = process.env.CORS_ORIGIN?.split(',').map((o) => o.trim()) - ?? [bosConfig.hostUrl, bosConfig.ui.url]; - - if (!process.env.CORS_ORIGIN && isDev === false) { - logger.warn('[CORS] ⚠️ CORS_ORIGIN not set. Using bos.config.json defaults. Set explicitly for production.'); - } - - apiApp.use( - '/*', - cors({ - origin: corsOrigins, - credentials: true, - }) - ); - - apiApp.get('/health', (c) => c.text('OK')); - - apiApp.get('/health/ready', async (c) => { - const checks: Record = { - database: false, - ai: false, - }; - - // Check database connectivity - try { - await db.query.user.findFirst(); - checks.database = true; - } catch (error) { - console.error('[Health] Database check failed:', error); - checks.database = false; - } - - // Check AI service availability (optional dependency) - checks.ai = plugins?.status?.available ?? false; - - // Ready if database is connected (AI is optional) - const ready = checks.database; - - return c.json( - { - status: ready ? 'ready' : 'degraded', - checks, - timestamp: new Date().toISOString(), - }, - ready ? 200 : 503 - ); - }); - - apiApp.on(['POST', 'GET'], '/api/auth/*', rateLimitAuth, (c) => auth.handler(c.req.raw)); - - // Apply rate limiting to chat endpoints - apiApp.use('/api/chat', rateLimitChat); - apiApp.use('/api/chat/*', rateLimitChat); - - // Apply rate limiting to KV endpoints - apiApp.use('/api/kv', rateLimitKV); - apiApp.use('/api/kv/*', rateLimitKV); - - apiApp.all('/api/rpc/*', async (c) => { - const req = c.req.raw; - const context = await createContext(req); - - const result = await rpcHandler.handle(req, { - prefix: '/api/rpc', - context, - }); - - return result.response - ? c.newResponse(result.response.body, result.response) - : c.text('Not Found', 404); - }); - - apiApp.all('/api/*', async (c) => { - const req = c.req.raw; - const context = await createContext(req); - - const result = await apiHandler.handle(req, { - prefix: '/api', - context, - }); - - return result.response - ? c.newResponse(result.response.body, result.response) - : c.text('Not Found', 404); - }); - - if (isDev) { - serve({ fetch: apiApp.fetch, port: apiPort }, (info) => { - logger.info(`API server running at http://localhost:${info.port}`); - logger.info( - ` http://localhost:${info.port}/api → REST API (OpenAPI docs)` - ); - logger.info(` http://localhost:${info.port}/api/rpc → RPC endpoint`); - }); - - const rsbuild = await createRsbuild({ - cwd: import.meta.dirname, - rsbuildConfig: config, - }); - - await rsbuild.startDevServer(); - } else { - const ssrEnabled = process.env.DISABLE_SSR !== 'true'; - const indexHtml = await readFile(resolve(import.meta.dirname, './dist/index.html'), 'utf-8'); - const injectedHtml = injectRuntimeConfig(indexHtml, bosConfig); - - if (ssrEnabled) { - initializeServerFederation(bosConfig); - } - - apiApp.use('/*', serveStatic({ root: './dist' })); - - apiApp.get('*', async (c) => { - if (ssrEnabled) { - try { - const url = new URL(c.req.url).pathname + new URL(c.req.url).search; - const { stream, dehydratedState, headData } = await renderToStream({ - url, - config: bosConfig, - }); - - const decoder = new TextDecoder(); - let bodyContent = ''; - const reader = stream.getReader(); - - while (true) { - const { done, value } = await reader.read(); - if (done) break; - bodyContent += decoder.decode(value, { stream: true }); - } - bodyContent += decoder.decode(); - - const html = createSSRHtml(bodyContent, dehydratedState, bosConfig, headData); - return c.html(html); - } catch (error) { - logger.error('[SSR] Render failed, falling back to CSR:', error); - return c.html(injectedHtml); - } - } - - return c.html(injectedHtml); - }); - - serve({ fetch: apiApp.fetch, port }, (info) => { - logger.info( - `Host production server running at http://localhost:${info.port}` - ); - logger.info( - ` http://localhost:${info.port}/api → REST API (OpenAPI docs)` - ); - logger.info(` http://localhost:${info.port}/api/rpc → RPC endpoint`); - logger.info(` SSR: ${ssrEnabled ? 'Enabled' : 'Disabled'}`); - }); - } -} - -startServer().catch((err) => { - logger.error('Failed to start server'); - logger.error(err); - process.exit(1); -}); +runServer(); diff --git a/host/src/components.tsx b/host/src/components.tsx deleted file mode 100644 index 72024c8..0000000 --- a/host/src/components.tsx +++ /dev/null @@ -1,365 +0,0 @@ -import { loadRemote } from "@module-federation/runtime"; -import { - Suspense, - lazy, - useEffect, - useMemo, - useState, - type CSSProperties, - type ComponentType, - type FC, -} from "react"; -import { getRuntimeConfig } from "./federation"; -import { ErrorBoundary, Loading } from "./ui"; - -interface RegistryItem { - name: string; - type: string; - title: string; - description: string; - registryDependencies?: string[]; - files: { path: string; type: string }[]; - meta?: { - defaultProps?: Record; - }; -} - -interface Registry { - $schema: string; - name: string; - homepage: string; - items: RegistryItem[]; -} - -const Providers = lazy(async () => { - const config = getRuntimeConfig(); - const module = await loadRemote<{ - default: FC<{ children: React.ReactNode }>; - }>(`${config.ui.name}/providers`); - if (!module) throw new Error(`Failed to load ${config.ui.name}/providers`); - return module; -}); - -const cardContainerStyle: CSSProperties = { - background: "#fff", - borderRadius: "12px", - border: "1px solid #e5e7eb", - overflow: "hidden", - display: "flex", - flexDirection: "column", -}; - -const cardHeaderStyle: CSSProperties = { - padding: "12px 16px", - borderBottom: "1px solid #e5e7eb", - background: "#fafafa", - display: "flex", - alignItems: "center", - justifyContent: "space-between", -}; - -const cardTitleStyle: CSSProperties = { - fontSize: "13px", - fontWeight: 600, - color: "#374151", - fontFamily: - "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace", -}; - -const previewContainerStyle: CSSProperties = { - padding: "24px", - display: "flex", - alignItems: "center", - justifyContent: "center", - minHeight: "120px", - background: "linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%)", -}; - -const propsToggleStyle: CSSProperties = { - fontSize: "11px", - color: "#6b7280", - cursor: "pointer", - display: "flex", - alignItems: "center", - gap: "4px", - padding: "4px 8px", - borderRadius: "4px", - border: "none", - background: "transparent", -}; - -const propsContainerStyle: CSSProperties = { - borderTop: "1px solid #e5e7eb", - background: "#f9fafb", - padding: "12px 16px", - fontSize: "11px", - fontFamily: - "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace", - color: "#6b7280", - overflow: "auto", - maxHeight: "120px", -}; - -const inlineLoaderStyle: CSSProperties = { - display: "flex", - alignItems: "center", - gap: "8px", - color: "#9ca3af", - fontSize: "12px", -}; - -const errorBadgeStyle: CSSProperties = { - fontSize: "11px", - color: "#dc2626", - background: "#fef2f2", - padding: "4px 8px", - borderRadius: "4px", -}; - -interface ComponentCardProps { - name: string; - title: string; - description: string; - Component: ComponentType>; - props: Record; - index: number; -} - -const ComponentCard: FC = ({ title, Component, props }) => { - const [showProps, setShowProps] = useState(false); - const hasProps = Object.keys(props).length > 0; - - return ( -
-
- {`<${title} />`} - {hasProps && ( - - )} -
-
- Failed to load} - > - - Loading... -
- } - > - - - -
- {hasProps && showProps && ( -
-
-            {JSON.stringify(props, null, 2)}
-          
-
- )} - - ); -}; - -const pageContainerStyle: CSSProperties = { - display: "flex", - flexDirection: "column", - height: "100vh", - width: "100vw", - overflow: "hidden", - background: "#f3f4f6", -}; - -const scrollContainerStyle: CSSProperties = { - flex: 1, - overflow: "auto", - padding: "clamp(16px, 4vw, 32px)", -}; - -const contentWrapperStyle: CSSProperties = { - maxWidth: "1200px", - margin: "0 auto", -}; - -const headerStyle: CSSProperties = { - marginBottom: "clamp(24px, 4vw, 40px)", -}; - -const titleStyle: CSSProperties = { - fontSize: "clamp(20px, 4vw, 28px)", - fontWeight: 600, - color: "#111827", - margin: 0, -}; - -const subtitleStyle: CSSProperties = { - fontSize: "clamp(13px, 2vw, 15px)", - color: "#6b7280", - marginTop: "8px", -}; - -const codeStyle: CSSProperties = { - background: "#e5e7eb", - padding: "2px 6px", - borderRadius: "4px", - fontFamily: - "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace", - fontSize: "0.9em", -}; - -const gridStyle: CSSProperties = { - display: "grid", - gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))", - gap: "clamp(16px, 3vw, 24px)", -}; - -const createLazyComponent = (componentName: string) => { - return lazy(async () => { - const config = getRuntimeConfig(); - const module = await loadRemote< - Record>> - >(`${config.ui.name}/components`); - if (!module || !module[componentName]) { - throw new Error( - `Component ${componentName} not found in ${config.ui.name}/components` - ); - } - return { default: module[componentName] }; - }); -}; - -export const Components: FC = () => { - const [ready, setReady] = useState(false); - const [registry, setRegistry] = useState(null); - const [registryError, setRegistryError] = useState(null); - const [config, setConfig] = useState | null>(null); - - useEffect(() => { - const timer = setTimeout(() => setReady(true), 50); - return () => clearTimeout(timer); - }, []); - - useEffect(() => { - setConfig(getRuntimeConfig()); - }, []); - - useEffect(() => { - const fetchRegistry = async () => { - if (!config) return; - - try { - const remoteUrl = config.ui.url; - const baseUrl = remoteUrl.replace(/\/remoteEntry\.js$/, ""); - const registryUrl = `${baseUrl}/r/registry.json`; - - const response = await fetch(registryUrl); - if (!response.ok) - throw new Error(`Failed to fetch registry: ${response.status}`); - const data = await response.json(); - setRegistry(data); - } catch (err) { - console.error("Failed to load registry:", err); - setRegistryError(err instanceof Error ? err.message : "Unknown error"); - } - }; - - fetchRegistry(); - }, [config]); - - const componentEntries = useMemo(() => { - if (!registry) return []; - return registry.items.map((item) => ({ - name: item.name, - title: item.title, - description: item.description, - Component: createLazyComponent(item.title), - defaultProps: item.meta?.defaultProps || {}, - })); - }, [registry]); - - const wrapperAnimation: CSSProperties = { - opacity: ready ? 1 : 0, - transition: "opacity 300ms ease-out", - }; - - return ( -
- - - }> - -
-
-
-

Component Gallery

-

- Remote components from{" "} - - {config?.ui.name || "Loading..."} - -

-
- - {registryError && ( -
- Failed to load registry: {registryError} -
- )} - - {!registry && !registryError && ( -
- Loading component registry... -
- )} - -
- {componentEntries.map((entry, index) => ( - - ))} -
-
-
-
-
-
-
- ); -}; - -export default Components; diff --git a/host/src/config.ts b/host/src/config.ts deleted file mode 100644 index 979c4ad..0000000 --- a/host/src/config.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { readFile } from 'node:fs/promises'; -import { resolve } from 'node:path'; - -interface BosConfig { - account: string; - app: { - host: { - title: string; - development: string; - production: string; - }; - ui: { - name: string; - development: string; - production: string; - exposes: Record; - }; - api: { - name: string; - development: string; - production: string; - variables?: RuntimeVariables; - secrets?: string[]; - }; - }; -} - -type RuntimeVariables = Record; - -export interface RuntimeConfig { - env: 'development' | 'production'; - account: string; - title: string; - hostUrl: string; - ui: { - name: string; - url: string; - exposes: Record; - }; - api: { - name: string; - url: string; - variables?: RuntimeVariables; - secrets?: string[]; - }; -} - -export async function loadBosConfig(): Promise { - const env = (process.env.NODE_ENV as 'development' | 'production') || 'development'; - - const path = process.env.BOS_CONFIG_PATH ?? resolve(process.cwd(), 'bos.config.json'); - - const raw = await readFile(path, 'utf8'); - const config = JSON.parse(raw) as BosConfig; - - const useRemoteApi = process.env.USE_REMOTE_API === 'true'; - const useRemoteUi = process.env.USE_REMOTE_UI === 'true'; - - const api: RuntimeConfig['api'] = { - name: config.app.api.name, - url: useRemoteApi ? config.app.api.production : config.app.api[env], - variables: config.app.api.variables, - secrets: config.app.api.secrets, - }; - - return { - env, - account: config.account, - title: config.app.host.title, - hostUrl: config.app.host[env], - ui: { - name: config.app.ui.name, - url: useRemoteUi ? config.app.ui.production : config.app.ui[env], - exposes: config.app.ui.exposes, - }, - api, - }; -} diff --git a/host/src/db/index.ts b/host/src/db/index.ts deleted file mode 100644 index b20169e..0000000 --- a/host/src/db/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { drizzle } from 'drizzle-orm/libsql'; -import { createClient } from '@libsql/client'; -import * as authSchema from './schema/auth'; - -const client = createClient({ - url: process.env.HOST_DATABASE_URL || 'file:./database.db', - authToken: process.env.HOST_DATABASE_AUTH_TOKEN, -}); - -export const db = drizzle(client, { - schema: { - ...authSchema, - }, -}); diff --git a/host/src/federation.server.ts b/host/src/federation.server.ts deleted file mode 100644 index 27770d3..0000000 --- a/host/src/federation.server.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { createInstance } from '@module-federation/enhanced/runtime'; -import type { RuntimeConfig } from './config'; - -let mfInstance: ReturnType | null = null; - -export function getServerFederationInstance() { - return mfInstance; -} - -export function initializeServerFederation(config: RuntimeConfig) { - if (mfInstance) { - console.log('[Federation Server] Using existing instance'); - return mfInstance; - } - - mfInstance = createInstance({ - name: 'host_ssr', - remotes: [ - { - name: config.ui.name, - entry: `${config.ui.url}/remoteEntry.js`, - alias: config.ui.name, - }, - ], - }); - - console.log('[Federation Server] Created new instance with remote:', config.ui.name); - return mfInstance; -} - -export async function loadRemoteModule(remoteName: string, exposedModule: string): Promise { - if (!mfInstance) { - throw new Error('Server federation not initialized. Call initializeServerFederation first.'); - } - - const modulePath = `${remoteName}/${exposedModule}`; - const module = await mfInstance.loadRemote(modulePath); - - if (!module) { - throw new Error(`Failed to load remote module: ${modulePath}`); - } - - return module; -} diff --git a/host/src/federation.ts b/host/src/federation.ts deleted file mode 100644 index df690f7..0000000 --- a/host/src/federation.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { registerRemotes } from '@module-federation/enhanced/runtime'; - -interface RuntimeConfig { - env: 'development' | 'production'; - title: string; - hostUrl: string; - ui: { - name: string; - url: string; - exposes: Record; - }; - apiBase: string; - rpcBase: string; -} - -declare global { - interface Window { - __RUNTIME_CONFIG__?: RuntimeConfig; - } -} - -let runtimeConfig: RuntimeConfig | null = null; - -export function getRuntimeConfig(): RuntimeConfig { - if (!runtimeConfig) { - throw new Error('Runtime config not initialized. Ensure window.__RUNTIME_CONFIG__ is set.'); - } - return runtimeConfig; -} - -export async function initializeFederation() { - if (!window.__RUNTIME_CONFIG__) { - throw new Error('Runtime config not found. SSR should always inline __RUNTIME_CONFIG__.'); - } - - runtimeConfig = window.__RUNTIME_CONFIG__; - - console.log('[Federation] Registering dynamic remote:', { - name: runtimeConfig.ui.name, - entry: `${runtimeConfig.ui.url}/remoteEntry.js`, - alias: runtimeConfig.ui.name, - }); - - registerRemotes([ - { - name: runtimeConfig.ui.name, - entry: `${runtimeConfig.ui.url}/remoteEntry.js`, - alias: runtimeConfig.ui.name, - }, - ]); - - return runtimeConfig; -} diff --git a/host/src/index.client.tsx b/host/src/index.client.tsx deleted file mode 100644 index 49571cc..0000000 --- a/host/src/index.client.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { StrictMode } from 'react'; -import { createRoot } from 'react-dom/client'; -import { initializeFederation } from './federation'; - -const rootElement = document.getElementById('root'); - -if (!rootElement) { - throw new Error('Root element not found'); -} - -const pathname = window.location.pathname; - -// Initialize federation before rendering -initializeFederation().then(async () => { - const ComponentModule = pathname === '/components' - ? await import('./components') - : await import('./main'); - - const RootComponent = ComponentModule.default; - - createRoot(rootElement!).render( - - - - ); -}).catch((error) => { - console.error('Failed to initialize federation:', error); - document.body.innerHTML = '
Failed to initialize application. Check console for details.
'; -}); diff --git a/host/src/layers/index.ts b/host/src/layers/index.ts new file mode 100644 index 0000000..d63565a --- /dev/null +++ b/host/src/layers/index.ts @@ -0,0 +1,20 @@ +import { Layer } from "every-plugin/effect"; +import { AuthService } from "../services/auth"; +import { ConfigService } from "../services/config"; +import { DatabaseService } from "../services/database"; +import { FederationServerService } from "../services/federation.server"; +import { PluginsService } from "../services/plugins"; + +export const ConfigLive = ConfigService.Default; + +export const DatabaseLive = DatabaseService.Default; + +export const AuthLive = AuthService.Default; + +export const PluginsLive = PluginsService.Live; + +export const FederationServerLive = FederationServerService.Live; + +export const CoreLive = Layer.mergeAll(ConfigLive, DatabaseLive, AuthLive); + +export const FullServerLive = Layer.mergeAll(CoreLive, PluginsLive); diff --git a/host/src/lib/api-client.server.ts b/host/src/lib/api-client.server.ts deleted file mode 100644 index 881774e..0000000 --- a/host/src/lib/api-client.server.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { createRouterClient, type RouterClient } from 'every-plugin/orpc'; -import type { AppRouter } from '../routers'; - -declare global { - var $apiClient: RouterClient | undefined; -} - -export function initializeServerApiClient(router: AppRouter) { - globalThis.$apiClient = createRouterClient(router, { - context: async () => ({ - session: null, - user: null, - nearAccountId: null, - }), - }); -} - -export function getServerApiClient() { - if (!globalThis.$apiClient) { - throw new Error('Server API client not initialized. Call initializeServerApiClient first.'); - } - return globalThis.$apiClient; -} - -export function hasServerApiClient(): boolean { - return !!globalThis.$apiClient; -} diff --git a/host/src/lib/auth.ts b/host/src/lib/auth.ts deleted file mode 100644 index 6e34d88..0000000 --- a/host/src/lib/auth.ts +++ /dev/null @@ -1,57 +0,0 @@ - -import fs from "node:fs"; -import path from "node:path"; -import { betterAuth } from "better-auth"; -import { drizzleAdapter } from "better-auth/adapters/drizzle"; -import { admin } from "better-auth/plugins"; -import { siwn } from "better-near-auth"; -import { db } from "../db"; -import * as schema from "../db/schema/auth"; - -const configPath = process.env.BOS_CONFIG_PATH ?? path.resolve(process.cwd(), 'bos.config.json'); -const bosConfig = JSON.parse(fs.readFileSync(configPath, 'utf8')); -const env = process.env.NODE_ENV === "production" ? "production" : "development"; -const defaultOrigins = [ - bosConfig?.app?.host?.[env], - bosConfig?.app?.ui?.[env], -].filter(Boolean); - -export const auth = betterAuth({ - database: drizzleAdapter(db, { - provider: "sqlite", - schema: schema, - }), - trustedOrigins: process.env.CORS_ORIGIN?.split(",") || defaultOrigins, - secret: process.env.BETTER_AUTH_SECRET, - baseURL: process.env.BETTER_AUTH_URL, - plugins: [ - siwn({ - recipient: bosConfig.account - }), - admin({ - defaultRole: "user", - adminRoles: ["admin"], - }), - ], - account: { - accountLinking: { - enabled: true, - trustedProviders: ["siwn"], - allowDifferentEmails: true, - updateUserInfoOnLink: true - } - }, - session: { - cookieCache: { - enabled: true, - maxAge: 5 * 60 // 5 minutes cache - reduces DB hits - } - }, - advanced: { - defaultCookieAttributes: { - sameSite: "lax", - secure: process.env.NODE_ENV === "production", - httpOnly: true - } - } -}); diff --git a/host/src/lib/rate-limit.ts b/host/src/lib/rate-limit.ts deleted file mode 100644 index b90a25c..0000000 --- a/host/src/lib/rate-limit.ts +++ /dev/null @@ -1,85 +0,0 @@ -/** - * In-Memory Rate Limiter - * - * Provides simple rate limiting for API endpoints. - * For production multi-instance deployments, replace with Redis-backed implementation. - */ - -type RateLimitEntry = { - count: number; - resetAt: number; -}; - -type RateLimitConfig = { - windowMs: number; - maxRequests: number; -}; - -class RateLimiter { - private store = new Map(); - private cleanupInterval: NodeJS.Timeout; - - constructor() { - // Clean up expired entries every minute - this.cleanupInterval = setInterval(() => this.cleanup(), 60_000); - } - - check( - key: string, - config: RateLimitConfig - ): { allowed: boolean; remaining: number; resetAt: number } { - const now = Date.now(); - const entry = this.store.get(key); - - // No entry or expired - create new window - if (!entry || now >= entry.resetAt) { - const resetAt = now + config.windowMs; - this.store.set(key, { count: 1, resetAt }); - return { allowed: true, remaining: config.maxRequests - 1, resetAt }; - } - - // Rate limit exceeded - if (entry.count >= config.maxRequests) { - return { allowed: false, remaining: 0, resetAt: entry.resetAt }; - } - - // Increment counter - entry.count++; - return { - allowed: true, - remaining: config.maxRequests - entry.count, - resetAt: entry.resetAt, - }; - } - - private cleanup() { - const now = Date.now(); - for (const [key, entry] of this.store) { - if (now >= entry.resetAt) { - this.store.delete(key); - } - } - } - - destroy() { - clearInterval(this.cleanupInterval); - this.store.clear(); - } -} - -export const rateLimiter = new RateLimiter(); - -/** - * Rate limit configurations by endpoint type - * - * Production note: Adjust these based on your expected traffic patterns - * and NEAR AI Cloud API limits. - */ -export const RATE_LIMITS = { - chat: { windowMs: 60_000, maxRequests: 20 }, // 20 chat requests per minute - kv: { windowMs: 60_000, maxRequests: 100 }, // 100 KV operations per minute - auth: { windowMs: 60_000, maxRequests: 100 }, // 100 auth attempts per minute - global: { windowMs: 60_000, maxRequests: 1000 }, // 1000 total requests per minute -} as const; - -export type RateLimitType = keyof typeof RATE_LIMITS; diff --git a/host/src/main.tsx b/host/src/main.tsx deleted file mode 100644 index 3ec22d0..0000000 --- a/host/src/main.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { - Suspense, - lazy, - type FC, - useState, - type CSSProperties, - useCallback, -} from 'react'; -import { loadRemote } from '@module-federation/enhanced/runtime'; -import { ErrorBoundary, Loading } from './ui'; -import { getRuntimeConfig } from './federation'; - -const RemoteApp = lazy(async () => { - const config = getRuntimeConfig(); - const module = await loadRemote<{ default: FC }>(`${config.ui.name}/App`); - if (!module) throw new Error(`Failed to load ${config.ui.name}/App`); - return module; -}); - -export const Main: FC = () => { - const [retryKey, setRetryKey] = useState(0); - - const handleRetry = useCallback(() => { - console.log('[Host] Retrying remote app load...'); - setRetryKey((prev) => prev + 1); - }, []); - - const containerStyle: CSSProperties = { - display: 'flex', - flexDirection: 'column', - height: '100vh', - width: '100vw', - overflow: 'hidden', - }; - - const contentStyle: CSSProperties = { - flex: 1, - display: 'flex', - flexDirection: 'column', - overflow: 'auto', - }; - - return ( -
-
- { - console.error('[Host] Failed to load remote app:', error.message); - }} - onRetry={handleRetry} - > - }> - - - -
-
- ); -}; - -export default Main; diff --git a/host/src/middleware/rate-limit.ts b/host/src/middleware/rate-limit.ts deleted file mode 100644 index 681deb5..0000000 --- a/host/src/middleware/rate-limit.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Rate Limiting Middleware - * - * Provides configurable rate limiting for Hono routes. - * Keys are based on authenticated user ID (preferred) or IP address (fallback). - */ - -import type { Context, Next } from "hono"; -import { rateLimiter, RATE_LIMITS, type RateLimitType } from "../lib/rate-limit"; - -export function rateLimit(type: RateLimitType, keyFn?: (c: Context) => string) { - const config = RATE_LIMITS[type]; - - return async (c: Context, next: Next) => { - let key: string; - - if (keyFn) { - // Custom key function provided - key = keyFn(c); - } else { - // Default: use authenticated user ID or fall back to IP - const session = c.get("session"); - const userId = session?.user?.id; - const ip = c.req.header("x-forwarded-for")?.split(",")[0] || - c.req.header("x-real-ip") || - "unknown"; - key = userId || `ip:${ip}`; - } - - const fullKey = `${type}:${key}`; - const result = rateLimiter.check(fullKey, config); - - // Add rate limit headers to response - c.header("X-RateLimit-Limit", String(config.maxRequests)); - c.header("X-RateLimit-Remaining", String(result.remaining)); - c.header("X-RateLimit-Reset", String(Math.ceil(result.resetAt / 1000))); - - if (!result.allowed) { - c.header("Retry-After", String(Math.ceil((result.resetAt - Date.now()) / 1000))); - return c.json( - { - error: "RATE_LIMITED", - message: "Too many requests. Please slow down.", - retryAfter: Math.ceil((result.resetAt - Date.now()) / 1000), - }, - 429 - ); - } - - // Global rate limit check (protects against total system overload) - const globalResult = rateLimiter.check("global:all", RATE_LIMITS.global); - if (!globalResult.allowed) { - return c.json( - { - error: "RATE_LIMITED", - message: "Service is experiencing high load. Please try again shortly.", - retryAfter: Math.ceil((globalResult.resetAt - Date.now()) / 1000), - }, - 429 - ); - } - - await next(); - }; -} - -// Pre-configured middleware for common endpoints -export const rateLimitChat = rateLimit("chat"); -export const rateLimitKV = rateLimit("kv"); -export const rateLimitAuth = rateLimit("auth", (c) => { - // For auth, always key by IP (user isn't authenticated yet) - const ip = c.req.header("x-forwarded-for")?.split(",")[0] || - c.req.header("x-real-ip") || - "unknown"; - return `ip:${ip}`; -}); diff --git a/host/src/program.ts b/host/src/program.ts new file mode 100644 index 0000000..7470784 --- /dev/null +++ b/host/src/program.ts @@ -0,0 +1,372 @@ +import { createServer, type IncomingHttpHeaders } from "node:http"; +import { serve } from "@hono/node-server"; +import { serveStatic } from "@hono/node-server/serve-static"; +import { OpenAPIHandler } from "@orpc/openapi/fetch"; +import { OpenAPIReferencePlugin } from "@orpc/openapi/plugins"; +import { RPCHandler } from "@orpc/server/fetch"; +import { BatchHandlerPlugin } from "@orpc/server/plugins"; +import { ZodToJsonSchemaConverter } from "@orpc/zod/zod4"; +import { Effect, ManagedRuntime } from "every-plugin/effect"; +import { formatORPCError } from "every-plugin/errors"; +import { onError } from "every-plugin/orpc"; +import { type Context, Hono } from "hono"; +import { compress } from "hono/compress"; +import { cors } from "hono/cors"; +import { FullServerLive } from "./layers"; +import { type Auth, AuthService } from "./services/auth"; +import { type BootstrapConfig, ConfigService, type RuntimeConfig, setBootstrapConfig } from "./services/config"; +import { createRequestContext } from "./services/context"; +import type { Database } from "./services/database"; +import { closeDatabase, DatabaseService } from "./services/database"; +import { loadRouterModule, type RouterModule } from "./services/federation.server"; +import { type PluginResult, PluginsService } from "./services/plugins"; +import { createRouter } from "./services/router"; +import { logger } from "./utils/logger"; + +function nodeHeadersToHeaders(nodeHeaders: IncomingHttpHeaders): Headers { + const headers = new Headers(); + for (const [key, value] of Object.entries(nodeHeaders)) { + if (value) { + if (Array.isArray(value)) { + for (const v of value) { + headers.append(key, v); + } + } else { + headers.set(key, value); + } + } + } + return headers; +} + +async function proxyRequest(req: Request, targetBase: string): Promise { + const url = new URL(req.url); + const targetUrl = `${targetBase}${url.pathname}${url.search}`; + + const headers = new Headers(req.headers); + headers.delete("host"); + + const proxyReq = new Request(targetUrl, { + method: req.method, + headers, + body: req.body, + duplex: "half", + } as RequestInit); + + return fetch(proxyReq); +} + +function setupApiRoutes( + app: Hono, + config: RuntimeConfig, + plugins: PluginResult, + auth: Auth, + db: Database +) { + const isProxyMode = !!config.api.proxy; + + if (isProxyMode) { + const proxyTarget = config.api.proxy!; + logger.info(`[API] Proxy mode enabled → ${proxyTarget}`); + + app.all("/api/*", async (c: Context) => { + const response = await proxyRequest(c.req.raw, proxyTarget); + return response; + }); + + return; + } + + const router = createRouter(plugins); + + const rpcHandler = new RPCHandler(router, { + plugins: [new BatchHandlerPlugin()], + interceptors: [onError((error: unknown) => formatORPCError(error))], + }); + + const apiHandler = new OpenAPIHandler(router, { + plugins: [ + new OpenAPIReferencePlugin({ + schemaConverters: [new ZodToJsonSchemaConverter()], + specGenerateOptions: { + info: { + title: config.title, + version: "1.0.0", + }, + servers: [{ url: `${config.hostUrl}/api` }], + }, + }), + ], + interceptors: [onError((error: unknown) => formatORPCError(error))], + }); + + app.on(["POST", "GET"], "/api/auth/*", (c: Context) => auth.handler(c.req.raw)); + + app.all("/api/rpc/*", async (c: Context) => { + const req = c.req.raw; + const context = await createRequestContext(req, auth, db); + + const result = await rpcHandler.handle(req, { + prefix: "/api/rpc", + context, + }); + + return result.response ? c.newResponse(result.response.body, result.response) : c.text("Not Found", 404); + }); + + app.all("/api/*", async (c: Context) => { + const req = c.req.raw; + const context = await createRequestContext(req, auth, db); + + const result = await apiHandler.handle(req, { + prefix: "/api", + context, + }); + + return result.response ? c.newResponse(result.response.body, result.response) : c.text("Not Found", 404); + }); +} + +export const createStartServer = (onReady?: () => void) => Effect.gen(function* () { + const port = Number(process.env.PORT) || 3000; + const isDev = process.env.NODE_ENV !== "production"; + + const config = yield* ConfigService; + const db = yield* DatabaseService; + const auth = yield* AuthService; + const plugins = yield* PluginsService; + + const app = new Hono(); + + app.use( + "/*", + cors({ + origin: process.env.CORS_ORIGIN?.split(",").map((o) => o.trim()) ?? [ + config.hostUrl, + config.ui.url, + ], + credentials: true, + }) + ); + + if (!isDev) { + app.use("/*", async (c, next) => { + const accept = c.req.header("accept") || ""; + if (accept.includes("text/html")) { + return next(); + } + return compress()(c, next); + }); + } + + app.get("/health", (c: Context) => c.text("OK")); + + setupApiRoutes(app, config, plugins, auth, db); + + logger.info(`[Config] UI source: ${config.ui.source} → ${config.ui.url}`); + logger.info(`[Config] API source: ${config.api.source} → ${config.api.url}`); + if (config.api.proxy) { + logger.info(`[Config] API proxy: ${config.api.proxy}`); + } + + let ssrRouterModule: RouterModule | null = null; + + app.get("*", async (c: Context) => { + if (!ssrRouterModule) { + return c.html(` + + + + + Loading... + + + + +

⏳ SSR Loading...

+

The UI module is still loading. This page will refresh automatically.

+ + + `, 503); + } + + try { + const { env, account, title, hostUrl } = config; + const assetsUrl = config.ui.url; + const result = await ssrRouterModule.renderToStream(c.req.raw, { + assetsUrl, + runtimeConfig: { env, account, title, hostUrl, assetsUrl, apiBase: "/api", rpcBase: "/api/rpc" }, + }); + return new Response(result.stream, { + status: result.statusCode, + headers: result.headers, + }); + } catch (error) { + logger.error("[SSR] Streaming error:", error); + return c.html(` + + + + + Server Error + + + +

Server Error

+

An error occurred during server-side rendering.

+
${error instanceof Error ? error.stack : String(error)}
+ + + `, 500); + } + }); + + if (!isDev) { + app.use("/static/*", serveStatic({ root: "./dist" })); + app.use("/favicon.ico", serveStatic({ root: "./dist" })); + app.use("/icon.svg", serveStatic({ root: "./dist" })); + app.use("/manifest.json", serveStatic({ root: "./dist" })); + app.use("/robots.txt", serveStatic({ root: "./dist" })); + } + + const startHttpServer = () => { + if (isDev) { + const server = createServer(async (req, res) => { + const url = req.url || "/"; + const fetchReq = new Request(`http://localhost:${port}${url}`, { + method: req.method, + headers: nodeHeadersToHeaders(req.headers), + body: req.method !== "GET" && req.method !== "HEAD" ? req : undefined, + duplex: "half", + } as RequestInit); + + try { + const response = await app.fetch(fetchReq); + res.statusCode = response.status; + response.headers.forEach((value: string, key: string) => { + res.setHeader(key, value); + }); + + if (response.body) { + const reader = response.body.getReader(); + const pump = async () => { + const { done, value } = await reader.read(); + if (done) { + res.end(); + return; + } + res.write(value); + await pump(); + }; + await pump(); + } else { + const body = await response.arrayBuffer(); + res.end(Buffer.from(body)); + } + } catch (err) { + logger.error("[Server] Error handling request:", err); + res.statusCode = 500; + res.end("Internal Server Error"); + } + }); + + server.listen(port, () => { + logger.info(`Host dev server running at http://localhost:${port}`); + logger.info(` http://localhost:${port}/api → REST API (OpenAPI docs)`); + logger.info(` http://localhost:${port}/api/rpc → RPC endpoint`); + onReady?.(); + }); + } else { + const hostname = process.env.HOST || "0.0.0.0"; + serve({ fetch: app.fetch, port, hostname }, (info: { port: number }) => { + logger.info(`Host production server running at http://${hostname}:${info.port}`); + logger.info(` http://${hostname}:${info.port}/api → REST API (OpenAPI docs)`); + logger.info(` http://${hostname}:${info.port}/api/rpc → RPC endpoint`); + onReady?.(); + }); + } + }; + + startHttpServer(); + + yield* Effect.fork( + Effect.gen(function* () { + const ssrUrl = config.ui.ssrUrl ?? config.ui.url; + logger.info(`[SSR] Loading Router module from ${ssrUrl}...`); + + const routerModuleResult = yield* loadRouterModule(config).pipe(Effect.either); + + if (routerModuleResult._tag === "Left") { + logger.error("[SSR] Failed to load Router module:", routerModuleResult.left); + logger.warn("[SSR] Server running in API-only mode, SSR disabled"); + return; + } + + ssrRouterModule = routerModuleResult.right; + logger.info("[SSR] Router module loaded successfully, SSR routes active"); + }) + ); + + yield* Effect.never; +}); + +export const startServer = createStartServer(); + +export const ServerLive = FullServerLive; + +export interface ServerHandle { + ready: Promise; + shutdown: () => Promise; +} + +export const runServer = (bootstrap?: BootstrapConfig): ServerHandle => { + if (bootstrap) { + setBootstrapConfig(bootstrap); + } + + let resolveReady: () => void; + let rejectReady: (err: unknown) => void; + + const ready = new Promise((resolve, reject) => { + resolveReady = resolve; + rejectReady = reject; + }); + + const runtime = ManagedRuntime.make(ServerLive); + + const shutdown = async () => { + console.log("[Server] Shutting down..."); + closeDatabase(); + await runtime.dispose(); + console.log("[Server] Shutdown complete"); + }; + + const serverEffect = createStartServer(() => resolveReady()); + + runtime.runPromise(serverEffect).catch((err) => { + console.error("Failed to start server:", err); + rejectReady(err); + }); + + return { ready, shutdown }; +}; + +export const runServerBlocking = async () => { + const handle = runServer(); + + process.on("SIGINT", () => void handle.shutdown().then(() => process.exit(0))); + process.on("SIGTERM", () => void handle.shutdown().then(() => process.exit(0))); + + try { + await handle.ready; + await new Promise(() => { }); + } catch (err) { + console.error("Failed to start server:", err); + process.exit(1); + } +}; diff --git a/ui/src/reportWebVitals.ts b/host/src/reportWebVitals.ts similarity index 100% rename from ui/src/reportWebVitals.ts rename to host/src/reportWebVitals.ts diff --git a/host/src/routers/index.ts b/host/src/routers/index.ts deleted file mode 100644 index 1a770d5..0000000 --- a/host/src/routers/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { RouterClient } from 'every-plugin/orpc'; -import { os } from 'every-plugin/orpc'; -import type { Plugins } from '../runtime'; - -export function createRouter(plugins: Plugins) { - const baseRouter = { - health: os.route({ method: 'GET', path: '/health' }).handler(() => 'OK'), - } as const; - - if (!plugins.status.available || !plugins.api?.router) { - console.warn( - '[Router] Plugin router not available, using base router only' - ); - return baseRouter; - } - - return { - ...baseRouter, - ...plugins.api.router, - } as const; -} - -export type AppRouter = ReturnType; -export type AppRouterClient = RouterClient; diff --git a/host/src/runtime.ts b/host/src/runtime.ts deleted file mode 100644 index 8965522..0000000 --- a/host/src/runtime.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { createPluginRuntime } from 'every-plugin'; -import { loadBosConfig } from './config'; - -export interface PluginStatus { - available: boolean; - pluginName: string | null; - error: string | null; - errorDetails: string | null; -} - -function secretsFromEnv(keys: string[]): Record { - const out: Record = {}; - for (const k of keys) { - const v = process.env[k]; - if (typeof v === "string" && v.length > 0) out[k] = v; - } - return out; -} - -export interface PluginResult { - runtime: ReturnType | null; - api: any | null; // Plugin types loaded dynamically - status: PluginStatus; -} - -export async function initializePlugins(): Promise { - let pluginName: string | null = null; - let pluginUrl: string | null = null; - - try { - const config = await loadBosConfig(); - const pluginConfig = config.api; - pluginName = pluginConfig.name; - pluginUrl = pluginConfig.url; - - console.log(`[Plugins] Registering remote: ${pluginName} from ${pluginUrl}`); - - const runtime = createPluginRuntime({ - registry: { - [pluginName]: { - remote: pluginUrl, - }, - }, - secrets: {}, - }); - - const secrets = pluginConfig.secrets - ? secretsFromEnv(pluginConfig.secrets) - : {}; - const variables = pluginConfig.variables ?? {}; - - const api = await runtime.usePlugin(pluginName, { - // @ts-expect-error no plugin types loaded - variables, - // @ts-expect-error no plugin types loaded - secrets, - }); - - return { - runtime, - api, - status: { - available: true, - pluginName, - error: null, - errorDetails: null, - }, - }; - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - const errorStack = error instanceof Error ? error.stack : undefined; - - console.error('[Plugins] ❌ Failed to initialize plugin'); - - if (errorMessage.includes('register-remote') || errorStack?.includes('register-remote')) { - console.error(`[Plugins] Failed to register remote plugin: ${pluginName}`); - console.error(`[Plugins] Remote URL: ${pluginUrl}`); - console.error('[Plugins] Possible causes:'); - console.error(' • API server is not running at the configured URL'); - console.error(' • Wrong URL in bos.config.json'); - console.error(' • Network connectivity issue'); - console.error(' • CORS configuration problem'); - console.error(`[Plugins] Error: ${errorMessage}`); - } else if (errorMessage.includes('validation') || errorMessage.includes('ZodError')) { - console.error('[Plugins] Configuration validation failed'); - console.error('[Plugins] Check that all required secrets are set in your environment variables'); - console.error(`[Plugins] Error: ${errorMessage}`); - } else if (errorMessage.includes('ENOTDIR') || errorMessage.includes('ENOENT')) { - console.error('[Plugins] Plugin file not found - ensure API is running and built'); - console.error(`[Plugins] Attempted URL: ${pluginUrl}`); - console.error(`[Plugins] Error: ${errorMessage}`); - } else if (errorMessage.includes('fetch') || errorMessage.includes('network')) { - console.error('[Plugins] Network error - ensure API server is running at the configured URL'); - console.error(`[Plugins] URL: ${pluginUrl}`); - console.error(`[Plugins] Error: ${errorMessage}`); - } else { - console.error(`[Plugins] Plugin: ${pluginName}`); - console.error(`[Plugins] URL: ${pluginUrl}`); - console.error(`[Plugins] Error: ${errorMessage}`); - } - - console.warn('[Plugins] Server will continue without plugin functionality'); - - return { - runtime: null, - api: null, - status: { - available: false, - pluginName, - error: errorMessage, - errorDetails: errorStack ?? null, - }, - }; - } -} - -export type Plugins = Awaited>; diff --git a/host/src/scripts/promote-admin.ts b/host/src/scripts/promote-admin.ts deleted file mode 100644 index 83e448a..0000000 --- a/host/src/scripts/promote-admin.ts +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Promote User to Admin - * - * Usage: bun run promote-admin - * Example: bun run promote-admin alice.near - */ - -import { db } from '../db'; -import { user, nearAccount } from '../db/schema/auth'; -import { eq } from 'drizzle-orm'; - -async function promoteToAdmin(nearAccountId: string) { - // Find user by NEAR account ID - const account = await db.query.nearAccount.findFirst({ - where: eq(nearAccount.accountId, nearAccountId), - }); - - if (!account) { - console.error(`❌ No user found with NEAR account: ${nearAccountId}`); - process.exit(1); - } - - // Update user role - const result = await db - .update(user) - .set({ role: 'admin' }) - .where(eq(user.id, account.userId)) - .returning(); - - if (result.length > 0) { - console.log(`✅ Promoted ${nearAccountId} to admin`); - console.log(` User ID: ${result[0].id}`); - console.log(` Email: ${result[0].email}`); - } else { - console.error(`❌ Failed to promote user`); - process.exit(1); - } -} - -const nearAccountId = process.argv[2]; -if (!nearAccountId) { - console.error('Usage: bun run promote-admin '); - process.exit(1); -} - -promoteToAdmin(nearAccountId) - .then(() => process.exit(0)) - .catch((err) => { - console.error('Error:', err); - process.exit(1); - }); diff --git a/host/src/services/auth.ts b/host/src/services/auth.ts new file mode 100644 index 0000000..a527244 --- /dev/null +++ b/host/src/services/auth.ts @@ -0,0 +1,62 @@ +import { betterAuth } from "better-auth"; +import { drizzleAdapter } from "better-auth/adapters/drizzle"; +import { admin } from "better-auth/plugins"; +import { siwn } from "better-near-auth"; +import { Context, Effect, Layer } from "every-plugin/effect"; +import * as schema from "../db/schema/auth"; +import { ConfigService } from "./config"; +import { DatabaseService } from "./database"; + +export type Auth = ReturnType; + +export const createAuth = Effect.gen(function* () { + const config = yield* ConfigService; + const db = yield* DatabaseService; + + return betterAuth({ + database: drizzleAdapter(db, { + provider: "sqlite", + schema: schema, + }), + trustedOrigins: process.env.CORS_ORIGIN?.split(",") || ["*"], + secret: process.env.BETTER_AUTH_SECRET || "default-secret-change-in-production", + baseURL: process.env.BETTER_AUTH_URL, + plugins: [ + siwn({ + recipient: config.account, + }), + admin({ + defaultRole: "user", + adminRoles: ["admin"], + }), + ], + account: { + accountLinking: { + enabled: true, + trustedProviders: ["siwn"], + allowDifferentEmails: true, + updateUserInfoOnLink: true, + }, + }, + session: { + cookieCache: { + enabled: process.env.NODE_ENV === "production", + maxAge: 5 * 60 // 5 minutes cache - reduces DB hits + } + }, + advanced: { + defaultCookieAttributes: { + sameSite: "lax", + secure: process.env.NODE_ENV === "production", + httpOnly: true + } + }, + }); +}); + +export class AuthService extends Context.Tag("host/AuthService")() { + static Default = Layer.effect(AuthService, createAuth).pipe( + Layer.provide(ConfigService.Default), + Layer.provide(DatabaseService.Default) + ); +} diff --git a/host/src/services/config.ts b/host/src/services/config.ts new file mode 100644 index 0000000..d24980f --- /dev/null +++ b/host/src/services/config.ts @@ -0,0 +1,194 @@ +import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; +import { Effect } from "every-plugin/effect"; +import { ConfigError } from "./errors"; + +export interface BootstrapConfig { + configPath?: string; + secrets?: Record; + host?: { url?: string }; + ui?: { source?: SourceMode }; + api?: { source?: SourceMode; proxy?: string }; + database?: { url?: string }; + gatewayConfig?: BosConfig; + gatewaySecrets?: Record; +} + +let globalBootstrap: BootstrapConfig | undefined; + +export function setBootstrapConfig(config: BootstrapConfig): void { + globalBootstrap = config; +} + +export interface BosConfig { + account: string; + gateway?: string; + app: { + host: { + title: string; + description?: string; + development: string; + production: string; + secrets?: string[]; + }; + ui: { + name: string; + development: string; + production: string; + ssr?: string; + exposes: Record; + }; + api: { + name: string; + development: string; + production: string; + variables?: Record; + secrets?: string[]; + }; + }; +} + +export type SourceMode = "local" | "remote"; + +export interface RuntimeConfig { + env: "development" | "production"; + account: string; + title: string; + hostUrl: string; + ui: { + name: string; + url: string; + ssrUrl?: string; + source: SourceMode; + exposes: Record; + }; + api: { + name: string; + url: string; + source: SourceMode; + proxy?: string; + variables?: Record; + secrets?: string[]; + }; +} + +export type ClientRuntimeConfig = Pick & { + assetsUrl: string; + apiBase: string; + rpcBase: string; +}; + +export type WindowRuntimeConfig = Pick & { + ui: Pick; + apiBase: string; + rpcBase: string; +}; + +function resolveSource( + bootstrapSource: SourceMode | undefined, + envVar: string | undefined, + env: string +): SourceMode { + if (bootstrapSource) return bootstrapSource; + if (envVar === "local" || envVar === "remote") return envVar; + return env === "production" ? "remote" : "local"; +} + +function loadConfigFromGateway( + gatewayConfig: BosConfig, + gatewaySecrets: Record | undefined, + env: "development" | "production" +): RuntimeConfig { + if (gatewaySecrets) { + for (const [key, value] of Object.entries(gatewaySecrets)) { + process.env[key] = value; + } + } + + return { + env, + account: gatewayConfig.account, + title: gatewayConfig.app.host.title, + hostUrl: gatewayConfig.app.host.production, + ui: { + name: gatewayConfig.app.ui.name, + url: gatewayConfig.app.ui.production, + ssrUrl: gatewayConfig.app.ui.ssr || undefined, + source: "remote", + exposes: gatewayConfig.app.ui.exposes, + }, + api: { + name: gatewayConfig.app.api.name, + url: gatewayConfig.app.api.production, + source: "remote", + proxy: undefined, + variables: gatewayConfig.app.api.variables, + secrets: gatewayConfig.app.api.secrets, + }, + }; +} + +export const loadConfig = Effect.gen(function* () { + const bootstrap = globalBootstrap; + const env = (process.env.NODE_ENV as "development" | "production") || "development"; + + if (bootstrap?.gatewayConfig) { + return loadConfigFromGateway(bootstrap.gatewayConfig, bootstrap.gatewaySecrets, env); + } + + const path = bootstrap?.configPath ?? process.env.BOS_CONFIG_PATH ?? resolve(process.cwd(), "bos.config.json"); + + if (bootstrap?.secrets) { + for (const [key, value] of Object.entries(bootstrap.secrets)) { + process.env[key] = value; + } + } + + const raw = yield* Effect.tryPromise({ + try: () => readFile(path, "utf8"), + catch: (e) => new ConfigError({ path, cause: e }), + }); + + const config = yield* Effect.try({ + try: () => JSON.parse(raw) as BosConfig, + catch: (e) => new ConfigError({ path, cause: e }), + }); + + const uiSource = resolveSource(bootstrap?.ui?.source, process.env.UI_SOURCE, env); + const apiSource = resolveSource(bootstrap?.api?.source, process.env.API_SOURCE, env); + + const apiProxyEnv = bootstrap?.api?.proxy ?? process.env.API_PROXY; + const apiProxy = apiProxyEnv === "true" ? config.app.host.production : apiProxyEnv || undefined; + + const uiUrl = uiSource === "remote" ? config.app.ui.production : config.app.ui.development; + const apiUrl = apiSource === "remote" ? config.app.api.production : config.app.api.development; + const ssrUrl = config.app.ui.ssr || undefined; + + return { + env, + account: config.account, + title: config.app.host.title, + hostUrl: bootstrap?.host?.url ?? config.app.host[env], + ui: { + name: config.app.ui.name, + url: uiUrl, + ssrUrl, + source: uiSource, + exposes: config.app.ui.exposes, + }, + api: { + name: config.app.api.name, + url: apiUrl, + source: apiSource, + proxy: apiProxy, + variables: config.app.api.variables, + secrets: config.app.api.secrets, + }, + } satisfies RuntimeConfig; +}); + +export class ConfigService extends Effect.Service()("host/ConfigService", { + effect: loadConfig, +}) { } + +export const loadBosConfig = (): Promise => Effect.runPromise(loadConfig); diff --git a/host/src/services/context.ts b/host/src/services/context.ts new file mode 100644 index 0000000..f1ec007 --- /dev/null +++ b/host/src/services/context.ts @@ -0,0 +1,35 @@ +import { eq } from "drizzle-orm"; +import * as schema from "../db/schema/auth"; +import type { Auth } from "./auth"; +import type { Database } from "./database"; + +type SessionResult = Awaited>; +type User = NonNullable["user"]; + +export interface RequestContext { + session: SessionResult; + user: User | null; + nearAccountId: string | null; +} + +export async function createRequestContext( + req: Request, + auth: Auth, + db: Database +): Promise { + const session = await auth.api.getSession({ headers: req.headers }); + + let nearAccountId: string | null = null; + if (session?.user?.id) { + const nearAccount = await db.query.nearAccount.findFirst({ + where: eq(schema.nearAccount.userId, session.user.id), + }); + nearAccountId = nearAccount?.accountId ?? null; + } + + return { + session, + user: session?.user ?? null, + nearAccountId, + }; +} diff --git a/host/src/services/database.ts b/host/src/services/database.ts new file mode 100644 index 0000000..b944eff --- /dev/null +++ b/host/src/services/database.ts @@ -0,0 +1,53 @@ +import { type Client, createClient } from "@libsql/client"; +import { drizzle, type LibSQLDatabase } from "drizzle-orm/libsql"; +import { Effect } from "every-plugin/effect"; +import * as authSchema from "../db/schema/auth"; +import { DatabaseError } from "./errors"; + +type Schema = typeof authSchema; + +export interface DatabaseClient { + db: LibSQLDatabase; + client: Client; +} + +let activeClient: Client | null = null; + +const acquireDatabase = Effect.try({ + try: (): LibSQLDatabase => { + const client = createClient({ + url: process.env.HOST_DATABASE_URL || "file:./database.db", + authToken: process.env.HOST_DATABASE_AUTH_TOKEN, + }); + + activeClient = client; + + const db = drizzle(client, { + schema: { + ...authSchema, + }, + }); + + return db; + }, + catch: (e) => new DatabaseError({ cause: e }), +}); + +export const closeDatabase = (): void => { + if (activeClient) { + try { + activeClient.close(); + console.log("[Database] Connection closed"); + } catch { + } + activeClient = null; + } +}; + +export const createDatabase = acquireDatabase; + +export type Database = LibSQLDatabase; + +export class DatabaseService extends Effect.Service()("host/DatabaseService", { + effect: createDatabase, +}) {} diff --git a/host/src/services/errors.ts b/host/src/services/errors.ts new file mode 100644 index 0000000..4195544 --- /dev/null +++ b/host/src/services/errors.ts @@ -0,0 +1,26 @@ +import { Data } from "every-plugin/effect"; + +export class ConfigError extends Data.TaggedError("ConfigError")<{ + readonly path?: string; + readonly cause?: unknown; +}> {} + +export class DatabaseError extends Data.TaggedError("DatabaseError")<{ + readonly cause?: unknown; +}> {} + +export class FederationError extends Data.TaggedError("FederationError")<{ + readonly remoteName: string; + readonly remoteUrl?: string; + readonly cause?: unknown; +}> {} + +export class PluginError extends Data.TaggedError("PluginError")<{ + readonly pluginName?: string; + readonly pluginUrl?: string; + readonly cause?: unknown; +}> {} + +export class ServerError extends Data.TaggedError("ServerError")<{ + readonly cause?: unknown; +}> {} diff --git a/host/src/services/federation.server.ts b/host/src/services/federation.server.ts new file mode 100644 index 0000000..94aa9e9 --- /dev/null +++ b/host/src/services/federation.server.ts @@ -0,0 +1,99 @@ +import { createInstance, getInstance } from "@module-federation/enhanced/runtime"; +import { setGlobalFederationInstance } from "@module-federation/runtime-core"; +import { Context, Effect, Layer, Schedule } from "every-plugin/effect"; +import type { RouterModule } from "../types"; +import type { RuntimeConfig } from "./config"; +import { ConfigService } from "./config"; +import { FederationError } from "./errors"; + +export type { RouterModule }; + +let federationInstance: ReturnType | null = null; + +function getOrCreateFederationInstance(config: RuntimeConfig) { + if (federationInstance) return federationInstance; + + const existingInstance = getInstance(); + + const ssrEntryUrl = config.ui.ssrUrl + ? `${config.ui.ssrUrl}/remoteEntry.server.js` + : `${config.ui.url}/remoteEntry.server.js`; + + if (!ssrEntryUrl) { + throw new FederationError({ + remoteName: config.ui.name, + cause: new Error("SSR URL not configured. Set app.ui.ssr in bos.config.json to enable SSR."), + }); + } + + if (existingInstance) { + existingInstance.registerRemotes([{ + name: config.ui.name, + entry: ssrEntryUrl, + alias: config.ui.name, + }]); + federationInstance = existingInstance; + return federationInstance; + } + + federationInstance = createInstance({ + name: "host", + remotes: [ + { + name: config.ui.name, + entry: ssrEntryUrl, + alias: config.ui.name, + }, + ], + }); + + setGlobalFederationInstance(federationInstance); + return federationInstance; +} + +const isDev = process.env.NODE_ENV !== "production"; + +const retrySchedule = Schedule.exponential("500 millis").pipe( + Schedule.compose(Schedule.recurs(isDev ? 15 : 3)), + Schedule.tapOutput((count: number) => + Effect.logInfo(`[Federation] Retry attempt ${count + 1}...`) + ) +); + +export const loadRouterModule = (config: RuntimeConfig) => + Effect.tryPromise({ + try: async () => { + const mf = getOrCreateFederationInstance(config); + const routerModule = await mf.loadRemote(`${config.ui.name}/Router`); + + if (!routerModule) { + throw new Error(`Failed to load Router module from ${config.ui.name}`); + } + + return routerModule; + }, + catch: (e) => + new FederationError({ + remoteName: config.ui.name, + remoteUrl: config.ui.ssrUrl, + cause: e, + }), + }).pipe( + Effect.retry(retrySchedule), + Effect.tapError((e) => + Effect.logError(`[Federation] Failed to load Router module after retries: ${e.message}`) + ) + ); + +export class FederationServerService extends Context.Tag("host/FederationServerService")< + FederationServerService, + RouterModule +>() { + static Live = Layer.effect( + FederationServerService, + Effect.gen(function* () { + const config = yield* ConfigService; + return yield* loadRouterModule(config); + }) + ).pipe(Layer.provide(ConfigService.Default)); +} diff --git a/host/src/services/plugins.ts b/host/src/services/plugins.ts new file mode 100644 index 0000000..c76fb33 --- /dev/null +++ b/host/src/services/plugins.ts @@ -0,0 +1,125 @@ +import { Context, Effect, Layer } from "every-plugin/effect"; +import { createPluginRuntime } from "every-plugin"; +import { ConfigService } from "./config"; +import { PluginError } from "./errors"; + +export interface PluginStatus { + available: boolean; + pluginName: string | null; + error: string | null; + errorDetails: string | null; +} + +export interface PluginResult { + runtime: ReturnType | null; + api: unknown; + status: PluginStatus; +} + +function secretsFromEnv(keys: string[]): Record { + const out: Record = {}; + for (const k of keys) { + const v = process.env[k]; + if (typeof v === "string" && v.length > 0) out[k] = v; + } + return out; +} + +const unavailableResult = ( + pluginName: string | null, + error: string | null, + errorDetails: string | null +): PluginResult => ({ + runtime: null, + api: null, + status: { available: false, pluginName, error, errorDetails }, +}); + +export const initializePlugins = Effect.gen(function* () { + const config = yield* ConfigService; + const pluginConfig = config.api; + const pluginName = pluginConfig.name; + const pluginUrl = pluginConfig.url; + + console.log(`[Plugins] Registering remote: ${pluginName} from ${pluginUrl}`); + + const result = yield* Effect.tryPromise({ + try: async () => { + const runtime = createPluginRuntime({ + registry: { + [pluginName]: { + remote: pluginUrl, + }, + }, + secrets: {}, + }); + + const secrets = pluginConfig.secrets ? secretsFromEnv(pluginConfig.secrets) : {}; + const variables = pluginConfig.variables ?? {}; + + const api = await runtime.usePlugin(pluginName, { + // @ts-expect-error no plugin types loaded + variables, + // @ts-expect-error no plugin types loaded + secrets, + }); + + return { + runtime, + api, + status: { + available: true, + pluginName, + error: null, + errorDetails: null, + }, + } satisfies PluginResult; + }, + catch: (error) => + new PluginError({ + pluginName, + pluginUrl, + cause: error, + }), + }); + + return result; +}).pipe( + Effect.catchAll((error) => { + const pluginName = error instanceof PluginError ? error.pluginName : null; + const pluginUrl = error instanceof PluginError ? error.pluginUrl : null; + const errorMessage = error instanceof Error ? error.message : String(error); + const errorStack = error instanceof Error ? error.stack : undefined; + + console.error("[Plugins] ❌ Failed to initialize plugin"); + console.error(`[Plugins] Plugin: ${pluginName}`); + console.error(`[Plugins] URL: ${pluginUrl}`); + console.error(`[Plugins] Error: ${errorMessage}`); + console.warn("[Plugins] Server will continue without plugin functionality"); + + return Effect.succeed(unavailableResult(pluginName ?? null, errorMessage, errorStack ?? null)); + }) +); + +export class PluginsService extends Context.Tag("host/PluginsService")< + PluginsService, + PluginResult +>() { + static Live = Layer.scoped( + PluginsService, + Effect.gen(function* () { + const plugins = yield* initializePlugins; + + yield* Effect.addFinalizer(() => + Effect.sync(() => { + if (plugins.runtime) { + console.log("[Plugins] Shutting down plugin runtime..."); + plugins.runtime.shutdown(); + } + }) + ); + + return plugins; + }) + ).pipe(Layer.provide(ConfigService.Default)); +} diff --git a/host/src/services/router.ts b/host/src/services/router.ts new file mode 100644 index 0000000..30ef21d --- /dev/null +++ b/host/src/services/router.ts @@ -0,0 +1,28 @@ +import type { RouterClient } from "every-plugin/orpc"; +import { os } from "every-plugin/orpc"; +import type { PluginResult } from "./plugins"; + +export function createRouter(plugins: PluginResult) { + const baseRouter = { + health: os.route({ method: "GET", path: "/health" }).handler(() => "OK"), + } as const; + + if (!plugins.status.available || !plugins.api) { + console.warn("[Router] Plugin router not available, using base router only"); + return baseRouter; + } + + const pluginApi = plugins.api as { router?: Record }; + if (!pluginApi.router) { + console.warn("[Router] Plugin API has no router, using base router only"); + return baseRouter; + } + + return { + ...baseRouter, + ...pluginApi.router, + } as const; +} + +export type AppRouter = ReturnType; +export type AppRouterClient = RouterClient; diff --git a/host/src/ssr.tsx b/host/src/ssr.tsx deleted file mode 100644 index 21638d7..0000000 --- a/host/src/ssr.tsx +++ /dev/null @@ -1,254 +0,0 @@ -import { createElement } from "react"; -import { renderToReadableStream } from "react-dom/server"; -import { RouterProvider } from "@tanstack/react-router"; -import { createMemoryHistory } from "@tanstack/react-router"; -import type { AnyRouter } from "@tanstack/react-router"; -import { - QueryClientProvider, - dehydrate, - type QueryClient, -} from "@tanstack/react-query"; -import { loadRemoteModule } from "./federation.server"; -import type { RuntimeConfig } from "./config"; - -interface CreateRouterResult { - router: AnyRouter; - queryClient: QueryClient; -} - -interface RouterModule { - createRouter: (opts?: { - context?: { queryClient?: QueryClient }; - }) => CreateRouterResult; -} - -export interface SSRRenderOptions { - url: string; - config: RuntimeConfig; -} - -export interface HeadMeta { - title?: string; - name?: string; - property?: string; - content?: string; - charSet?: string; -} - -export interface HeadLink { - rel: string; - href: string; - type?: string; - sizes?: string; - crossorigin?: string; -} - -export interface HeadData { - meta?: HeadMeta[]; - links?: HeadLink[]; -} - -export interface SSRRenderResult { - stream: ReadableStream; - dehydratedState: unknown; - headData: HeadData; -} - -function safeJsonStringify(value: unknown): string { - return JSON.stringify(value) - .replace(//g, "\\u003e") - .replace(/&/g, "\\u0026") - .replace(/\u2028/g, "\\u2028") - .replace(/\u2029/g, "\\u2029"); -} - -function extractHeadData(router: AnyRouter): HeadData { - const meta: HeadMeta[] = []; - const links: HeadLink[] = []; - - try { - const matches = router.state?.matches || []; - - for (const match of matches) { - const route = router.routesById?.[match.routeId]; - const headFn = route?.options?.head; - if (typeof headFn === "function") { - const headResult = headFn({ - params: match.params, - loaderData: match.loaderData, - }); - - if (headResult?.meta) { - meta.push(...headResult.meta); - } - if (headResult?.links) { - links.push(...headResult.links); - } - } - } - } catch (error) { - console.error("[SSR] Failed to extract head data:", error); - } - - return { meta, links }; -} - -export async function renderToStream( - options: SSRRenderOptions -): Promise { - const { url, config } = options; - - const routerModule = await loadRemoteModule( - config.ui.name, - "Router" - ); - const { router, queryClient } = routerModule.createRouter(); - - const memoryHistory = createMemoryHistory({ - initialEntries: [url], - }); - - router.update({ history: memoryHistory }); - - await router.load(); - - const headData = extractHeadData(router); - - const App = createElement( - QueryClientProvider, - { client: queryClient }, - createElement(RouterProvider, { router }) - ); - - const stream = await renderToReadableStream(App, { - onError(error) { - console.error("[SSR] Render error:", error); - }, - }); - - const dehydratedState = dehydrate(queryClient); - - return { stream, dehydratedState, headData }; -} - -function getUiOrigin(url: string): string { - try { - return new URL(url).origin; - } catch { - return url; - } -} - -function renderMetaTags(headData: HeadData): { title: string; tags: string } { - const tags: string[] = []; - let title = ""; - - if (headData.meta) { - for (const meta of headData.meta) { - if (meta.title) { - title = meta.title; - continue; - } - - const attrs: string[] = []; - if (meta.name) attrs.push(`name="${meta.name}"`); - if (meta.property) attrs.push(`property="${meta.property}"`); - if (meta.content) - attrs.push(`content="${meta.content.replace(/"/g, """)}"`); - if (meta.charSet) attrs.push(`charset="${meta.charSet}"`); - - if (attrs.length > 0) { - tags.push(` `); - } - } - } - - if (headData.links) { - for (const link of headData.links) { - const attrs: string[] = [`rel="${link.rel}"`, `href="${link.href}"`]; - if (link.type) attrs.push(`type="${link.type}"`); - if (link.sizes) attrs.push(`sizes="${link.sizes}"`); - if (link.crossorigin) attrs.push(`crossorigin="${link.crossorigin}"`); - - tags.push(` `); - } - } - - return { title, tags: tags.join("\n") }; -} - -export function createSSRHtml( - bodyContent: string, - dehydratedState: unknown, - config: RuntimeConfig, - headData?: HeadData -): string { - const clientConfig = { - env: config.env, - title: config.title, - hostUrl: config.hostUrl, - ui: config.ui, - apiBase: "/api", - rpcBase: "/api/rpc", - }; - - const uiOrigin = getUiOrigin(config.ui.url); - - const { title, tags } = headData - ? renderMetaTags(headData) - : { title: config.title, tags: "" }; - - const pageTitle = title || config.title; - const serializedConfig = safeJsonStringify(clientConfig); - const serializedState = safeJsonStringify(dehydratedState); - - return ` - - - - - - - ${pageTitle} - - - - - - - - -${tags} - - - - - - - - - - - -
${bodyContent}
- - -`; -} diff --git a/host/src/types.ts b/host/src/types.ts new file mode 100644 index 0000000..f6b21e8 --- /dev/null +++ b/host/src/types.ts @@ -0,0 +1,17 @@ +export type { + CreateRouterOptions, + HeadData, + HeadLink, + HeadMeta, + HeadScript, + RenderOptions, + RenderResult, + RouterContext, + RouterModule, +} from "../../ui/src/types"; +export type { + ClientRuntimeConfig, + RuntimeConfig, + SourceMode, + WindowRuntimeConfig, +} from "./services/config"; diff --git a/host/src/ui.tsx b/host/src/ui.tsx index 8d5dc71..d3755a7 100644 --- a/host/src/ui.tsx +++ b/host/src/ui.tsx @@ -201,10 +201,12 @@ export const Loading: FC = () => ( style={{ width: "100%", height: "100%", + minHeight: "100vh", display: "flex", alignItems: "center", justifyContent: "center", - opacity: 0.7, + backgroundColor: "var(--host-bg, #ffffff)", + transition: "background-color 0.2s ease", }} /> ); diff --git a/host/src/utils/logger.ts b/host/src/utils/logger.ts new file mode 100644 index 0000000..897864b --- /dev/null +++ b/host/src/utils/logger.ts @@ -0,0 +1,7 @@ +import { Effect } from "every-plugin/effect" + +export const logger = { + info: (...args: unknown[]) => Effect.runSync(Effect.logInfo(...args)), + warn: (...args: unknown[]) => Effect.runSync(Effect.logWarning(...args)), + error: (...args: unknown[]) => Effect.runSync(Effect.logError(...args)), +} diff --git a/host/tests/integration/seo.test.ts b/host/tests/integration/seo.test.ts new file mode 100644 index 0000000..9e3d6c8 --- /dev/null +++ b/host/tests/integration/seo.test.ts @@ -0,0 +1,518 @@ +import { loadBosConfig, type RuntimeConfig } from "@/services/config"; +import { loadRouterModule } from "@/services/federation.server"; +import type { HeadData, RouterModule } from "@/types"; +import { Effect } from "every-plugin/effect"; +import { beforeAll, describe, expect, it, vi } from "vitest"; + +declare global { + var $apiClient: typeof mockApiClient; +} + +const mockApiClient = { + getValue: vi.fn().mockImplementation(({ key }: { key: string }) => + Promise.resolve({ key, value: `test-value-for-${key}` }) + ), + setValue: vi.fn().mockResolvedValue({ success: true }), + protected: vi.fn().mockResolvedValue({ message: "Protected data" }), +}; + +function escapeHtml(str: string): string { + return str + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """); +} + +function renderHeadToString(head: HeadData): string { + const parts: string[] = []; + + for (const meta of head.meta) { + if (!meta) continue; + const metaObj = meta as Record; + if ("title" in metaObj && metaObj.title) { + parts.push(`${escapeHtml(String(metaObj.title))}`); + } else { + const attrs = Object.entries(metaObj) + .filter(([k, v]) => k !== "children" && v !== undefined) + .map(([k, v]) => `${k}="${escapeHtml(String(v))}"`) + .join(" "); + if (attrs) parts.push(``); + } + } + + for (const link of head.links) { + if (!link) continue; + const linkObj = link as Record; + const attrs = Object.entries(linkObj) + .filter(([, v]) => v !== undefined) + .map(([k, v]) => `${k}="${escapeHtml(String(v))}"`) + .join(" "); + if (attrs) parts.push(``); + } + + for (const script of head.scripts) { + if (!script) continue; + const scriptObj = script as Record; + const { children, ...rest } = scriptObj; + const attrs = Object.entries(rest) + .filter(([, v]) => v !== undefined) + .map(([k, v]) => + typeof v === "boolean" ? (v ? k : "") : `${k}="${escapeHtml(String(v))}"` + ) + .filter(Boolean) + .join(" "); + if (children) { + parts.push(``); + } else if (attrs) { + parts.push(``); + } + } + + return parts.join("\n"); +} + +describe("SEO Head Extraction", () => { + let routerModule: RouterModule; + let config: RuntimeConfig; + + beforeAll(async () => { + globalThis.$apiClient = mockApiClient; + + config = await loadBosConfig(); + routerModule = await Effect.runPromise(loadRouterModule(config)); + }); + + describe("Module Federation", () => { + it("loads RouterModule from production SSR remote", () => { + expect(routerModule).toBeDefined(); + expect(routerModule.getRouteHead).toBeTypeOf("function"); + expect(routerModule.createRouter).toBeTypeOf("function"); + expect(routerModule.routeTree).toBeDefined(); + }); + + }); + + describe("Root Route (/)", () => { + let head: HeadData; + + beforeAll(async () => { + head = await routerModule.getRouteHead("/", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + }); + + it("returns HeadData structure", () => { + expect(head).toHaveProperty("meta"); + expect(head).toHaveProperty("links"); + expect(head).toHaveProperty("scripts"); + expect(Array.isArray(head.meta)).toBe(true); + expect(Array.isArray(head.links)).toBe(true); + expect(Array.isArray(head.scripts)).toBe(true); + }); + + it("has title meta tag", () => { + const titleMeta = head.meta.find( + (m) => m && typeof m === "object" && "title" in m + ); + expect(titleMeta).toBeDefined(); + expect((titleMeta as { title: string }).title).toBeTruthy(); + }); + + it("has charset meta tag", () => { + const charsetMeta = head.meta.find( + (m) => m && typeof m === "object" && "charSet" in m + ); + expect(charsetMeta).toBeDefined(); + expect((charsetMeta as { charSet: string }).charSet).toBe("utf-8"); + }); + + it("has viewport meta tag", () => { + const viewportMeta = head.meta.find( + (m) => m && typeof m === "object" && "name" in m && (m as { name: string }).name === "viewport" + ); + expect(viewportMeta).toBeDefined(); + }); + + it("has description meta tag", () => { + const descMeta = head.meta.find( + (m) => + m && + typeof m === "object" && + "name" in m && + (m as { name: string }).name === "description" + ); + expect(descMeta).toBeDefined(); + expect((descMeta as { content: string }).content).toBeTruthy(); + }); + + it("has Open Graph tags", () => { + const ogTitle = head.meta.find( + (m) => + m && + typeof m === "object" && + "property" in m && + (m as { property: string }).property === "og:title" + ); + const ogDescription = head.meta.find( + (m) => + m && + typeof m === "object" && + "property" in m && + (m as { property: string }).property === "og:description" + ); + const ogType = head.meta.find( + (m) => + m && + typeof m === "object" && + "property" in m && + (m as { property: string }).property === "og:type" + ); + + expect(ogTitle).toBeDefined(); + expect(ogDescription).toBeDefined(); + expect(ogType).toBeDefined(); + }); + + it("has Twitter Card tags", () => { + const twitterCard = head.meta.find( + (m) => + m && + typeof m === "object" && + "name" in m && + (m as { name: string }).name === "twitter:card" + ); + const twitterTitle = head.meta.find( + (m) => + m && + typeof m === "object" && + "name" in m && + (m as { name: string }).name === "twitter:title" + ); + + expect(twitterCard).toBeDefined(); + expect(twitterTitle).toBeDefined(); + }); + + it("has canonical link", () => { + const canonical = head.links.find( + (l) => + l && typeof l === "object" && "rel" in l && (l as { rel: string }).rel === "canonical" + ); + expect(canonical).toBeDefined(); + }); + + it("has structured data script", () => { + const jsonLd = head.scripts.find( + (s) => + s && + typeof s === "object" && + "type" in s && + (s as { type: string }).type === "application/ld+json" + ); + expect(jsonLd).toBeDefined(); + + const scriptObj = jsonLd as { children?: string }; + if (scriptObj.children) { + const parsed = JSON.parse(scriptObj.children); + expect(parsed["@context"]).toBe("https://schema.org"); + expect(parsed["@type"]).toBe("WebSite"); + } + }); + }); + + describe("Dynamic Route (/keys/:key)", () => { + const testKey = "my-test-key-123"; + + it("includes key param in title", async () => { + const head = await routerModule.getRouteHead(`/keys/${testKey}`, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const titleMeta = head.meta.find( + (m) => m && typeof m === "object" && "title" in m + ); + expect(titleMeta).toBeDefined(); + expect((titleMeta as { title: string }).title).toContain(testKey); + }); + + it("includes key param in og:title", async () => { + const head = await routerModule.getRouteHead(`/keys/${testKey}`, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const ogTitle = head.meta.find( + (m) => + m && + typeof m === "object" && + "property" in m && + (m as { property: string }).property === "og:title" + ); + expect(ogTitle).toBeDefined(); + expect((ogTitle as { content: string }).content).toContain(testKey); + }); + + it("includes key param in description", async () => { + const head = await routerModule.getRouteHead(`/keys/${testKey}`, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const descMeta = head.meta.find( + (m) => + m && + typeof m === "object" && + "name" in m && + (m as { name: string }).name === "description" + ); + expect(descMeta).toBeDefined(); + expect((descMeta as { content: string }).content).toContain(testKey); + }); + + it("works with different key values", async () => { + const keys = ["foo", "bar-baz", "test_key", "KEY123"]; + + for (const key of keys) { + const head = await routerModule.getRouteHead(`/keys/${key}`, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const titleMeta = head.meta.find( + (m) => m && typeof m === "object" && "title" in m + ); + expect((titleMeta as { title: string }).title).toContain(key); + } + }); + + it("includes og:image meta tag", async () => { + const head = await routerModule.getRouteHead(`/keys/${testKey}`, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const ogImage = head.meta.find( + (m) => + m && + typeof m === "object" && + "property" in m && + (m as { property: string }).property === "og:image" + ); + expect(ogImage).toBeDefined(); + expect((ogImage as { content: string }).content).toBeTruthy(); + expect((ogImage as { content: string }).content).toContain("data:image/svg+xml;base64,"); + }); + + it("includes twitter:image meta tag", async () => { + const head = await routerModule.getRouteHead(`/keys/${testKey}`, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const twitterImage = head.meta.find( + (m) => + m && + typeof m === "object" && + "name" in m && + (m as { name: string }).name === "twitter:image" + ); + expect(twitterImage).toBeDefined(); + expect((twitterImage as { content: string }).content).toBeTruthy(); + expect((twitterImage as { content: string }).content).toContain("data:image/svg+xml;base64,"); + }); + + it("generates valid SVG data URL for og:image", async () => { + const head = await routerModule.getRouteHead(`/keys/${testKey}`, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const ogImage = head.meta.find( + (m) => + m && + typeof m === "object" && + "property" in m && + (m as { property: string }).property === "og:image" + ); + const content = (ogImage as { content: string }).content; + const base64Part = content.replace("data:image/svg+xml;base64,", ""); + const svgContent = atob(base64Part); + + expect(svgContent).toContain(" { + it("renders valid title tag", async () => { + const head = await routerModule.getRouteHead("/", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = renderHeadToString(head); + expect(html).toMatch(/.+<\/title>/); + }); + + it("renders meta tags with proper attributes", async () => { + const head = await routerModule.getRouteHead("/", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = renderHeadToString(head); + expect(html).toMatch(/<meta charSet="utf-8" \/>/); + expect(html).toMatch(/<meta name="viewport"/); + expect(html).toMatch(/<meta name="description"/); + expect(html).toMatch(/<meta property="og:title"/); + }); + + it("renders link tags", async () => { + const head = await routerModule.getRouteHead("/", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = renderHeadToString(head); + expect(html).toMatch(/<link rel="canonical"/); + expect(html).toMatch(/<link rel="icon"/); + }); + + it("renders structured data with valid JSON", async () => { + const head = await routerModule.getRouteHead("/", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = renderHeadToString(head); + const jsonLdMatch = html.match( + /<script type="application\/ld\+json">(.+?)<\/script>/s + ); + expect(jsonLdMatch).toBeTruthy(); + + if (jsonLdMatch) { + const jsonContent = jsonLdMatch[1]; + expect(() => JSON.parse(jsonContent)).not.toThrow(); + } + }); + + it("properly escapes HTML in meta content", async () => { + const head: HeadData = { + meta: [ + { title: 'Test <script>alert("xss")</script>' }, + { name: "description", content: 'Test & "quotes" < > symbols' }, + ], + links: [], + scripts: [], + }; + + const html = renderHeadToString(head); + expect(html).not.toContain("<script>"); + expect(html).toContain("<script>"); + expect(html).toContain("&"); + expect(html).toContain("""); + }); + }); +}); diff --git a/host/tests/integration/ssr.test.ts b/host/tests/integration/ssr.test.ts new file mode 100644 index 0000000..7796259 --- /dev/null +++ b/host/tests/integration/ssr.test.ts @@ -0,0 +1,360 @@ +import { Effect } from "every-plugin/effect"; +import { beforeAll, describe, expect, it, vi } from "vitest"; +import { loadBosConfig, type RuntimeConfig } from "@/services/config"; +import { loadRouterModule } from "@/services/federation.server"; +import type { RouterModule } from "@/types"; + +async function consumeStream(stream: ReadableStream): Promise<string> { + const reader = stream.getReader(); + const decoder = new TextDecoder(); + let html = ''; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + html += decoder.decode(value, { stream: true }); + } + html += decoder.decode(); + return html; +} + +const mockApiClient = { + getValue: vi.fn().mockImplementation(({ key }: { key: string }) => + Promise.resolve({ key, value: `test-value-for-${key}` }) + ), + setValue: vi.fn().mockResolvedValue({ success: true }), + protected: vi.fn().mockResolvedValue({ message: "Protected data" }), + listKeys: vi.fn().mockResolvedValue({ keys: [], total: 0, hasMore: false }), +}; + +describe("SSR Stream Lifecycle", () => { + let routerModule: RouterModule; + let config: RuntimeConfig; + + beforeAll(async () => { + globalThis.$apiClient = mockApiClient; + config = await loadBosConfig(); + routerModule = await Effect.runPromise(loadRouterModule(config)); + }); + + describe("Stream Completion", () => { + it("completes stream for root route without timeout", async () => { + const startTime = Date.now(); + + const head = await routerModule.getRouteHead("/", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const elapsed = Date.now() - startTime; + + expect(head).toBeDefined(); + expect(head.meta).toBeDefined(); + expect(elapsed).toBeLessThan(5000); + }); + + it("completes stream for layout routes", async () => { + const startTime = Date.now(); + + const head = await routerModule.getRouteHead("/login", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const elapsed = Date.now() - startTime; + + expect(head).toBeDefined(); + expect(elapsed).toBeLessThan(5000); + }); + + it("does not block on authenticated routes with ssr: false", async () => { + const startTime = Date.now(); + + const head = await routerModule.getRouteHead("/keys", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const elapsed = Date.now() - startTime; + + expect(head).toBeDefined(); + expect(elapsed).toBeLessThan(5000); + }); + + it("handles dynamic authenticated routes without blocking", async () => { + const startTime = Date.now(); + + const head = await routerModule.getRouteHead("/keys/test-key-123", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const elapsed = Date.now() - startTime; + + expect(head).toBeDefined(); + expect(elapsed).toBeLessThan(5000); + }); + }); + + describe("SSR Configuration", () => { + it("renders layout route metadata", async () => { + const head = await routerModule.getRouteHead("/", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const titleMeta = head.meta.find( + (m) => m && typeof m === "object" && "title" in m + ); + expect(titleMeta).toBeDefined(); + }); + + it("authenticated route head does not trigger auth check during SSR", async () => { + const authCallsBefore = mockApiClient.protected.mock.calls.length; + + await routerModule.getRouteHead("/keys", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const authCallsAfter = mockApiClient.protected.mock.calls.length; + expect(authCallsAfter).toBe(authCallsBefore); + }); + }); + + describe("Public SSR Routes", () => { + const STREAM_TIMEOUT = 5000; + + it("renders public /p/{key} route with full SSR", { timeout: 6000 }, async () => { + const request = new Request("http://localhost/p/test-public-key"); + const startTime = Date.now(); + + const result = await routerModule.renderToStream(request, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = await consumeStream(result.stream); + const elapsed = Date.now() - startTime; + + expect(elapsed).toBeLessThan(STREAM_TIMEOUT); + expect(result.statusCode).toBe(200); + expect(html).toContain("<!DOCTYPE html>"); + expect(html).toContain("</html>"); + expect(html).toContain("test-public-key"); + }); + + it("includes OG metadata in public route head", async () => { + const head = await routerModule.getRouteHead("/p/my-og-test", { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + expect(head).toBeDefined(); + expect(head.meta).toBeDefined(); + + const ogTitle = head.meta.find( + (m) => m && typeof m === "object" && "property" in m && m.property === "og:title" + ); + const ogDescription = head.meta.find( + (m) => m && typeof m === "object" && "property" in m && m.property === "og:description" + ); + const ogImage = head.meta.find( + (m) => m && typeof m === "object" && "property" in m && m.property === "og:image" + ); + + expect(ogTitle).toBeDefined(); + expect(ogDescription).toBeDefined(); + expect(ogImage).toBeDefined(); + }); + + it("renders key parameter in full SSR stream", { timeout: 6000 }, async () => { + const request = new Request("http://localhost/p/rendered-key-value"); + + const result = await routerModule.renderToStream(request, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = await consumeStream(result.stream); + + expect(html).toContain("rendered-key-value"); + expect(html).toContain("Public Page:"); + }); + }); + + describe("Full Stream Rendering", () => { + const STREAM_TIMEOUT = 5000; + + it("completes full stream render for root route", { timeout: 6000 }, async () => { + const request = new Request("http://localhost/"); + const startTime = Date.now(); + + const result = await routerModule.renderToStream(request, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = await consumeStream(result.stream); + const elapsed = Date.now() - startTime; + + expect(elapsed).toBeLessThan(STREAM_TIMEOUT); + expect(result.statusCode).toBe(200); + expect(html).toContain("<!DOCTYPE html>"); + expect(html).toContain("</html>"); + }); + + it("completes full stream render for /login route", { timeout: 6000 }, async () => { + const request = new Request("http://localhost/login"); + const startTime = Date.now(); + + const result = await routerModule.renderToStream(request, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = await consumeStream(result.stream); + const elapsed = Date.now() - startTime; + + expect(elapsed).toBeLessThan(STREAM_TIMEOUT); + expect(result.statusCode).toBe(200); + expect(html).toContain("<!DOCTYPE html>"); + }); + + it("completes full stream render for authenticated route /keys/test-key", { timeout: 6000 }, async () => { + const request = new Request("http://localhost/keys/test-key"); + const startTime = Date.now(); + + const result = await routerModule.renderToStream(request, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = await consumeStream(result.stream); + const elapsed = Date.now() - startTime; + + expect(elapsed).toBeLessThan(STREAM_TIMEOUT); + expect(result.statusCode).toBe(200); + expect(html).toContain("<!DOCTYPE html>"); + expect(html).toContain("test-key"); + }); + + it("does NOT call API during SSR for ssr:false authenticated routes", { timeout: 6000 }, async () => { + mockApiClient.getValue.mockClear(); + const request = new Request("http://localhost/keys/my-test-key"); + + const result = await routerModule.renderToStream(request, { + assetsUrl: config.ui.url, + runtimeConfig: { + env: config.env, + account: config.account, + title: config.title, + hostUrl: config.hostUrl, + apiBase: "/api", + rpcBase: "/api/rpc", + assetsUrl: config.ui.url, + }, + }); + + const html = await consumeStream(result.stream); + + expect(html).toContain("my-test-key"); + expect(mockApiClient.getValue).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/host/vitest.config.ts b/host/vitest.config.ts new file mode 100644 index 0000000..0092c5f --- /dev/null +++ b/host/vitest.config.ts @@ -0,0 +1,15 @@ +import tsconfigPaths from "vite-tsconfig-paths"; +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + environment: "node", + testTimeout: 30000, + include: ["tests/**/*.test.ts"], + }, + plugins: [ + tsconfigPaths({ + projects: ["./tsconfig.json"], + }), + ], +}); diff --git a/package.json b/package.json index 26c8190..e92b4c7 100644 --- a/package.json +++ b/package.json @@ -1,39 +1,63 @@ { "name": "monorepo", "private": true, - "workspaces": [ - "api", - "host", - "ui" - ], - "scripts": { - "dev": "turbo dev", - "dev:ui": "USE_REMOTE_API=true turbo dev --filter=host --filter=ui", - "dev:api": "USE_REMOTE_UI=true turbo dev --filter=host --filter=api", - "start": "turbo preview --filter=host", - "build": "turbo build", - "build:api": "turbo build --filter=api", - "build:host": "turbo build --filter=host", - "build:ui": "turbo build --filter=ui", - "deploy": "NODE_ENV=production turbo build --filter=ui --filter=api", - "typecheck": "turbo typecheck", - "db:push": "turbo db:push", - "db:studio": "turbo db:studio", - "db:generate": "turbo db:generate", - "db:migrate": "turbo db:migrate" + "workspaces": { + "packages": [ + "api", + "ui", + "host" + ], + "catalog": { + "react": "^19.2.3", + "react-dom": "^19.2.3", + "@tanstack/react-query": "^5.90.11", + "@tanstack/react-router": "^1.153.2", + "near-kit": "^0.10.0", + "@hot-labs/near-connect": "^0.8.2", + "drizzle-orm": "^0.45.1", + "drizzle-kit": "^0.31.8", + "@libsql/client": "^0.17.0", + "better-auth": "^1.4.15", + "better-near-auth": "^0.3.4", + "every-plugin": "0.8.8", + "typescript": "^5.9.3", + "vitest": "^4.0.17", + "@types/node": "^25.0.3", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "effect": "^3.19.15" + } }, - "devDependencies": { - "@types/node": "^25.0.9", - "turbo": "^2.7.5" + "scripts": { + "init": "bun run db:migrate", + "bos": "bunx everything-dev", + "dev": "bunx everything-dev dev", + "dev:ui": "bunx everything-dev dev --ui", + "dev:api": "bunx everything-dev dev --api", + "dev:host": "bunx everything-dev dev --host", + "dev:proxy": "bunx everything-dev dev --proxy", + "build": "bunx everything-dev build", + "build:api": "bun run --cwd api rsbuild build", + "build:host": "bun run --cwd host rsbuild build", + "build:ui": "bun run --cwd ui rsbuild build", + "deploy": "NODE_ENV=production bun run build:ui && bun run build:api", + "typecheck": "bun run --cwd host tsc --noEmit && bun run --cwd ui tsc --noEmit && bun run --cwd api tsc --noEmit", + "start": "NODE_ENV=production bunx everything-dev start --no-interactive", + "db:push": "bun run --cwd host drizzle-kit push", + "db:studio": "bun run --cwd host drizzle-kit studio", + "db:generate": "bun run --cwd host drizzle-kit generate", + "db:migrate": "bun run --cwd host drizzle-kit migrate" }, "packageManager": "bun@1.2.20", "dependencies": { - "@tanstack/router-plugin": "^1.151.1", - "drizzle-kit": "^0.31.8", - "esbuild": "^0.27.2", - "hono": "^4.11.4", - "tsx": "^4.21.0", - "vite-tsconfig-paths": "^6.0.4", - "vitest": "^4.0.17" + "@types/bun": "^1.3.6" + }, + "module": "index.ts", + "type": "module", + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5" } -} \ No newline at end of file +} diff --git a/turbo.json b/turbo.json deleted file mode 100644 index 385303e..0000000 --- a/turbo.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "https://turbo.build/schema.json", - "ui": "tui", - "envMode": "loose", - "globalPassThroughEnv": ["USE_REMOTE_API", "USE_REMOTE_UI", "NODE_ENV"], - "tasks": { - "dev": { - "cache": false, - "persistent": true - }, - "build": { - "dependsOn": ["^build"], - "outputs": ["dist/**", ".rsbuild/**"] - }, - "typecheck": { - "dependsOn": ["^typecheck"] - }, - "preview": { - - }, - "test": { - "dependsOn": ["^build"] - }, - "db:push": { - "cache": false - }, - "db:studio": { - "cache": false, - "persistent": true - }, - "db:generate": { - "cache": false - }, - "db:migrate": { - "cache": false - } - } -} diff --git a/ui/.cta.json b/ui/.cta.json index 4921e9c..5e01f18 100644 --- a/ui/.cta.json +++ b/ui/.cta.json @@ -1,5 +1,5 @@ { - "projectName": "agency", + "projectName": "demo", "mode": "file-router", "typescript": true, "tailwind": true, diff --git a/ui/README.md b/ui/README.md index 5d21b7f..6e81e97 100644 --- a/ui/README.md +++ b/ui/README.md @@ -1,15 +1,6 @@ # ui -Frontend application for NEAR AI chat with streaming responses and KV store demo. - -## Tech Stack - -- **Framework**: React 19 -- **Routing**: TanStack Router (file-based) -- **Data**: TanStack Query + oRPC client -- **Styling**: Tailwind CSS v4 -- **Build**: Rsbuild + Module Federation -- **Auth**: better-auth client +Remote frontend module with TanStack Router and SSR support. ## Module Federation @@ -17,18 +8,72 @@ Exposed as remote module for host consumption via `remoteEntry.js`: | Export | Path | Description | |--------|------|-------------| -| `./App` | `bootstrap.tsx` | Main app component | -| `./Router` | `router.tsx` | TanStack Router instance | +| `./Router` | `router.tsx` | TanStack Router instance (client) | +| `./Hydrate` | `hydrate.tsx` | Client hydration entry | | `./components` | `components/index.ts` | Reusable UI components | | `./providers` | `providers/index.tsx` | Context providers | +| `./hooks` | `hooks/index.ts` | React hooks | | `./types` | `types/index.ts` | TypeScript types | +**SSR Build** also exposes: +- `./Router` → `router.server.tsx` (server-side rendering) + **Shared dependencies** (singleton): - `react`, `react-dom` - `@tanstack/react-query`, `@tanstack/react-router` +- `@hot-labs/near-connect`, `near-kit` + +## Route Protection + +File-based routing with auth guards via TanStack Router: + +- `_authenticated.tsx` - Requires login, redirects to `/login` +- `_authenticated/_admin.tsx` - Requires admin role + +## Directory Structure + +``` +ui/ +├── src/ +│ ├── router.tsx # Client router +│ ├── router.server.tsx # Server router (SSR) +│ ├── hydrate.tsx # Client hydration entry +│ ├── components/ +│ │ ├── index.ts # Public component exports +│ │ ├── chat/ # Chat feature components +│ │ ├── kv/ # Key-value editor +│ │ └── ui/ # shadcn/ui primitives +│ ├── hooks/ # React hooks +│ ├── lib/ # Utilities (auth-client, utils) +│ ├── providers/ # Context providers +│ ├── routes/ # TanStack file-based routes +│ ├── types/ # TypeScript types +│ └── utils/ # API client (oRPC, streaming) +├── rsbuild.config.ts # Build configuration +└── package.json +``` + +## Tech Stack -**Configuration** (`bos.config.json`): +- **Framework**: React 19 +- **Routing**: TanStack Router (file-based) +- **Data**: TanStack Query + oRPC client +- **Styling**: Tailwind CSS v4 + shadcn/ui +- **Build**: Rsbuild + Module Federation +- **Auth**: better-auth client + +## Available Scripts + +- `bun dev` - Start dev server (port 3002) +- `bun build` - Build for production (client + server) +- `bun build:client` - Build client bundle only +- `bun build:server` - Build SSR bundle only +- `bun typecheck` - Type checking + +## Configuration + +**bos.config.json**: ```json { @@ -36,7 +81,8 @@ Exposed as remote module for host consumption via `remoteEntry.js`: "ui": { "name": "ui", "development": "http://localhost:3002", - "production": "https://", + "production": "https://cdn.example.com/ui", + "ssr": "https://cdn.example.com/ui-ssr", "exposes": { "App": "./App", "components": "./components", @@ -48,21 +94,9 @@ Exposed as remote module for host consumption via `remoteEntry.js`: } ``` -## Available Scripts - -- `bun dev` - Start dev server (port 3002) -- `bun build` - Build for production -- `bun preview` - Preview production build -- `bun typecheck` - Type checking +## Component Conventions -## Project Structure - -- `src/routes/` - File-based routes (TanStack Router) - - `/` - Chat interface (canonical) - - `/chat` - Redirect alias to `/` - - `/dashboard` - Admin dashboard (role-gated) -- `src/components/` - UI components (shadcn/ui) - - `chat/` - Chat UI components - - `kv/` - Key-value store demo -- `src/utils/` - API client (oRPC) -- `src/lib/` - Auth client (Better-Auth + NEAR) +- All component files use **kebab-case** naming: `chat-input.tsx`, `user-nav.tsx` +- UI primitives in `components/ui/` (shadcn/ui) +- Feature components in `components/<feature>/` +- Export public components via `components/index.ts` diff --git a/ui/index.html b/ui/index.html deleted file mode 100644 index be1ac68..0000000 --- a/ui/index.html +++ /dev/null @@ -1,52 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" /> - <meta name="color-scheme" content="light dark" /> - <meta name="format-detection" content="telephone=no" /> - - <!-- Favicon --> - <link rel="icon" type="image/x-icon" href="/favicon.ico" /> - <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" /> - <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" /> - <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> - <link rel="manifest" href="/manifest.json" /> - - <!-- Preconnect to font origins --> - <link rel="preconnect" href="https://fonts.googleapis.com" /> - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> - - <!-- Theme --> - <meta name="theme-color" content="#171717" /> - - <!-- Theme flash prevention - runs before any render --> - <script> - (function() { - var t = localStorage.getItem('theme'); - if (t === 'dark' || (!t && window.matchMedia('(prefers-color-scheme: dark)').matches)) { - document.documentElement.classList.add('dark'); - } - })(); - </script> - - <style> - /* Minimal shell reset - matches host for dev consistency */ - *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - html { height: 100%; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } - body { - min-height: 100%; - -webkit-tap-highlight-color: transparent; - touch-action: manipulation; - } - #app { min-height: 100vh; } - @supports (min-height: 100dvh) { - #app { min-height: 100dvh; } - } - </style> - </head> - <body> - <div id="app"></div> - <script type="module" src="/src/main.tsx"></script> - </body> -</html> diff --git a/ui/package.json b/ui/package.json index 8810c46..71c1324 100644 --- a/ui/package.json +++ b/ui/package.json @@ -5,7 +5,9 @@ "type": "module", "scripts": { "dev": "rsbuild dev", - "build": "rsbuild build", + "build": "bun run build:client && bun run build:server", + "build:client": "BUILD_TARGET=client rsbuild build", + "build:server": "BUILD_TARGET=server rsbuild build", "preview": "rsbuild preview", "test": "vitest run", "typecheck": "tsc --noEmit", @@ -13,11 +15,8 @@ }, "dependencies": { "@hot-labs/near-connect": "^0.8.2", - "@orpc/client": "^1.13.4", + "@orpc/client": "^1.12.3", "@orpc/contract": "^1.13.4", - "@orpc/react-query": "^1.13.4", - "@orpc/server": "^1.13.4", - "@orpc/tanstack-query": "^1.13.4", "@radix-ui/react-aspect-ratio": "^1.1.8", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-checkbox": "^1.3.3", @@ -31,55 +30,52 @@ "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-tabs": "^1.1.13", - "@reactflow/background": "^11.3.14", - "@reactflow/controls": "^11.2.14", - "@reactflow/minimap": "^11.7.14", - "@tanstack/react-devtools": "^0.7.11", - "@tanstack/react-query": "^5.90.19", - "@tanstack/react-query-devtools": "^5.91.2", - "@tanstack/react-router": "^1.151.1", - "@tanstack/react-router-devtools": "^1.151.1", + "@tanstack/react-devtools": "^0.9.2", + "@tanstack/react-query": "catalog:", + "@tanstack/react-query-devtools": "^5.91.1", + "@tanstack/react-router": "catalog:", + "@tanstack/react-router-devtools": "^1.157.15", "@tanstack/react-table": "^8.21.3", - "better-auth": "^1.4.14", - "better-near-auth": "^0.3.4", + "better-auth": "catalog:", + "better-near-auth": "catalog:", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "lucide-react": "^0.544.0", - "near-kit": "^0.6.3", + "lucide-react": "^0.563.0", + "near-kit": "^0.10.0", "next-themes": "^0.4.6", "react": "^19.2.3", "react-dom": "^19.2.3", - "reactflow": "^11.11.4", "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tw-animate-css": "^1.4.0", - "zustand": "^5.0.10" + "zustand": "^5.0.9" }, "peerDependencies": { - "@hot-labs/near-connect": "^0.8.2", + "@hot-labs/near-connect": "^0.8.x", "@tanstack/react-query": "^5.x", "@tanstack/react-router": "^1.x", - "near-kit": "^0.6.x", - "react": "^19.0.0", - "react-dom": "^19.0.0" + "near-kit": "^0.10.0", + "react": "^19.2.0", + "react-dom": "^19.2.0" }, "devDependencies": { - "@module-federation/enhanced": "^0.21.6", - "@module-federation/rsbuild-plugin": "^0.21.6", - "@rsbuild/core": "^1.7.2", - "@rsbuild/plugin-react": "^1.4.3", - "@tailwindcss/postcss": "^4.1.18", - "@tanstack/router-plugin": "^1.151.1", + "every-plugin": "catalog:", + "@module-federation/enhanced": "^0.23.0", + "@module-federation/node": "^2.7.26", + "@module-federation/rsbuild-plugin": "^0.23.0", + "@rsbuild/core": "^1.6.12", + "@rsbuild/plugin-react": "^1.4.2", + "@tailwindcss/postcss": "^4.1.17", + "@tanstack/router-plugin": "^1.157.15", "@testing-library/dom": "^10.4.1", - "@testing-library/react": "^16.3.1", - "@types/node": "^22.19.7", - "@types/react": "^19.2.8", - "@types/react-dom": "^19.2.3", - "jsdom": "^27.4.0", - "tailwindcss": "^4.1.18", - "typescript": "^5.9.3", - "vitest": "^3.2.4", - "web-vitals": "^5.1.0", - "zephyr-rsbuild-plugin": "^0.1.4" + "@testing-library/react": "^16.3.2", + "@types/node": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "jsdom": "^27.2.0", + "tailwindcss": "^4.1.17", + "typescript": "catalog:", + "vitest": "catalog:", + "zephyr-rsbuild-plugin": "^0.1.2" } } diff --git a/ui/rsbuild.config.ts b/ui/rsbuild.config.ts index bb8a4a9..b099327 100644 --- a/ui/rsbuild.config.ts +++ b/ui/rsbuild.config.ts @@ -1,10 +1,12 @@ import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; +import { ModuleFederationPlugin } from "@module-federation/enhanced/rspack"; import { pluginModuleFederation } from "@module-federation/rsbuild-plugin"; import { defineConfig } from "@rsbuild/core"; import { pluginReact } from "@rsbuild/plugin-react"; import { TanStackRouterRspack } from "@tanstack/router-plugin/rspack"; +import { getUISharedDependencies } from "every-plugin/build/rspack"; import { withZephyr } from "zephyr-rsbuild-plugin"; import pkg from "./package.json"; @@ -12,11 +14,10 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const normalizedName = pkg.name; const isProduction = process.env.NODE_ENV === "production"; +const buildTarget = process.env.BUILD_TARGET as "client" | "server" | undefined; +const isServerBuild = buildTarget === "server"; -const configPath = path.resolve(__dirname, "../bos.config.json"); -const bosConfig = JSON.parse(fs.readFileSync(configPath, "utf8")); - -function updateHostConfig(_name: string, url: string) { +function updateBosConfig(field: "production" | "ssr", url: string) { try { const configPath = path.resolve(__dirname, "../bos.config.json"); const config = JSON.parse(fs.readFileSync(configPath, "utf8")); @@ -26,9 +27,9 @@ function updateHostConfig(_name: string, url: string) { return; } - config.app.ui.production = url; - fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n"); - console.log(" ✅ Updated bos.config.json: app.ui.production"); + config.app.ui[field] = url; + fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`); + console.log(` ✅ Updated bos.config.json: app.ui.${field}`); } catch (err) { console.error( " ❌ Failed to update bos.config.json:", @@ -37,150 +38,160 @@ function updateHostConfig(_name: string, url: string) { } } -const plugins = [ - pluginReact(), - pluginModuleFederation({ - name: normalizedName, - filename: "remoteEntry.js", - dts: false, - exposes: { - "./App": "./src/bootstrap.tsx", - "./Router": "./src/router.tsx", - "./components": "./src/components/index.ts", - "./providers": "./src/providers/index.tsx", - "./hooks": "./src/hooks/index.ts", - "./types": "./src/types/index.ts", - }, - shared: { - react: { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies.react, +const uiSharedDeps = getUISharedDependencies(); + +function createClientConfig() { + const plugins = [ + pluginReact(), + pluginModuleFederation({ + name: normalizedName, + filename: "remoteEntry.js", + dts: false, + exposes: { + "./Router": "./src/router.tsx", + "./Hydrate": "./src/hydrate.tsx", + "./components": "./src/components/index.ts", + "./providers": "./src/providers/index.tsx", + "./hooks": "./src/hooks/index.ts", + "./types": "./src/types/index.ts", }, - "react-dom": { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies["react-dom"], + shared: uiSharedDeps, + }), + ]; + + if (isProduction) { + plugins.push( + withZephyr({ + hooks: { + onDeployComplete: (info) => { + console.log("🚀 UI Client Deployed:", info.url); + updateBosConfig("production", info.url); + }, + }, + }) + ); + } + + return defineConfig({ + plugins, + source: { + entry: { + index: "./src/hydrate.tsx", }, - "@tanstack/react-query": { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies["@tanstack/react-query"], + }, + resolve: { + alias: { + "@": "./src", }, - "@tanstack/react-router": { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies["@tanstack/react-router"], + }, + dev: { + lazyCompilation: false, + progressBar: false, + client: { + overlay: false, }, - "@hot-labs/near-connect": { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies["@hot-labs/near-connect"], + }, + server: { + port: 3002, + printUrls: ({ urls }) => urls.filter((url) => url.includes("localhost")), + headers: { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, POST, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type", }, - "near-kit": { - singleton: true, - eager: true, - requiredVersion: pkg.dependencies["near-kit"], + publicDir: { + name: "dist", + copyOnBuild: false, }, }, - }), -]; - -if (isProduction) { - plugins.push( - withZephyr({ - hooks: { - onDeployComplete: (info) => { - console.log("🚀 UI Deployed:", info.url); - updateHostConfig(normalizedName, info.url); + tools: { + rspack: { + target: "web", + output: { + uniqueName: normalizedName, }, + infrastructureLogging: { level: "error" }, + stats: "errors-warnings", + plugins: [ + TanStackRouterRspack({ + target: "react", + autoCodeSplitting: true, + }), + ], }, - }) - ); -} - -export default defineConfig({ - plugins, - source: { - define: { - "import.meta.env.PUBLIC_ACCOUNT_ID": JSON.stringify(bosConfig.account), - }, - entry: { - index: "./src/main.tsx", - remote: "./src/remote.tsx", }, - }, - resolve: { - alias: { - "@": "./src", + output: { + distPath: { root: "dist", css: "static/css", js: "static/js" }, + assetPrefix: "auto", + filename: { js: "[name].js", css: "style.css" }, + copy: [{ from: path.resolve(__dirname, "public"), to: "./" }], }, - }, - html: { - template: "./index.html", - }, - dev: { - lazyCompilation: false, - progressBar: false, - client: { - overlay: false, - }, - }, - server: { - port: 3002, - printUrls: ({ urls }) => urls.filter((url) => url.includes("localhost")), - headers: { - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "GET, POST, OPTIONS", - "Access-Control-Allow-Headers": "Content-Type", - }, - }, - tools: { - rspack: { - target: "web", - output: { - library: { - name: normalizedName, - type: "var", + }); +} + +function createServerConfig() { + const plugins = [pluginReact()]; + + if (isProduction) { + plugins.push( + withZephyr({ + hooks: { + onDeployComplete: (info) => { + console.log("🚀 UI SSR Deployed:", info.url); + updateBosConfig("ssr", info.url); + }, }, + }) + ); + } + + return defineConfig({ + plugins, + source: { + entry: { + index: "./src/router.server.tsx", }, - externalsType: "module", - externals: { - fs: "commonjs fs", - path: "commonjs path", - crypto: "commonjs crypto", - "node:fs": "commonjs node:fs", - "node:fs/promises": "commonjs node:fs/promises", - "node:path": "commonjs node:path", - "node:crypto": "commonjs node:crypto", - }, - infrastructureLogging: { - level: "error", + }, + resolve: { + alias: { + "@": "./src", + "@tanstack/react-devtools": false, + "@tanstack/react-router-devtools": false, }, - stats: "errors-warnings", - plugins: [ - TanStackRouterRspack({ - target: "react", - autoCodeSplitting: true, - }), - ], }, - }, - output: { - distPath: { - root: 'dist', + tools: { + rspack: { + target: "async-node", + output: { + uniqueName: `${normalizedName}_server`, + publicPath: "/", + library: { type: "commonjs-module" }, + }, + externals: [ + /^node:/, + ], + infrastructureLogging: { level: "error" }, + stats: "errors-warnings", + plugins: [ + TanStackRouterRspack({ target: "react", autoCodeSplitting: false }), + new ModuleFederationPlugin({ + name: normalizedName, + filename: "remoteEntry.server.js", + dts: false, + runtimePlugins: [require.resolve("@module-federation/node/runtimePlugin")], + library: { type: "commonjs-module" }, + exposes: { "./Router": "./src/router.server.tsx" }, + shared: uiSharedDeps, + }), + ], + }, }, - assetPrefix: "auto", - // assetPrefix: isProduction - // ? `${bosConfig.app.ui.production}/` - // : "auto", - filename: { - css: "static/css/[name].css", + output: { + distPath: { root: "dist" }, + assetPrefix: "auto", + cleanDistPath: false, }, - copy: [ - { - from: path.resolve(__dirname, "public"), - to: "./", - }, - ], - }, -}); + }); +} + +export default isServerBuild ? createServerConfig() : createClientConfig(); diff --git a/ui/src/assets/logo_full.png b/ui/src/assets/logo_full.png deleted file mode 100644 index b12422e..0000000 Binary files a/ui/src/assets/logo_full.png and /dev/null differ diff --git a/ui/src/bootstrap.tsx b/ui/src/bootstrap.tsx deleted file mode 100644 index 0dfe1e1..0000000 --- a/ui/src/bootstrap.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { createRouter, RouterProvider } from "@tanstack/react-router"; -import { HydrationBoundary, type DehydratedState } from "@tanstack/react-query"; -import { ThemeProvider } from "next-themes"; -import { StrictMode } from "react"; -import { Toaster } from "sonner"; - -import * as TanStackQueryProvider from "./integrations/tanstack-query/root-provider.tsx"; - -import { routeTree } from "./routeTree.gen.ts"; - -import "./styles.css"; - -declare global { - interface Window { - __DEHYDRATED_STATE__?: DehydratedState; - } -} - -const TanStackQueryProviderContext = TanStackQueryProvider.getContext(); -const dehydratedState = typeof window !== 'undefined' ? window.__DEHYDRATED_STATE__ : undefined; -function NotFoundComponent() { - return ( - <div className="min-h-screen flex items-center justify-center bg-background"> - <div className="text-center"> - <h1 className="text-4xl font-bold text-foreground mb-4">404</h1> - <p className="text-muted-foreground mb-8">Page not found</p> - <a - href="/" - className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2" - > - Go Home - </a> - </div> - </div> - ); -} - -function ErrorComponent({ error }: { error: Error }) { - return ( - <div className="min-h-screen flex items-center justify-center bg-background"> - <div className="text-center"> - <h1 className="text-4xl font-bold text-foreground mb-4">Oops!</h1> - <p className="text-muted-foreground mb-4">Something went wrong</p> - <details className="text-sm text-muted-foreground bg-muted p-4 rounded mb-8"> - <summary className="cursor-pointer">Error Details</summary> - <pre className="mt-2 whitespace-pre-wrap text-left"> - {error.message} - </pre> - </details> - <button - type="button" - onClick={() => window.location.reload()} - className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2" - > - Reload Page - </button> - </div> - </div> - ); -} - -const router = createRouter({ - routeTree, - context: { - ...TanStackQueryProviderContext, - }, - defaultPreload: "intent", - scrollRestoration: true, - defaultStructuralSharing: true, - defaultPreloadStaleTime: 0, - defaultNotFoundComponent: NotFoundComponent, - defaultErrorComponent: ErrorComponent, -}); - -declare module "@tanstack/react-router" { - interface Register { - router: typeof router; - } -} - -export function App() { - return ( - <StrictMode> - <TanStackQueryProvider.Provider {...TanStackQueryProviderContext}> - <HydrationBoundary state={dehydratedState}> - <ThemeProvider attribute="class" defaultTheme="system" enableSystem> - <RouterProvider router={router} /> - <Toaster position="bottom-right" richColors closeButton /> - </ThemeProvider> - </HydrationBoundary> - </TanStackQueryProvider.Provider> - </StrictMode> - ); -} - -export default App; diff --git a/ui/src/components/chat/ChatInput.tsx b/ui/src/components/chat/chat-input.tsx similarity index 100% rename from ui/src/components/chat/ChatInput.tsx rename to ui/src/components/chat/chat-input.tsx diff --git a/ui/src/components/chat/ChatMessage.tsx b/ui/src/components/chat/chat-message.tsx similarity index 100% rename from ui/src/components/chat/ChatMessage.tsx rename to ui/src/components/chat/chat-message.tsx diff --git a/ui/src/components/chat/ChatPage.tsx b/ui/src/components/chat/chat-page.tsx similarity index 98% rename from ui/src/components/chat/ChatPage.tsx rename to ui/src/components/chat/chat-page.tsx index 9b3dab5..13d675b 100644 --- a/ui/src/components/chat/ChatPage.tsx +++ b/ui/src/components/chat/chat-page.tsx @@ -11,8 +11,8 @@ import { isCompleteData, isErrorData, } from "../../utils/stream"; -import { ChatMessage } from "../../components/chat/ChatMessage"; -import { ChatInput } from "../../components/chat/ChatInput"; +import { ChatMessage } from "./chat-message"; +import { ChatInput } from "./chat-input"; interface Message { id: string; diff --git a/ui/src/components/kv/KVEditor.tsx b/ui/src/components/kv/kv-editor.tsx similarity index 100% rename from ui/src/components/kv/KVEditor.tsx rename to ui/src/components/kv/kv-editor.tsx diff --git a/ui/src/components/ui/markdown.tsx b/ui/src/components/ui/markdown.tsx new file mode 100644 index 0000000..93cde67 --- /dev/null +++ b/ui/src/components/ui/markdown.tsx @@ -0,0 +1,189 @@ +import { cn } from "@/lib/utils"; + +interface MarkdownProps { + content: string; + className?: string; +} + +export function Markdown({ content, className }: MarkdownProps) { + const html = parseMarkdown(content); + + return ( + // biome-ignore lint/security/noDangerouslySetInnerHtml: markdown rendering requires HTML injection + <article + className={cn( + "prose prose-neutral dark:prose-invert max-w-none", + "prose-headings:font-semibold prose-headings:tracking-tight", + "prose-h1:text-3xl prose-h1:mb-6", + "prose-h2:text-2xl prose-h2:mt-8 prose-h2:mb-4 prose-h2:border-b prose-h2:border-border prose-h2:pb-2", + "prose-h3:text-xl prose-h3:mt-6 prose-h3:mb-3", + "prose-p:text-muted-foreground prose-p:leading-relaxed", + "prose-a:text-primary prose-a:no-underline hover:prose-a:underline", + "prose-code:bg-muted prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm prose-code:font-mono prose-code:before:content-none prose-code:after:content-none", + "prose-pre:bg-muted prose-pre:border prose-pre:border-border prose-pre:rounded-lg", + "prose-blockquote:border-l-primary prose-blockquote:bg-muted/30 prose-blockquote:py-1 prose-blockquote:not-italic", + "prose-li:text-muted-foreground", + "prose-table:border prose-table:border-border", + "prose-th:bg-muted prose-th:border prose-th:border-border prose-th:px-4 prose-th:py-2", + "prose-td:border prose-td:border-border prose-td:px-4 prose-td:py-2", + "prose-hr:border-border", + className + )} + dangerouslySetInnerHTML={{ __html: html }} + /> + ); +} + +function parseMarkdown(md: string): string { + let html = md; + + html = html.replace(/^### (.*$)/gim, '<h3>$1</h3>'); + html = html.replace(/^## (.*$)/gim, '<h2>$1</h2>'); + html = html.replace(/^# (.*$)/gim, '<h1>$1</h1>'); + + html = html.replace(/\*\*\*(.*?)\*\*\*/gim, '<strong><em>$1</em></strong>'); + html = html.replace(/\*\*(.*?)\*\*/gim, '<strong>$1</strong>'); + html = html.replace(/\*(.*?)\*/gim, '<em>$1</em>'); + + html = html.replace(/`{3}(\w*)\n([\s\S]*?)\n`{3}/gim, (_, lang, code) => { + const escapedCode = escapeHtml(code); + return `<pre><code class="language-${lang || 'text'}">${escapedCode}</code></pre>`; + }); + html = html.replace(/`([^`]+)`/gim, (_, code) => { + return `<code>${escapeHtml(code)}</code>`; + }); + + html = html.replace(/^\|(.+)\|$/gim, (match) => { + return match; + }); + + const lines = html.split('\n'); + const processedLines: string[] = []; + let inTable = false; + let tableRows: string[] = []; + let inList = false; + let listItems: string[] = []; + let listType: 'ul' | 'ol' = 'ul'; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + if (line.match(/^\|(.+)\|$/)) { + if (!inTable) { + inTable = true; + tableRows = []; + } + + if (line.match(/^\|[\s\-:|]+\|$/)) { + continue; + } + tableRows.push(line); + } else { + if (inTable) { + processedLines.push(buildTable(tableRows)); + inTable = false; + tableRows = []; + } + + const ulMatch = line.match(/^[\s]*[-*]\s+(.+)$/); + const olMatch = line.match(/^[\s]*\d+\.\s+(.+)$/); + + if (ulMatch) { + if (!inList || listType !== 'ul') { + if (inList) { + processedLines.push(buildList(listItems, listType)); + } + inList = true; + listType = 'ul'; + listItems = []; + } + listItems.push(ulMatch[1]); + } else if (olMatch) { + if (!inList || listType !== 'ol') { + if (inList) { + processedLines.push(buildList(listItems, listType)); + } + inList = true; + listType = 'ol'; + listItems = []; + } + listItems.push(olMatch[1]); + } else { + if (inList) { + processedLines.push(buildList(listItems, listType)); + inList = false; + listItems = []; + } + + if (line.match(/^>\s*(.*)/)) { + const quoteContent = line.replace(/^>\s*/, ''); + processedLines.push(`<blockquote><p>${quoteContent}</p></blockquote>`); + } else if (line.match(/^---+$/)) { + processedLines.push('<hr />'); + } else if (line.trim() === '') { + processedLines.push(''); + } else if (!line.match(/^<h[1-6]>/)) { + processedLines.push(`<p>${line}</p>`); + } else { + processedLines.push(line); + } + } + } + } + + if (inTable) { + processedLines.push(buildTable(tableRows)); + } + if (inList) { + processedLines.push(buildList(listItems, listType)); + } + + html = processedLines.join('\n'); + + html = html.replace( + /\[([^\]]+)\]\(([^)]+)\)/gim, + '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>' + ); + + return html; +} + +function buildTable(rows: string[]): string { + if (rows.length === 0) return ''; + + const headerRow = rows[0]; + const dataRows = rows.slice(1); + + const headerCells = headerRow + .split('|') + .filter((c) => c.trim()) + .map((c) => `<th>${c.trim()}</th>`) + .join(''); + + const bodyRows = dataRows + .map((row) => { + const cells = row + .split('|') + .filter((c) => c.trim()) + .map((c) => `<td>${c.trim()}</td>`) + .join(''); + return `<tr>${cells}</tr>`; + }) + .join(''); + + return `<div class="overflow-x-auto"><table><thead><tr>${headerCells}</tr></thead><tbody>${bodyRows}</tbody></table></div>`; +} + +function buildList(items: string[], type: 'ul' | 'ol'): string { + const listItems = items.map((item) => `<li>${item}</li>`).join(''); + return `<${type}>${listItems}</${type}>`; +} + +function escapeHtml(text: string): string { + return text + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} diff --git a/ui/src/components/user-nav.tsx b/ui/src/components/user-nav.tsx new file mode 100644 index 0000000..e3830ea --- /dev/null +++ b/ui/src/components/user-nav.tsx @@ -0,0 +1,49 @@ +import { useQuery } from "@tanstack/react-query"; +import { Link, useRouter } from "@tanstack/react-router"; +import { authClient } from "../lib/auth-client"; +import { sessionQueryOptions } from "../lib/session"; +import { queryClient } from "../utils/orpc"; + +export function UserNav() { + const router = useRouter(); + const { data: session } = useQuery(sessionQueryOptions); + const accountId = session?.user?.id; + + const handleSignOut = async () => { + try { + await authClient.signOut(); + await authClient.near.disconnect(); + queryClient.invalidateQueries({ queryKey: ["session"] }); + router.invalidate(); + window.location.href = "/"; + } catch (error) { + console.error("Sign out error:", error); + } + }; + + if (accountId) { + return ( + <> + <span className="text-xs text-muted-foreground font-mono"> + {accountId} + </span> + <button + type="button" + onClick={handleSignOut} + className="text-xs text-muted-foreground hover:text-foreground transition-colors font-mono" + > + sign out + </button> + </> + ); + } + + return ( + <Link + to="/login" + className="text-xs text-muted-foreground hover:text-foreground transition-colors font-mono" + > + login + </Link> + ); +} diff --git a/ui/src/env.d.ts b/ui/src/env.d.ts index 2155f2d..ae4ce79 100644 --- a/ui/src/env.d.ts +++ b/ui/src/env.d.ts @@ -1,15 +1,8 @@ /// <reference types="@rsbuild/core/types" /> -interface ImportMetaEnv { - readonly PUBLIC_ACCOUNT_ID: string; -} - -interface ImportMeta { - readonly env: ImportMetaEnv; -} - interface RuntimeConfig { env: string; + account: string; title: string; hostUrl: string; ui: { diff --git a/ui/src/hydrate.tsx b/ui/src/hydrate.tsx new file mode 100644 index 0000000..976a2c4 --- /dev/null +++ b/ui/src/hydrate.tsx @@ -0,0 +1,36 @@ +import type { ClientRuntimeConfig } from "./types"; + +export async function hydrate() { + console.log("[Hydrate] Starting..."); + + const runtimeConfig = (window as { __RUNTIME_CONFIG__?: ClientRuntimeConfig }) + .__RUNTIME_CONFIG__; + if (!runtimeConfig) { + console.error("[Hydrate] No runtime config found"); + return; + } + + const { hydrateRoot } = await import("react-dom/client"); + const { RouterClient } = await import("@tanstack/react-router/ssr/client"); + const { QueryClientProvider } = await import("@tanstack/react-query"); + const { createRouter } = await import("./router"); + + const { router, queryClient } = createRouter({ + context: { + assetsUrl: runtimeConfig.assetsUrl, + runtimeConfig, + }, + }); + + console.log("[Hydrate] Calling hydrateRoot..."); + hydrateRoot( + document, + <QueryClientProvider client={queryClient}> + <RouterClient router={router} /> + </QueryClientProvider>, + ); + + console.log("[Hydrate] Complete!"); +} + +export default hydrate; diff --git a/ui/src/integrations/api/index.ts b/ui/src/integrations/api/index.ts deleted file mode 100644 index 7e60e83..0000000 --- a/ui/src/integrations/api/index.ts +++ /dev/null @@ -1 +0,0 @@ -// keep \ No newline at end of file diff --git a/ui/src/integrations/tanstack-query/root-provider.tsx b/ui/src/integrations/tanstack-query/root-provider.tsx deleted file mode 100644 index d2b91f3..0000000 --- a/ui/src/integrations/tanstack-query/root-provider.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; - -export function getContext() { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - staleTime: 5 * 60 * 1000, - gcTime: 30 * 60 * 1000, - refetchOnWindowFocus: false, - retry: 1, - }, - }, - }); - return { - queryClient, - }; -} - -export function Provider({ - children, - queryClient, -}: { - children: React.ReactNode; - queryClient: QueryClient; -}) { - return ( - <QueryClientProvider client={queryClient}>{children}</QueryClientProvider> - ); -} diff --git a/ui/src/lib/auth-client.ts b/ui/src/lib/auth-client.ts index d02a221..41d55f1 100644 --- a/ui/src/lib/auth-client.ts +++ b/ui/src/lib/auth-client.ts @@ -1,24 +1,35 @@ import { adminClient } from "better-auth/client/plugins"; -import { createAuthClient } from "better-auth/react"; +import { createAuthClient as createBetterAuthClient } from "better-auth/react"; import { siwnClient } from "better-near-auth/client"; -function getBaseURL(): string { - if (typeof window !== 'undefined' && window.__RUNTIME_CONFIG__?.hostUrl) { - return window.__RUNTIME_CONFIG__.hostUrl; - } - if (typeof window !== 'undefined') { - return window.location.origin; +function getAuthBaseUrl(): string { + if (typeof window === "undefined") return ""; + return window.__RUNTIME_CONFIG__?.hostUrl ?? window.location.origin; +} + +function createAuthClient() { + return createBetterAuthClient({ + baseURL: getAuthBaseUrl(), + fetchOptions: { credentials: "include" }, + plugins: [ + siwnClient({ + domain: typeof window !== "undefined" + ? (window.__RUNTIME_CONFIG__?.account ?? "every.near") + : "every.near", + networkId: "mainnet", + }), + adminClient(), + ], + }); +} + +let _authClient: ReturnType<typeof createAuthClient> | undefined; + +export function getAuthClient() { + if (_authClient === undefined) { + _authClient = createAuthClient(); } - return ''; + return _authClient; } -export const authClient = createAuthClient({ - baseURL: getBaseURL(), - plugins: [ - siwnClient({ - domain: import.meta.env.PUBLIC_ACCOUNT_ID || "every.near", - networkId: "mainnet", - }), - adminClient(), - ], -}); +export const authClient = getAuthClient(); diff --git a/ui/src/lib/auth-utils.ts b/ui/src/lib/auth-utils.ts index d8e4bbb..fdf9c06 100644 --- a/ui/src/lib/auth-utils.ts +++ b/ui/src/lib/auth-utils.ts @@ -1,20 +1,15 @@ -import type { Account } from "better-auth"; -import type { Dispatch, SetStateAction } from "react"; - -type LinkedAccount = Pick<Account, "providerId" | "accountId">; - -export function getNearAccountId(linkedAccounts: LinkedAccount[]): string | null { +export function getNearAccountId(linkedAccounts: any[]): string | null { const nearAccount = linkedAccounts.find(account => account.providerId === 'siwn'); return (nearAccount?.accountId)?.split(":")[0] || nearAccount?.providerId || null; } -export function getLinkedProviders(linkedAccounts: LinkedAccount[]): string[] { +export function getLinkedProviders(linkedAccounts: any[]): string[] { return linkedAccounts.map(account => account.providerId); } export function handleAccountLinkRefresh( - _componentState: unknown, - _setLinkedAccounts: Dispatch<SetStateAction<LinkedAccount[]>>, + _componentState: any, + _setLinkedAccounts: React.Dispatch<React.SetStateAction<any[]>>, refreshAccounts: () => Promise<void> ) { refreshAccounts(); diff --git a/ui/src/lib/session.ts b/ui/src/lib/session.ts index 1cf41e2..9a3ede8 100644 --- a/ui/src/lib/session.ts +++ b/ui/src/lib/session.ts @@ -9,4 +9,5 @@ export const sessionQueryOptions = queryOptions({ }, staleTime: 0, gcTime: 1000 * 60 * 10, + enabled: typeof window !== 'undefined', }); diff --git a/ui/src/main.tsx b/ui/src/main.tsx deleted file mode 100644 index 2719c38..0000000 --- a/ui/src/main.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { StrictMode } from 'react'; -import ReactDOM from 'react-dom/client'; -import { App } from './bootstrap'; -import reportWebVitals from './reportWebVitals'; - -const rootElement = document.getElementById('app'); -if (rootElement) { - const root = ReactDOM.createRoot(rootElement); - root.render( - <StrictMode> - <App /> - </StrictMode> - ); -} - -reportWebVitals(); diff --git a/ui/src/providers/index.tsx b/ui/src/providers/index.tsx index bfe2472..68fd5ad 100644 --- a/ui/src/providers/index.tsx +++ b/ui/src/providers/index.tsx @@ -1,55 +1,9 @@ -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { QueryClientProvider } from "@tanstack/react-query"; import { ThemeProvider } from "next-themes"; import { Toaster } from "sonner"; -import type { Network } from "near-kit"; -import { ErrorBoundary } from "@/components/error-boundary"; export * from "@/hooks"; -const defaultQueryClient = new QueryClient({ - defaultOptions: { - queries: { - staleTime: 5 * 60 * 1000, - gcTime: 30 * 60 * 1000, - refetchOnWindowFocus: false, - retry: 1, - }, - }, -}); - -export interface AppProviderProps { - children: React.ReactNode; - network?: Network; - queryClient?: QueryClient; -} - -export function AppProvider({ - children, - queryClient = defaultQueryClient, -}: AppProviderProps) { - return ( - <ErrorBoundary> - <ThemeProvider attribute="class" defaultTheme="system" enableSystem> - <QueryClientProvider client={queryClient}> - {children} - <Toaster position="top-center" richColors closeButton /> - </QueryClientProvider> - </ThemeProvider> - </ErrorBoundary> - ); -} - export { QueryClientProvider }; - -export function createQueryClient() { - return new QueryClient({ - defaultOptions: { - queries: { - staleTime: 5 * 60 * 1000, - gcTime: 30 * 60 * 1000, - refetchOnWindowFocus: false, - retry: 1, - }, - }, - }); -} +export { ThemeProvider }; +export { Toaster }; diff --git a/ui/src/remote.tsx b/ui/src/remote.tsx deleted file mode 100644 index b93c7a0..0000000 --- a/ui/src/remote.tsx +++ /dev/null @@ -1 +0,0 @@ -import('./bootstrap'); diff --git a/ui/src/routeTree.gen.ts b/ui/src/routeTree.gen.ts index 367ee0e..7b53950 100644 --- a/ui/src/routeTree.gen.ts +++ b/ui/src/routeTree.gen.ts @@ -11,11 +11,8 @@ import { Route as rootRouteImport } from './routes/__root' import { Route as LayoutRouteImport } from './routes/_layout' import { Route as LayoutLoginRouteImport } from './routes/_layout/login' -import { Route as LayoutPageRouteImport } from './routes/_layout/_page' import { Route as LayoutAuthenticatedRouteImport } from './routes/_layout/_authenticated' import { Route as LayoutAuthenticatedIndexRouteImport } from './routes/_layout/_authenticated/index' -import { Route as LayoutPageTermsOfServiceRouteImport } from './routes/_layout/_page/terms-of-service' -import { Route as LayoutPagePrivacyPolicyRouteImport } from './routes/_layout/_page/privacy-policy' import { Route as LayoutAuthenticatedSettingsRouteImport } from './routes/_layout/_authenticated/settings' import { Route as LayoutAuthenticatedAdminRouteImport } from './routes/_layout/_authenticated/_admin' import { Route as LayoutAuthenticatedChatIndexRouteImport } from './routes/_layout/_authenticated/chat/index' @@ -31,10 +28,6 @@ const LayoutLoginRoute = LayoutLoginRouteImport.update({ path: '/login', getParentRoute: () => LayoutRoute, } as any) -const LayoutPageRoute = LayoutPageRouteImport.update({ - id: '/_page', - getParentRoute: () => LayoutRoute, -} as any) const LayoutAuthenticatedRoute = LayoutAuthenticatedRouteImport.update({ id: '/_authenticated', getParentRoute: () => LayoutRoute, @@ -45,17 +38,6 @@ const LayoutAuthenticatedIndexRoute = path: '/', getParentRoute: () => LayoutAuthenticatedRoute, } as any) -const LayoutPageTermsOfServiceRoute = - LayoutPageTermsOfServiceRouteImport.update({ - id: '/terms-of-service', - path: '/terms-of-service', - getParentRoute: () => LayoutPageRoute, - } as any) -const LayoutPagePrivacyPolicyRoute = LayoutPagePrivacyPolicyRouteImport.update({ - id: '/privacy-policy', - path: '/privacy-policy', - getParentRoute: () => LayoutPageRoute, -} as any) const LayoutAuthenticatedSettingsRoute = LayoutAuthenticatedSettingsRouteImport.update({ id: '/settings', @@ -90,8 +72,6 @@ export interface FileRoutesByFullPath { '/': typeof LayoutAuthenticatedIndexRoute '/login': typeof LayoutLoginRoute '/settings': typeof LayoutAuthenticatedSettingsRoute - '/privacy-policy': typeof LayoutPagePrivacyPolicyRoute - '/terms-of-service': typeof LayoutPageTermsOfServiceRoute '/dashboard': typeof LayoutAuthenticatedAdminDashboardRoute '/keys/$key': typeof LayoutAuthenticatedKeysKeyRoute '/chat/': typeof LayoutAuthenticatedChatIndexRoute @@ -100,8 +80,6 @@ export interface FileRoutesByTo { '/': typeof LayoutAuthenticatedIndexRoute '/login': typeof LayoutLoginRoute '/settings': typeof LayoutAuthenticatedSettingsRoute - '/privacy-policy': typeof LayoutPagePrivacyPolicyRoute - '/terms-of-service': typeof LayoutPageTermsOfServiceRoute '/dashboard': typeof LayoutAuthenticatedAdminDashboardRoute '/keys/$key': typeof LayoutAuthenticatedKeysKeyRoute '/chat': typeof LayoutAuthenticatedChatIndexRoute @@ -110,12 +88,9 @@ export interface FileRoutesById { __root__: typeof rootRouteImport '/_layout': typeof LayoutRouteWithChildren '/_layout/_authenticated': typeof LayoutAuthenticatedRouteWithChildren - '/_layout/_page': typeof LayoutPageRouteWithChildren '/_layout/login': typeof LayoutLoginRoute '/_layout/_authenticated/_admin': typeof LayoutAuthenticatedAdminRouteWithChildren '/_layout/_authenticated/settings': typeof LayoutAuthenticatedSettingsRoute - '/_layout/_page/privacy-policy': typeof LayoutPagePrivacyPolicyRoute - '/_layout/_page/terms-of-service': typeof LayoutPageTermsOfServiceRoute '/_layout/_authenticated/': typeof LayoutAuthenticatedIndexRoute '/_layout/_authenticated/_admin/dashboard': typeof LayoutAuthenticatedAdminDashboardRoute '/_layout/_authenticated/keys/$key': typeof LayoutAuthenticatedKeysKeyRoute @@ -127,31 +102,18 @@ export interface FileRouteTypes { | '/' | '/login' | '/settings' - | '/privacy-policy' - | '/terms-of-service' | '/dashboard' | '/keys/$key' | '/chat/' fileRoutesByTo: FileRoutesByTo - to: - | '/' - | '/login' - | '/settings' - | '/privacy-policy' - | '/terms-of-service' - | '/dashboard' - | '/keys/$key' - | '/chat' + to: '/' | '/login' | '/settings' | '/dashboard' | '/keys/$key' | '/chat' id: | '__root__' | '/_layout' | '/_layout/_authenticated' - | '/_layout/_page' | '/_layout/login' | '/_layout/_authenticated/_admin' | '/_layout/_authenticated/settings' - | '/_layout/_page/privacy-policy' - | '/_layout/_page/terms-of-service' | '/_layout/_authenticated/' | '/_layout/_authenticated/_admin/dashboard' | '/_layout/_authenticated/keys/$key' @@ -178,13 +140,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LayoutLoginRouteImport parentRoute: typeof LayoutRoute } - '/_layout/_page': { - id: '/_layout/_page' - path: '' - fullPath: '/' - preLoaderRoute: typeof LayoutPageRouteImport - parentRoute: typeof LayoutRoute - } '/_layout/_authenticated': { id: '/_layout/_authenticated' path: '' @@ -199,20 +154,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LayoutAuthenticatedIndexRouteImport parentRoute: typeof LayoutAuthenticatedRoute } - '/_layout/_page/terms-of-service': { - id: '/_layout/_page/terms-of-service' - path: '/terms-of-service' - fullPath: '/terms-of-service' - preLoaderRoute: typeof LayoutPageTermsOfServiceRouteImport - parentRoute: typeof LayoutPageRoute - } - '/_layout/_page/privacy-policy': { - id: '/_layout/_page/privacy-policy' - path: '/privacy-policy' - fullPath: '/privacy-policy' - preLoaderRoute: typeof LayoutPagePrivacyPolicyRouteImport - parentRoute: typeof LayoutPageRoute - } '/_layout/_authenticated/settings': { id: '/_layout/_authenticated/settings' path: '/settings' @@ -285,29 +226,13 @@ const LayoutAuthenticatedRouteChildren: LayoutAuthenticatedRouteChildren = { const LayoutAuthenticatedRouteWithChildren = LayoutAuthenticatedRoute._addFileChildren(LayoutAuthenticatedRouteChildren) -interface LayoutPageRouteChildren { - LayoutPagePrivacyPolicyRoute: typeof LayoutPagePrivacyPolicyRoute - LayoutPageTermsOfServiceRoute: typeof LayoutPageTermsOfServiceRoute -} - -const LayoutPageRouteChildren: LayoutPageRouteChildren = { - LayoutPagePrivacyPolicyRoute: LayoutPagePrivacyPolicyRoute, - LayoutPageTermsOfServiceRoute: LayoutPageTermsOfServiceRoute, -} - -const LayoutPageRouteWithChildren = LayoutPageRoute._addFileChildren( - LayoutPageRouteChildren, -) - interface LayoutRouteChildren { LayoutAuthenticatedRoute: typeof LayoutAuthenticatedRouteWithChildren - LayoutPageRoute: typeof LayoutPageRouteWithChildren LayoutLoginRoute: typeof LayoutLoginRoute } const LayoutRouteChildren: LayoutRouteChildren = { LayoutAuthenticatedRoute: LayoutAuthenticatedRouteWithChildren, - LayoutPageRoute: LayoutPageRouteWithChildren, LayoutLoginRoute: LayoutLoginRoute, } diff --git a/ui/src/router.server.tsx b/ui/src/router.server.tsx new file mode 100644 index 0000000..7e7309a --- /dev/null +++ b/ui/src/router.server.tsx @@ -0,0 +1,173 @@ +import { QueryClientProvider } from "@tanstack/react-query"; +import type { AnyRoute } from "@tanstack/react-router"; +import { createMemoryHistory, createRouter as createTanStackRouter } from "@tanstack/react-router"; +import { createRequestHandler, renderRouterToStream, RouterServer } from "@tanstack/react-router/ssr/server"; +import { createRouter } from "./router"; +import { routeTree } from "./routeTree.gen"; +import type { + HeadData, + HeadLink, + HeadMeta, + HeadScript, + RenderOptions, + RenderResult, + RouterContext, +} from "./types"; + +export { createRouter, routeTree } from "./router"; +export type { + ClientRuntimeConfig, + CreateRouterOptions, + HeadData, + RenderOptions, + RenderResult, + RouterContext, +} from "./types"; + +function getMetaKey(meta: HeadMeta): string { + if (!meta) return "null"; + if ("title" in meta) return "title"; + if ("charSet" in meta) return "charSet"; + if ("name" in meta) return `name:${(meta as { name: string }).name}`; + if ("property" in meta) return `property:${(meta as { property: string }).property}`; + if ("httpEquiv" in meta) return `httpEquiv:${(meta as { httpEquiv: string }).httpEquiv}`; + return JSON.stringify(meta); +} + +function getLinkKey(link: HeadLink): string { + const rel = (link as { rel?: string }).rel ?? ""; + const href = (link as { href?: string }).href ?? ""; + return `${rel}:${href}`; +} + +function getScriptKey(script: HeadScript): string { + if (!script) return "null"; + if ("src" in script && script.src) return `src:${script.src}`; + if ("children" in script && script.children) return `children:${typeof script.children === "string" ? script.children : JSON.stringify(script.children)}`; + return JSON.stringify(script); +} + +export async function getRouteHead( + pathname: string, + context?: Partial<RouterContext> +): Promise<HeadData> { + const history = createMemoryHistory({ initialEntries: [pathname] }); + + const router = createTanStackRouter({ + routeTree, + history, + context: { + queryClient: undefined as never, + assetsUrl: context?.assetsUrl ?? "", + runtimeConfig: context?.runtimeConfig, + }, + }); + + const matches = router.matchRoutes(pathname); + + const metaMap = new Map<string, HeadMeta>(); + const linkMap = new Map<string, HeadLink>(); + const scriptMap = new Map<string, HeadScript>(); + + for (const match of matches) { + const route = router.looseRoutesById[match.routeId] as AnyRoute | undefined; + if (!route?.options?.head) continue; + + let loaderData: unknown = undefined; + const loaderFn = route.options.loader; + + if (loaderFn) { + try { + loaderData = await loaderFn({ + params: match.params, + context: router.options.context, + abortController: new AbortController(), + preload: false, + cause: "enter", + } as Parameters<typeof loaderFn>[0]); + } catch (error) { + console.warn( + `[getRouteHead] Loader failed for ${match.routeId}:`, + error + ); + } + } + + try { + const headResult = await route.options.head({ + loaderData, + matches, + match, + params: match.params, + } as Parameters<typeof route.options.head>[0]); + + if (headResult?.meta) { + for (const meta of headResult.meta) { + metaMap.set(getMetaKey(meta), meta); + } + } + if (headResult?.links) { + for (const link of headResult.links) { + linkMap.set(getLinkKey(link), link); + } + } + if (headResult?.scripts) { + for (const script of headResult.scripts) { + scriptMap.set(getScriptKey(script), script); + } + } + } catch (error) { + console.warn(`[getRouteHead] head() failed for ${match.routeId}:`, error); + } + } + + return { + meta: [...metaMap.values()], + links: [...linkMap.values()], + scripts: [...scriptMap.values()], + }; +} + +export async function renderToStream( + request: Request, + options: RenderOptions +): Promise<RenderResult> { + const url = new URL(request.url); + const history = createMemoryHistory({ initialEntries: [url.pathname + url.search] }); + + let queryClientRef: typeof import("@tanstack/react-query").QueryClient.prototype | null = null; + + const handler = createRequestHandler({ + request, + createRouter: () => { + const { router, queryClient } = createRouter({ + history, + context: { + assetsUrl: options.assetsUrl, + runtimeConfig: options.runtimeConfig, + }, + }); + queryClientRef = queryClient; + return router; + }, + }); + + const response = await handler(({ request, responseHeaders, router }) => + renderRouterToStream({ + request, + responseHeaders, + router, + children: ( + <QueryClientProvider client={queryClientRef!}> + <RouterServer router={router} /> + </QueryClientProvider> + ), + }), + ); + + return { + stream: response.body!, + statusCode: response.status, + headers: new Headers(response.headers), + }; +} diff --git a/ui/src/router.tsx b/ui/src/router.tsx index 269acca..b0ca78c 100644 --- a/ui/src/router.tsx +++ b/ui/src/router.tsx @@ -1,32 +1,93 @@ -import { createRouter as createTanStackRouter } from '@tanstack/react-router'; -import { QueryClient } from '@tanstack/react-query'; -import { routeTree } from './routeTree.gen'; +import { QueryClient } from "@tanstack/react-query"; +import { + createBrowserHistory, + createRouter as createTanStackRouter, +} from "@tanstack/react-router"; +import { routeTree } from "./routeTree.gen"; +import "./styles.css"; +import type { CreateRouterOptions } from "./types"; -export interface RouterContext { - queryClient: QueryClient; +export type { + ClientRuntimeConfig, CreateRouterOptions, RouterContext, RouterModule +} from "./types"; + +function NotFoundComponent() { + return ( + <div className="min-h-screen flex items-center justify-center bg-background"> + <div className="text-center"> + <h1 className="text-4xl font-bold text-foreground mb-4">404</h1> + <p className="text-muted-foreground mb-8">Page not found</p> + <a + href="/" + className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2" + > + Go Home + </a> + </div> + </div> + ); +} + +function ErrorComponent({ error }: { error: Error }) { + return ( + <div className="min-h-screen flex items-center justify-center bg-background"> + <div className="text-center"> + <h1 className="text-4xl font-bold text-foreground mb-4">Oops!</h1> + <p className="text-muted-foreground mb-4">Something went wrong</p> + <details className="text-sm text-muted-foreground bg-muted p-4 rounded mb-8"> + <summary className="cursor-pointer">Error Details</summary> + <pre className="mt-2 whitespace-pre-wrap text-left"> + {error.message} + </pre> + </details> + <button + type="button" + onClick={() => window.location.reload()} + className="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2" + > + Reload Page + </button> + </div> + </div> + ); +} + +function PendingComponent() { + return <div className="min-h-screen w-full bg-background" />; } -export function createRouter(opts?: { context?: Partial<RouterContext> }) { - const queryClient = opts?.context?.queryClient ?? new QueryClient({ - defaultOptions: { - queries: { - staleTime: 5 * 60 * 1000, - gcTime: 30 * 60 * 1000, - refetchOnWindowFocus: false, - retry: 1, +export function createRouter(opts: CreateRouterOptions = {}) { + const queryClient = + opts.context?.queryClient ?? + new QueryClient({ + defaultOptions: { + queries: { + staleTime: 5 * 60 * 1000, + gcTime: 30 * 60 * 1000, + refetchOnWindowFocus: false, + retry: 1, + }, }, - }, - }); + }); + + const history = opts.history ?? createBrowserHistory(); const router = createTanStackRouter({ routeTree, + history, context: { queryClient, + assetsUrl: opts.context?.assetsUrl ?? "", + runtimeConfig: opts.context?.runtimeConfig, }, - defaultPreload: 'intent', + defaultPreload: "intent", scrollRestoration: true, defaultStructuralSharing: true, defaultPreloadStaleTime: 0, + defaultNotFoundComponent: NotFoundComponent, + defaultErrorComponent: ErrorComponent, + defaultPendingComponent: PendingComponent, + defaultPendingMinMs: 100, }); return { router, queryClient }; @@ -34,8 +95,8 @@ export function createRouter(opts?: { context?: Partial<RouterContext> }) { export { routeTree }; -declare module '@tanstack/react-router' { +declare module "@tanstack/react-router" { interface Register { - router: ReturnType<typeof createRouter>['router']; + router: ReturnType<typeof createRouter>["router"]; } } diff --git a/ui/src/routes/__root.tsx b/ui/src/routes/__root.tsx index 870dd52..d3601b3 100644 --- a/ui/src/routes/__root.tsx +++ b/ui/src/routes/__root.tsx @@ -1,53 +1,114 @@ import { TanStackDevtools } from "@tanstack/react-devtools"; -import type { QueryClient } from "@tanstack/react-query"; import { ClientOnly, createRootRouteWithContext, HeadContent, Outlet, + Scripts, } from "@tanstack/react-router"; import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"; +import { ThemeProvider } from "next-themes"; +import { Toaster } from "sonner"; +import type { RouterContext } from "@/types"; import TanStackQueryDevtools from "../integrations/tanstack-query/devtools"; -interface MyRouterContext { - queryClient: QueryClient; -} - -function getAssetBase(): string { - if (typeof window !== "undefined" && window.__RUNTIME_CONFIG__?.ui?.url) { - return window.__RUNTIME_CONFIG__.ui.url; - } - return ""; -} +export const Route = createRootRouteWithContext<RouterContext>()({ + loader: ({ context }) => ({ + assetsUrl: context.assetsUrl || "", + runtimeConfig: context.runtimeConfig, + }), + head: ({ loaderData }) => { + const assetsUrl = loaderData?.assetsUrl || ""; + const runtimeConfig = loaderData?.runtimeConfig; + const siteUrl = runtimeConfig?.hostUrl || ""; + const title = runtimeConfig?.title || "demo.everything"; + const description = + "Demo application showcasing Module Federation with SSR, TanStack Router, and oRPC"; + const siteName = "Every Demo"; + const ogImage = `${assetsUrl}/metadata.png`; -export const Route = createRootRouteWithContext<MyRouterContext>()({ - head: () => { - const assetBase = getAssetBase(); return { meta: [ - { title: "NEAR Agency" }, + { charSet: "utf-8" }, { - name: "description", - content: - "NEAR AI application showcasing Module Federation with SSR, TanStack Router, and oRPC", + name: "viewport", + content: "width=device-width, initial-scale=1.0, viewport-fit=cover", }, + { title }, + { name: "description", content: description }, { name: "theme-color", content: "#171717" }, - { name: "application-name", content: "NEAR Agency" }, + { name: "color-scheme", content: "light dark" }, + { name: "application-name", content: siteName }, { name: "mobile-web-app-capable", content: "yes" }, { name: "apple-mobile-web-app-status-bar-style", content: "black-translucent", }, + { name: "format-detection", content: "telephone=no" }, + { name: "robots", content: "index, follow" }, + { property: "og:title", content: title }, + { property: "og:description", content: description }, + { property: "og:type", content: "website" }, + { property: "og:url", content: siteUrl }, + { property: "og:image", content: ogImage }, + { property: "og:site_name", content: siteName }, + { name: "twitter:card", content: "summary_large_image" }, + { name: "twitter:title", content: title }, + { name: "twitter:description", content: description }, + { name: "twitter:image", content: ogImage }, ], links: [ - { rel: "icon", type: "image/x-icon", href: `${assetBase}/favicon.ico` }, - { rel: "icon", type: "image/svg+xml", href: `${assetBase}/icon.svg` }, + { rel: "canonical", href: siteUrl }, + { rel: "stylesheet", href: `${assetsUrl}/static/css/async/style.css` }, + { rel: "preconnect", href: "https://fonts.googleapis.com" }, + { + rel: "preconnect", + href: "https://fonts.gstatic.com", + crossOrigin: "anonymous", + }, + { rel: "icon", type: "image/x-icon", href: `${assetsUrl}/favicon.ico` }, + { rel: "icon", type: "image/svg+xml", href: `${assetsUrl}/icon.svg` }, { rel: "apple-touch-icon", sizes: "180x180", - href: `${assetBase}/apple-touch-icon.png`, + href: `${assetsUrl}/apple-touch-icon.png`, + }, + { rel: "manifest", href: `${assetsUrl}/manifest.json` }, + ], + scripts: [ + { + src: `${assetsUrl}/remoteEntry.js`, + }, + { + children: `(function(){var t=localStorage.getItem('theme');if(t==='dark'||(!t&&window.matchMedia('(prefers-color-scheme: dark)').matches)){document.documentElement.classList.add('dark');}})();`, + }, + { + type: "application/ld+json", + children: JSON.stringify({ + "@context": "https://schema.org", + "@type": "WebSite", + name: siteName, + url: siteUrl, + description, + }), + }, + { + children: ` +window.__RUNTIME_CONFIG__=${JSON.stringify(runtimeConfig)}; +function __hydrate(){ + var container = window['ui']; + if (!container) { console.error('[Hydrate] Container not found'); return; } + container.init({}).then(function(){ + return container.get('./Hydrate'); + }).then(function(mod){ + return mod().hydrate(); + }).catch(function(e){ + console.error('[Hydrate] Failed:', e); + }); +} +if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',__hydrate);}else{__hydrate();} + `.trim(), }, - { rel: "manifest", href: `${assetBase}/manifest.json` }, ], }; }, @@ -56,23 +117,44 @@ export const Route = createRootRouteWithContext<MyRouterContext>()({ function RootComponent() { return ( - <> - <HeadContent /> - <Outlet /> - <ClientOnly> - <TanStackDevtools - config={{ - position: "bottom-right", + <html lang="en" suppressHydrationWarning> + <head> + <HeadContent /> + <style + dangerouslySetInnerHTML={{ + __html: ` + :root { --host-bg: #ffffff; --host-fg: #171717; } + .dark { --host-bg: #1c1c1e; --host-fg: #fafafa; } + *, *::before, *::after { box-sizing: border-box; } + html { height: 100%; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; color-scheme: light dark; } + body { min-height: 100%; margin: 0; background-color: var(--host-bg); color: var(--host-fg); -webkit-tap-highlight-color: transparent; touch-action: manipulation; transition: background-color 0.2s ease; } + #root { min-height: 100vh; background-color: var(--host-bg); } + @supports (min-height: 100dvh) { #root { min-height: 100dvh; } } + `, }} - plugins={[ - { - name: "Tanstack Router", - render: <TanStackRouterDevtoolsPanel />, - }, - TanStackQueryDevtools, - ]} /> - </ClientOnly> - </> + </head> + <body> + <ThemeProvider attribute="class" defaultTheme="system" enableSystem> + <div id="root"> + <Outlet /> + </div> + <Toaster position="bottom-right" richColors closeButton /> + </ThemeProvider> + <Scripts /> + <ClientOnly> + <TanStackDevtools + config={{ position: "bottom-right" }} + plugins={[ + { + name: "Tanstack Router", + render: <TanStackRouterDevtoolsPanel />, + }, + TanStackQueryDevtools, + ]} + /> + </ClientOnly> + </body> + </html> ); } diff --git a/ui/src/routes/_layout.tsx b/ui/src/routes/_layout.tsx index 26ed92b..547a211 100644 --- a/ui/src/routes/_layout.tsx +++ b/ui/src/routes/_layout.tsx @@ -1,81 +1,21 @@ -import { useSuspenseQuery } from "@tanstack/react-query"; -import { - createFileRoute, - Link, - Outlet, - useRouter, -} from "@tanstack/react-router"; +import { ClientOnly, createFileRoute, Outlet } from "@tanstack/react-router"; import { ThemeToggle } from "../components/theme-toggle"; -import { authClient } from "../lib/auth-client"; -import { sessionQueryOptions } from "../lib/session"; -import { queryClient } from "../utils/orpc"; +import { UserNav } from "../components/user-nav"; export const Route = createFileRoute("/_layout")({ - beforeLoad: async ({ context }) => { - await context.queryClient.ensureQueryData(sessionQueryOptions); - }, component: Layout, }); function Layout() { - const router = useRouter(); - const { data: session } = useSuspenseQuery(sessionQueryOptions); - const accountId = session?.user?.id; - const userRole = (session?.user as { role?: string })?.role; - - const handleSignOut = async () => { - try { - await authClient.signOut(); - await authClient.near.disconnect(); - queryClient.invalidateQueries({ queryKey: ["session"] }); - router.invalidate(); - window.location.href = "/"; - } catch (error) { - console.error("Sign out error:", error); - } - }; - return ( <div className="h-dvh w-full flex flex-col bg-background text-foreground overflow-hidden"> <header className="shrink-0 border-b border-border/50"> <div className="max-w-5xl mx-auto px-4 sm:px-6 py-3 sm:py-4"> <div className="flex items-center justify-end gap-4"> <ThemeToggle /> - {accountId ? ( - <> - {userRole === "admin" && ( - <Link - to="/dashboard" - className="text-xs text-muted-foreground hover:text-foreground transition-colors font-mono" - > - admin - </Link> - )} - <Link - to="/settings" - className="text-xs text-muted-foreground hover:text-foreground transition-colors font-mono" - > - settings - </Link> - <span className="text-xs text-muted-foreground font-mono"> - {accountId} - </span> - <button - type="button" - onClick={handleSignOut} - className="text-xs text-muted-foreground hover:text-foreground transition-colors font-mono" - > - sign out - </button> - </> - ) : ( - <Link - to="/login" - className="text-xs text-muted-foreground hover:text-foreground transition-colors font-mono" - > - login - </Link> - )} + <ClientOnly fallback={<span className="text-xs text-muted-foreground font-mono">...</span>}> + <UserNav /> + </ClientOnly> </div> </div> </header> diff --git a/ui/src/routes/_layout/_authenticated.tsx b/ui/src/routes/_layout/_authenticated.tsx index bb04706..43b114c 100644 --- a/ui/src/routes/_layout/_authenticated.tsx +++ b/ui/src/routes/_layout/_authenticated.tsx @@ -1,7 +1,8 @@ +import { createFileRoute, Outlet, redirect } from "@tanstack/react-router"; import { authClient } from "@/lib/auth-client"; -import { createFileRoute, redirect, Outlet } from "@tanstack/react-router"; export const Route = createFileRoute("/_layout/_authenticated")({ + ssr: false, beforeLoad: async ({ location }) => { const { data: session } = await authClient.getSession(); if (!session?.user) { diff --git a/ui/src/routes/_layout/_authenticated/index.tsx b/ui/src/routes/_layout/_authenticated/index.tsx index ef57272..376b9bc 100644 --- a/ui/src/routes/_layout/_authenticated/index.tsx +++ b/ui/src/routes/_layout/_authenticated/index.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; -import { ChatPage } from "../../../components/chat/ChatPage"; +import { ChatPage } from "../../../components/chat/chat-page"; export const Route = createFileRoute("/_layout/_authenticated/")({ component: IndexPage, diff --git a/ui/src/routes/_layout/_authenticated/settings.tsx b/ui/src/routes/_layout/_authenticated/settings.tsx index 9386449..dd1948c 100644 --- a/ui/src/routes/_layout/_authenticated/settings.tsx +++ b/ui/src/routes/_layout/_authenticated/settings.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; -import { KVEditor } from "../../../components/kv/KVEditor"; +import { KVEditor } from "../../../components/kv/kv-editor"; export const Route = createFileRoute("/_layout/_authenticated/settings")({ component: SettingsPage, diff --git a/ui/src/routes/_layout/_page.tsx b/ui/src/routes/_layout/_page.tsx deleted file mode 100644 index 35e5b21..0000000 --- a/ui/src/routes/_layout/_page.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { createFileRoute, Outlet } from "@tanstack/react-router"; - -export const Route = createFileRoute("/_layout/_page")({ - component: PageLayout, -}); - -function PageLayout() { - return ( - <div className="max-w-4xl mx-auto px-4 md:px-8 py-12"> - <Outlet /> - </div> - ); -} diff --git a/ui/src/routes/_layout/_page/privacy-policy.tsx b/ui/src/routes/_layout/_page/privacy-policy.tsx deleted file mode 100644 index f2bbbc9..0000000 --- a/ui/src/routes/_layout/_page/privacy-policy.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; - -export const Route = createFileRoute("/_layout/_page/privacy-policy")({ - component: PrivacyPolicy, -}); - -function PrivacyPolicy() { - return ( - <> - <h1 className="text-base font-normal mb-2">Privacy Policy</h1> - <p className="text-sm text-muted-foreground mb-8"> - Last updated: December 16, 2025 - </p> - - <div className="bg-muted/30 p-6 rounded-lg mb-8"> - <p className="text-sm text-muted-foreground"> - This is a placeholder for the Privacy Policy. Replace this content with your - actual privacy practices and policies. - </p> - </div> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">1. Introduction</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Introduce your commitment to privacy and the purpose of this policy.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">2. Information We Collect</h2> - <p className="text-muted-foreground mb-3"> - [Placeholder: Describe the types of information collected from users:] - </p> - <ul className="list-disc pl-6 space-y-2 text-muted-foreground"> - <li>Personal information (name, email, shipping address)</li> - <li>Payment information</li> - <li>NEAR wallet addresses</li> - <li>Browser and device information</li> - <li>Usage data and analytics</li> - </ul> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">3. How We Use Your Information</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Explain how collected information is used - order processing, - communications, service improvement, etc.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">4. Information Sharing</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Detail when and with whom information may be shared - payment processors, - shipping partners, legal requirements, etc.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">5. Blockchain and Cryptocurrency</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Explain privacy implications of blockchain transactions, wallet addresses - being public, and NEAR Protocol integration.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">6. Cookies and Tracking</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Describe use of cookies, analytics tools, and tracking technologies.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">7. Data Security</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Outline security measures taken to protect user information and - limitations of security.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">8. Data Retention</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Explain how long different types of data are retained and deletion - policies.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">9. Your Privacy Rights</h2> - <p className="text-muted-foreground mb-3"> - [Placeholder: Detail user rights regarding their personal information:] - </p> - <ul className="list-disc pl-6 space-y-2 text-muted-foreground"> - <li>Access and review your data</li> - <li>Request corrections or updates</li> - <li>Request deletion of your data</li> - <li>Opt-out of marketing communications</li> - <li>Data portability</li> - </ul> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">10. Third-Party Services</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Describe integration with third-party services and their privacy - practices.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">11. International Data Transfers</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: If applicable, explain how data is transferred and protected - internationally.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">12. Children's Privacy</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: State policies regarding collection of information from children under - 13.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">13. Regional Privacy Laws</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Address GDPR (California), and other regional privacy - regulations as applicable.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">14. Policy Updates</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Explain how users will be notified of privacy policy changes.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">15. Contact Us</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Provide contact information for privacy-related questions and data - requests.] - </p> - <hr className="border-t border-border my-6" /> - <p className="text-muted-foreground"> - For privacy-related questions or to exercise your privacy rights, please contact us at{" "} - <a href="mailto:privacy@near.org" className="text-primary hover:underline"> - privacy@near.org - </a> - </p> - </section> - </> - ); -} diff --git a/ui/src/routes/_layout/_page/terms-of-service.tsx b/ui/src/routes/_layout/_page/terms-of-service.tsx deleted file mode 100644 index 95825c5..0000000 --- a/ui/src/routes/_layout/_page/terms-of-service.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { createFileRoute } from "@tanstack/react-router"; - -export const Route = createFileRoute("/_layout/_page/terms-of-service")({ - component: TermsOfService, -}); - -function TermsOfService() { - return ( - <> - <h1 className="text-base font-normal mb-2">Terms of Service</h1> - <p className="text-sm text-muted-foreground mb-8"> - Last updated: December 16, 2025 - </p> - - <div className="bg-muted/30 p-6 rounded-lg mb-8"> - <p className="text-sm text-muted-foreground"> - This is a placeholder for the Terms of Service. Replace this content with your - actual terms and conditions. - </p> - </div> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">1. Acceptance of Terms</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Explain that by using the service, users agree to these terms.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">2. Use of Service</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Define acceptable use of the platform and user responsibilities.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">3. Account Responsibilities</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Detail user account obligations, security, and NEAR wallet integration requirements.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">4. Products and Pricing</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Explain product descriptions, pricing accuracy, and availability disclaimers.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">5. Payment Terms</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Detail payment methods, processing, blockchain transaction terms, and fees.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">6. Shipping and Delivery</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Outline shipping policies, delivery timeframes, and risk of loss transfer.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">7. Returns and Refunds</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Define return policy, refund process, and conditions for returns.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">8. Intellectual Property Rights</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: State ownership of content, trademarks, and user license grants.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">9. Prohibited Activities</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: List prohibited uses including fraud, unauthorized access, and illegal activities.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">10. Disclaimers and Warranties</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Include "as-is" disclaimers and warranty limitations.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">11. Limitation of Liability</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Limit liability for damages, losses, and service interruptions.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">12. Indemnification</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Require user indemnification for violations and third-party claims.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">13. Termination and Suspension</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Define termination rights, suspension conditions, and effects of termination.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">14. Dispute Resolution</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Specify arbitration requirements, class action waivers, and dispute procedures.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">15. Governing Law</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: State applicable jurisdiction and choice of law.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">16. Changes to Terms</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Explain modification rights and user notification procedures.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">17. General Provisions</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Include severability, waiver, entire agreement, and assignment clauses.] - </p> - </section> - - <section className="mb-8"> - <h2 className="text-xl font-semibold mb-4">18. Contact Information</h2> - <p className="text-muted-foreground mb-4"> - [Placeholder: Provide official contact details for legal notices and questions.] - </p> - <hr className="border-t border-border my-6" /> - <p className="text-muted-foreground"> - For questions about these Terms of Service, please contact us at{" "} - <a href="mailto:legal@near.org" className="text-primary hover:underline"> - legal@near.org - </a> - </p> - </section> - </> - ); -} diff --git a/ui/src/routes/_layout/login.tsx b/ui/src/routes/_layout/login.tsx index 842d34b..fd685dd 100644 --- a/ui/src/routes/_layout/login.tsx +++ b/ui/src/routes/_layout/login.tsx @@ -4,33 +4,12 @@ import { toast } from "sonner"; import { authClient } from "../../lib/auth-client"; import { queryClient } from "../../utils/orpc"; -type AuthErrorLike = { - code?: string; - message?: string; -}; - -function getErrorCode(error: unknown): string | undefined { - if (typeof error === "object" && error) { - const code = (error as AuthErrorLike).code; - if (typeof code === "string") return code; - } - return undefined; -} - -function getErrorMessage(error: unknown): string | undefined { - if (error instanceof Error) return error.message; - if (typeof error === "object" && error) { - const message = (error as AuthErrorLike).message; - if (typeof message === "string") return message; - } - return undefined; -} - type SearchParams = { redirect?: string; }; export const Route = createFileRoute("/_layout/login")({ + ssr: false, validateSearch: (search: Record<string, unknown>): SearchParams => ({ redirect: typeof search.redirect === "string" ? search.redirect : undefined, }), @@ -58,20 +37,19 @@ function LoginPage() { setIsConnectingWallet(true); try { await authClient.requestSignIn.near( - { recipient: import.meta.env.PUBLIC_ACCOUNT_ID || "every.near" }, + { recipient: window.__RUNTIME_CONFIG__?.account ?? "every.near" }, { onSuccess: () => { setIsConnectingWallet(false); toast.success("Wallet connected"); }, - onError: (error: unknown) => { + onError: (error: any) => { setIsConnectingWallet(false); console.error("Wallet connection failed:", error); - const errorCode = getErrorCode(error); const errorMessage = - errorCode === "SIGNER_NOT_AVAILABLE" + error.code === "SIGNER_NOT_AVAILABLE" ? "NEAR wallet not available" - : getErrorMessage(error) || "Failed to connect wallet"; + : error.message || "Failed to connect wallet"; toast.error(errorMessage); }, } @@ -87,7 +65,7 @@ function LoginPage() { setIsSigningInWithNear(true); try { await authClient.signIn.near( - { recipient: import.meta.env.PUBLIC_ACCOUNT_ID || "every.near" }, + { recipient: window.__RUNTIME_CONFIG__?.account ?? "every.near" }, { onSuccess: () => { setIsSigningInWithNear(false); @@ -96,17 +74,19 @@ function LoginPage() { navigate({ to: redirect ?? "/", replace: true }); toast.success(`Signed in as: ${accountId}`); }, - onError: (error: unknown) => { + onError: (error: any) => { setIsSigningInWithNear(false); console.error("NEAR sign in error:", error); - if (getErrorCode(error) === "NONCE_NOT_FOUND") { + if ((error as any)?.code === "NONCE_NOT_FOUND") { toast.error("Session expired. Please reconnect your wallet."); handleWalletDisconnect(); return; } - toast.error(getErrorMessage(error) || "Authentication failed"); + toast.error( + error instanceof Error ? error.message : "Authentication failed" + ); }, } ); @@ -114,7 +94,7 @@ function LoginPage() { setIsSigningInWithNear(false); console.error("NEAR sign in error:", error); - if (getErrorCode(error) === "NONCE_NOT_FOUND") { + if ((error as any)?.code === "NONCE_NOT_FOUND") { toast.error("Session expired. Please reconnect your wallet."); handleWalletDisconnect(); return; @@ -145,10 +125,6 @@ function LoginPage() { isSigningInWithNear || isDisconnectingWallet; - if (!authClient) { - return null; - } - return ( <div className="min-h-[80vh] w-full flex items-center justify-center px-6"> <div className="w-full max-w-sm space-y-3"> diff --git a/ui/src/types/index.ts b/ui/src/types/index.ts index 5b10c68..39901a9 100644 --- a/ui/src/types/index.ts +++ b/ui/src/types/index.ts @@ -1 +1,63 @@ -export type { Network } from "near-kit"; \ No newline at end of file +export type { Network } from "near-kit"; + +import type { QueryClient } from "@tanstack/react-query"; +import type { AnyRouteMatch, AnyRouter, RouterHistory } from "@tanstack/react-router"; + +// TODO: shared with host +export interface ClientRuntimeConfig { + env: string; + account: string; + title: string; + hostUrl: string; + assetsUrl: string; + apiBase: string; + rpcBase: string; +} + +export interface RouterContext { + queryClient: QueryClient; + assetsUrl: string; + runtimeConfig?: ClientRuntimeConfig; +} + +export interface CreateRouterOptions { + history?: RouterHistory; + context?: Partial<RouterContext>; +} + +export type HeadMeta = NonNullable<AnyRouteMatch["meta"]>[number]; +export type HeadLink = NonNullable<AnyRouteMatch["links"]>[number]; +export type HeadScript = NonNullable<AnyRouteMatch["headScripts"]>[number]; + +export interface HeadData { + meta: HeadMeta[]; + links: HeadLink[]; + scripts: HeadScript[]; +} + +export interface RenderOptions { + assetsUrl: string; + runtimeConfig: ClientRuntimeConfig; +} + +export interface RenderResult { + stream: ReadableStream; + statusCode: number; + headers: Headers; +} + +export interface RouterModule { + createRouter: (opts?: CreateRouterOptions) => { + router: AnyRouter; + queryClient: QueryClient; + }; + getRouteHead: ( + pathname: string, + context?: Partial<RouterContext> + ) => Promise<HeadData>; + renderToStream: ( + request: Request, + options: RenderOptions + ) => Promise<RenderResult>; + routeTree: AnyRouter["routeTree"]; +} diff --git a/ui/src/utils/orpc.ts b/ui/src/utils/orpc.ts index 2397d46..ddcc936 100644 --- a/ui/src/utils/orpc.ts +++ b/ui/src/utils/orpc.ts @@ -16,7 +16,8 @@ function getApiUrl(): string { if (typeof window === 'undefined') { throw new Error('RPCLink is not allowed on the server side. Use server-side client instead.'); } - return `${window.location.origin}/api/rpc`; + const base = window.__RUNTIME_CONFIG__?.rpcBase; + return base ? `${window.location.origin}${base}` : `${window.location.origin}/api/rpc`; } export const queryClient = new QueryClient({