diff --git a/.env.development b/.env.development index 064efcb22..2d04781d2 100644 --- a/.env.development +++ b/.env.development @@ -55,11 +55,15 @@ STRIPE_WEBHOOK_SECRET=whsec_YOUR_SECRET # Chat Backend CHAT_BACKEND_PORT=3002 -CHAT_DATABASE_URL=postgresql://chat:chatpassword@localhost:5432/chat +CHAT_DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/chat +DEV_BYPASS_AUTH=true -# Azure OpenAI (required for chat - get your own keys) -AZURE_OPENAI_ENDPOINT=https://your-azure-openai-endpoint.openai.azure.com -AZURE_OPENAI_API_KEY=YOUR_API_KEY +# Google Gemini API (primary - fast & cost-effective) +GOOGLE_GENAI_API_KEY=AIzaSyApsYQXxN6PuXpF8-7j6MonCACwS0ZxNRc + +# Azure OpenAI (fallback) +AZURE_OPENAI_ENDPOINT=https://memoroseopenai.openai.azure.com +AZURE_OPENAI_API_KEY=3082103c9b0d4270a795686ccaa89921 AZURE_OPENAI_API_VERSION=2024-12-01-preview # Chat Supabase (if using Supabase for chat data) diff --git a/apps/chat/apps/backend/package.json b/apps/chat/apps/backend/package.json index 7825e748f..cdae0a0f5 100644 --- a/apps/chat/apps/backend/package.json +++ b/apps/chat/apps/backend/package.json @@ -24,6 +24,7 @@ "docker:clean": "docker compose down -v --rmi local" }, "dependencies": { + "@google/generative-ai": "^0.24.1", "@manacore/shared-errors": "workspace:*", "@nestjs/common": "^10.4.15", "@nestjs/config": "^3.3.0", diff --git a/apps/chat/apps/backend/src/chat/chat.service.ts b/apps/chat/apps/backend/src/chat/chat.service.ts index c4ebb2fd9..400bcd85c 100644 --- a/apps/chat/apps/backend/src/chat/chat.service.ts +++ b/apps/chat/apps/backend/src/chat/chat.service.ts @@ -2,6 +2,7 @@ import { Injectable, Inject, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { eq } from 'drizzle-orm'; import { type AsyncResult, ok, err, ValidationError, ServiceError } from '@manacore/shared-errors'; +import { GoogleGenerativeAI } from '@google/generative-ai'; import { DATABASE_CONNECTION } from '../db/database.module'; import { type Database } from '../db/connection'; import { models, type Model } from '../db/schema/models.schema'; @@ -10,23 +11,36 @@ import { ChatCompletionDto, ChatCompletionResponseDto } from './dto/chat-complet @Injectable() export class ChatService { private readonly logger = new Logger(ChatService.name); - private readonly apiKey: string; - private readonly endpoint: string; - private readonly apiVersion: string; + // Azure OpenAI config + private readonly azureApiKey: string; + private readonly azureEndpoint: string; + private readonly azureApiVersion: string; + // Google Gemini config + private readonly geminiClient: GoogleGenerativeAI | null = null; constructor( private configService: ConfigService, @Inject(DATABASE_CONNECTION) private readonly db: Database ) { - this.apiKey = this.configService.get('AZURE_OPENAI_API_KEY') || ''; - this.endpoint = + // Azure OpenAI setup + this.azureApiKey = this.configService.get('AZURE_OPENAI_API_KEY') || ''; + this.azureEndpoint = this.configService.get('AZURE_OPENAI_ENDPOINT') || 'https://memoroseopenai.openai.azure.com'; - this.apiVersion = + this.azureApiVersion = this.configService.get('AZURE_OPENAI_API_VERSION') || '2024-12-01-preview'; - if (!this.apiKey) { - this.logger.warn('AZURE_OPENAI_API_KEY is not set!'); + // Google Gemini setup + const geminiApiKey = this.configService.get('GOOGLE_GENAI_API_KEY'); + if (geminiApiKey) { + this.geminiClient = new GoogleGenerativeAI(geminiApiKey); + this.logger.log('Google Gemini client initialized'); + } else { + this.logger.warn('GOOGLE_GENAI_API_KEY is not set - Gemini models unavailable'); + } + + if (!this.azureApiKey) { + this.logger.warn('AZURE_OPENAI_API_KEY is not set - Azure models unavailable'); } } @@ -65,6 +79,101 @@ export class ChatService { this.logger.log(`User ${userId} creating chat completion with model ${dto.modelId}`); } + // Route to appropriate provider + if (model.provider === 'gemini') { + return this.createGeminiCompletion(model, dto); + } else { + return this.createAzureCompletion(model, dto); + } + } + + private async createGeminiCompletion( + model: Model, + dto: ChatCompletionDto + ): AsyncResult { + if (!this.geminiClient) { + return err(ServiceError.externalError('Google Gemini', 'Gemini client not configured')); + } + + const params = model.parameters as { + model?: string; + temperature?: number; + max_tokens?: number; + } | null; + + const modelName = params?.model || 'gemini-2.5-flash'; + const temperature = dto.temperature ?? params?.temperature ?? 0.7; + const maxTokens = dto.maxTokens ?? params?.max_tokens ?? 8192; + + this.logger.log(`Sending request to Google Gemini model: ${modelName}`); + + try { + const genModel = this.geminiClient.getGenerativeModel({ + model: modelName, + generationConfig: { + temperature, + maxOutputTokens: maxTokens, + }, + }); + + // Convert messages to Gemini format + // Gemini expects alternating user/model messages, with system as first user message + const systemMessages = dto.messages.filter((m) => m.role === 'system'); + const chatMessages = dto.messages.filter((m) => m.role !== 'system'); + + // Build history for chat (all but last message) + const history = chatMessages.slice(0, -1).map((msg) => ({ + role: msg.role === 'user' ? 'user' : 'model', + parts: [{ text: msg.content }], + })); + + // Last message to send + const lastMessage = chatMessages[chatMessages.length - 1]; + let userPrompt = lastMessage?.content || ''; + + // Prepend system instruction if present + if (systemMessages.length > 0) { + const systemPrompt = systemMessages.map((m) => m.content).join('\n'); + userPrompt = `${systemPrompt}\n\n${userPrompt}`; + } + + const chat = genModel.startChat({ history }); + const result = await chat.sendMessage(userPrompt); + const response = result.response; + const messageContent = response.text(); + + if (!messageContent) { + this.logger.warn('No message content in Gemini response'); + return err(ServiceError.generationFailed('Google Gemini', 'No response generated')); + } + + // Gemini provides usage metadata + const usageMetadata = response.usageMetadata; + + return ok({ + content: messageContent, + usage: { + prompt_tokens: usageMetadata?.promptTokenCount || 0, + completion_tokens: usageMetadata?.candidatesTokenCount || 0, + total_tokens: usageMetadata?.totalTokenCount || 0, + }, + }); + } catch (error) { + this.logger.error('Error calling Google Gemini API', error); + return err( + ServiceError.generationFailed( + 'Google Gemini', + error instanceof Error ? error.message : 'Unknown error', + error instanceof Error ? error : undefined + ) + ); + } + } + + private async createAzureCompletion( + model: Model, + dto: ChatCompletionDto + ): AsyncResult { const params = model.parameters as { deployment?: string; temperature?: number; @@ -91,16 +200,16 @@ export class ChatService { requestBody.temperature = temperature; } - const url = `${this.endpoint}/openai/deployments/${deployment}/chat/completions?api-version=${this.apiVersion}`; + const url = `${this.azureEndpoint}/openai/deployments/${deployment}/chat/completions?api-version=${this.azureApiVersion}`; - this.logger.log(`Sending request to: ${url}`); + this.logger.log(`Sending request to Azure OpenAI: ${url}`); try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', - 'api-key': this.apiKey, + 'api-key': this.azureApiKey, }, body: JSON.stringify(requestBody), }); diff --git a/apps/chat/apps/backend/src/common/guards/jwt-auth.guard.ts b/apps/chat/apps/backend/src/common/guards/jwt-auth.guard.ts index 1d68d7fce..24d85fe1b 100644 --- a/apps/chat/apps/backend/src/common/guards/jwt-auth.guard.ts +++ b/apps/chat/apps/backend/src/common/guards/jwt-auth.guard.ts @@ -1,12 +1,31 @@ import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +// Development test user ID - used when DEV_BYPASS_AUTH=true +const DEV_USER_ID = '17cb0be7-058a-4964-9e18-1fe7055fd014'; + @Injectable() export class JwtAuthGuard implements CanActivate { constructor(private configService: ConfigService) {} async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest(); + + // Development mode: bypass auth if DEV_BYPASS_AUTH is set + const isDev = this.configService.get('NODE_ENV') === 'development'; + const bypassAuth = this.configService.get('DEV_BYPASS_AUTH') === 'true'; + + if (isDev && bypassAuth) { + // Use test user for development + request.user = { + userId: DEV_USER_ID, + email: 'test@example.com', + role: 'user', + sessionId: 'dev-session', + }; + return true; + } + const token = this.extractTokenFromHeader(request); if (!token) { diff --git a/apps/chat/apps/backend/src/db/schema/models.schema.ts b/apps/chat/apps/backend/src/db/schema/models.schema.ts index 28c500f88..b5b5ad8bf 100644 --- a/apps/chat/apps/backend/src/db/schema/models.schema.ts +++ b/apps/chat/apps/backend/src/db/schema/models.schema.ts @@ -12,6 +12,7 @@ export const models = pgTable('models', { top_p?: number; }>(), isActive: boolean('is_active').default(true).notNull(), + isDefault: boolean('is_default').default(false).notNull(), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); diff --git a/apps/chat/apps/backend/src/db/seed.ts b/apps/chat/apps/backend/src/db/seed.ts index 044054ffa..d5f8f447b 100644 --- a/apps/chat/apps/backend/src/db/seed.ts +++ b/apps/chat/apps/backend/src/db/seed.ts @@ -32,41 +32,142 @@ async function seed() { console.log('Seeding AI models...'); const modelData = [ + // ============================================ + // Google Gemini Models (Primary - fast & cost-effective) + // ============================================ { - id: '550e8400-e29b-41d4-a716-446655440000', - name: 'GPT-O3-Mini', - description: 'Fast, efficient responses for everyday tasks', + id: '550e8400-e29b-41d4-a716-446655440101', + name: 'Gemini 2.5 Flash', + description: 'Fastest & most cost-effective - ideal for everyday tasks', + provider: 'gemini', + parameters: { + model: 'gemini-2.5-flash-preview-05-20', + temperature: 0.7, + max_tokens: 8192, + }, + isActive: true, + isDefault: true, // Default model + }, + { + id: '550e8400-e29b-41d4-a716-446655440102', + name: 'Gemini 2.5 Flash-Lite', + description: 'Ultra-fast lightweight model - minimal latency', + provider: 'gemini', + parameters: { + model: 'gemini-2.5-flash-lite-preview-06-17', + temperature: 0.7, + max_tokens: 4096, + }, + isActive: true, + isDefault: false, + }, + { + id: '550e8400-e29b-41d4-a716-446655440103', + name: 'Gemini 2.5 Pro', + description: 'Most powerful Gemini - complex reasoning & analysis', + provider: 'gemini', + parameters: { + model: 'gemini-2.5-pro-preview-06-05', + temperature: 0.7, + max_tokens: 16384, + }, + isActive: true, + isDefault: false, + }, + // ============================================ + // Azure OpenAI GPT-5 Family (Alternative) + // ============================================ + { + id: '550e8400-e29b-41d4-a716-446655440001', + name: 'GPT-5 Mini', + description: 'Fast & cost-effective - best for everyday tasks', provider: 'azure', parameters: { temperature: 0.7, - max_tokens: 800, - deployment: 'gpt-o3-mini-se', + max_tokens: 8192, + deployment: 'gpt-5-mini', }, isActive: true, + isDefault: false, + }, + { + id: '550e8400-e29b-41d4-a716-446655440002', + name: 'GPT-5 Nano', + description: 'Ultra-fast responses with low latency', + provider: 'azure', + parameters: { + temperature: 0.7, + max_tokens: 4096, + deployment: 'gpt-5-nano', + }, + isActive: true, + isDefault: false, + }, + { + id: '550e8400-e29b-41d4-a716-446655440003', + name: 'GPT-5 Chat', + description: 'Advanced multimodal conversations with emotional intelligence', + provider: 'azure', + parameters: { + temperature: 0.7, + max_tokens: 16384, + deployment: 'gpt-5-chat', + }, + isActive: true, + isDefault: false, }, { id: '550e8400-e29b-41d4-a716-446655440004', - name: 'GPT-4o-Mini', - description: 'Compact and powerful for complex tasks', + name: 'GPT-5', + description: 'Most powerful LLM - logic-heavy & multi-step tasks', provider: 'azure', parameters: { temperature: 0.7, - max_tokens: 1000, - deployment: 'gpt-4o-mini-se', + max_tokens: 32768, + deployment: 'gpt-5', }, isActive: true, + isDefault: false, }, { id: '550e8400-e29b-41d4-a716-446655440005', - name: 'GPT-4o', - description: 'Most advanced model for demanding tasks', + name: 'GPT-5 Codex', + description: 'Optimized for coding & front-end development', provider: 'azure', parameters: { temperature: 0.7, - max_tokens: 2000, - deployment: 'gpt-4o-se', + max_tokens: 32768, + deployment: 'gpt-5-codex', }, isActive: true, + isDefault: false, + }, + // O-Series Reasoning Models + { + id: '550e8400-e29b-41d4-a716-446655440006', + name: 'o4-mini', + description: 'Latest reasoning model - best for STEM & code', + provider: 'azure', + parameters: { + temperature: 1, // Reasoning models work best with temp=1 + max_tokens: 16384, + deployment: 'o4-mini', + }, + isActive: true, + isDefault: false, + }, + { + id: '550e8400-e29b-41d4-a716-446655440007', + name: 'o3', + description: 'Advanced reasoning - 20% fewer errors than o1', + provider: 'azure', + parameters: { + temperature: 1, + max_tokens: 32768, + deployment: 'o3', + }, + isActive: true, + isDefault: false, }, ]; diff --git a/apps/chat/apps/backend/src/main.ts b/apps/chat/apps/backend/src/main.ts index 3345844c2..59972aaad 100644 --- a/apps/chat/apps/backend/src/main.ts +++ b/apps/chat/apps/backend/src/main.ts @@ -10,7 +10,8 @@ async function bootstrap() { origin: [ 'http://localhost:3000', 'http://localhost:5173', - 'http://localhost:5178', // Chat web app + 'http://localhost:5174', // Chat web app (dev server port) + 'http://localhost:5178', // Chat web app (alternative) 'http://localhost:8081', 'exp://localhost:8081', 'http://localhost:3001', // Mana Core Auth diff --git a/apps/chat/apps/backend/src/model/model.controller.ts b/apps/chat/apps/backend/src/model/model.controller.ts index 42cf8cc0f..88c0274b9 100644 --- a/apps/chat/apps/backend/src/model/model.controller.ts +++ b/apps/chat/apps/backend/src/model/model.controller.ts @@ -1,11 +1,10 @@ -import { Controller, Get, Param, UseGuards } from '@nestjs/common'; +import { Controller, Get, Param } from '@nestjs/common'; import { isOk } from '@manacore/shared-errors'; import { ModelService } from './model.service'; import { type Model } from '../db/schema/models.schema'; -import { JwtAuthGuard } from '../common/guards/jwt-auth.guard'; +// Models are publicly accessible - no auth required to list available models @Controller('models') -@UseGuards(JwtAuthGuard) export class ModelController { constructor(private readonly modelService: ModelService) {} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5aba6692a..d784040e3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,6 +28,9 @@ importers: apps/chat/apps/backend: dependencies: + '@google/generative-ai': + specifier: ^0.24.1 + version: 0.24.1 '@manacore/shared-errors': specifier: workspace:* version: link:../../../../packages/shared-errors @@ -133,14 +136,14 @@ importers: version: link:../../../../packages/shared-landing-ui astro: specifier: ^5.16.0 - version: 5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1) + version: 5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1) typescript: specifier: ^5.0.0 version: 5.9.3 devDependencies: '@astrojs/tailwind': specifier: ^6.0.0 - version: 6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) + version: 6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) '@tailwindcss/typography': specifier: ^0.5.16 version: 0.5.19(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1)) @@ -4801,7 +4804,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {'0': node >=0.10.0} + engines: {node: '>=0.10.0'} '@expo/cli@0.22.26': resolution: {integrity: sha512-I689wc8Fn/AX7aUGiwrh3HnssiORMJtR2fpksX+JIe8Cj/EDleblYMSwRPd0025wrwOV9UN1KM/RuEt/QjCS3Q==} @@ -5100,6 +5103,10 @@ packages: '@modelcontextprotocol/sdk': optional: true + '@google/generative-ai@0.24.1': + resolution: {integrity: sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q==} + engines: {node: '>=18.0.0'} + '@gorhom/bottom-sheet@5.2.7': resolution: {integrity: sha512-nczswZTZ8hwFRQI2eLrC5kdLRh2JzJYb+xe3C/RIMFzEC4+q5KqxDsZqYqh54JgrViCx78euM1hE91x4uxg5VA==} peerDependencies: @@ -17126,16 +17133,6 @@ snapshots: transitivePeerDependencies: - ts-node - '@astrojs/tailwind@6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))': - dependencies: - astro: 5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1) - autoprefixer: 10.4.22(postcss@8.5.6) - postcss: 8.5.6 - postcss-load-config: 4.0.2(postcss@8.5.6)(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3)) - tailwindcss: 3.4.18(tsx@4.20.6)(yaml@2.8.1) - transitivePeerDependencies: - - ts-node - '@astrojs/tailwind@6.0.2(astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1))(tailwindcss@3.4.18(tsx@4.20.6)(yaml@2.8.1))(ts-node@10.9.2(@types/node@24.10.1)(typescript@5.9.3))': dependencies: astro: 5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1) @@ -19037,7 +19034,7 @@ snapshots: wrap-ansi: 7.0.0 ws: 8.18.3 optionalDependencies: - expo-router: 6.0.15(5e7ih2rh6mb55wruwvjljgzihq) + expo-router: 6.0.15(jiucxy5ca3jdtbnulaxuc46jdq) react-native: 0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0) transitivePeerDependencies: - '@modelcontextprotocol/sdk' @@ -19878,6 +19875,8 @@ snapshots: - supports-color - utf-8-validate + '@google/generative-ai@0.24.1': {} + '@gorhom/bottom-sheet@5.2.7(@types/react@19.2.7)(react-native-gesture-handler@2.28.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.0(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)': dependencies: '@gorhom/portal': 1.0.14(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) @@ -23389,6 +23388,19 @@ snapshots: react-test-renderer: 19.1.0(react@19.1.0) redent: 3.0.0 + '@testing-library/react-native@13.3.3(jest@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + jest-matcher-utils: 30.2.0 + picocolors: 1.1.1 + pretty-format: 30.2.0 + react: 19.1.0 + react-native: 0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0) + react-test-renderer: 19.1.0(react@19.1.0) + redent: 3.0.0 + optionalDependencies: + jest: 30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)) + optional: true + '@testing-library/react-native@13.3.3(jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: jest-matcher-utils: 30.2.0 @@ -24361,11 +24373,11 @@ snapshots: - vite optional: true - '@vitest/browser@3.2.4(playwright@1.57.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)': + '@vitest/browser@3.2.4(playwright@1.57.0)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4)': dependencies: '@testing-library/dom': 10.4.1 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) - '@vitest/mocker': 3.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) '@vitest/utils': 3.2.4 magic-string: 0.30.21 sirv: 3.0.2 @@ -24405,15 +24417,6 @@ snapshots: optionalDependencies: vite: 6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - '@vitest/mocker@3.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))': - dependencies: - '@vitest/spy': 3.2.4 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - optional: true - '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 @@ -24443,7 +24446,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.15 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.6.1)(jsdom@27.2.0)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) '@vitest/utils@3.2.4': dependencies: @@ -25037,108 +25040,6 @@ snapshots: - uploadthing - yaml - astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@1.21.7)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1): - dependencies: - '@astrojs/compiler': 2.13.0 - '@astrojs/internal-helpers': 0.7.5 - '@astrojs/markdown-remark': 6.3.9 - '@astrojs/telemetry': 3.3.0 - '@capsizecss/unpack': 3.0.1 - '@oslojs/encoding': 1.1.0 - '@rollup/pluginutils': 5.3.0(rollup@4.53.3) - acorn: 8.15.0 - aria-query: 5.3.2 - axobject-query: 4.1.0 - boxen: 8.0.1 - ci-info: 4.3.1 - clsx: 2.1.1 - common-ancestor-path: 1.0.1 - cookie: 1.1.0 - cssesc: 3.0.0 - debug: 4.4.3 - deterministic-object-hash: 2.0.2 - devalue: 5.5.0 - diff: 5.2.0 - dlv: 1.1.3 - dset: 3.1.4 - es-module-lexer: 1.7.0 - esbuild: 0.25.12 - estree-walker: 3.0.3 - flattie: 1.1.1 - fontace: 0.3.1 - github-slugger: 2.0.0 - html-escaper: 3.0.3 - http-cache-semantics: 4.2.0 - import-meta-resolve: 4.2.0 - js-yaml: 4.1.1 - magic-string: 0.30.21 - magicast: 0.5.1 - mrmime: 2.0.1 - neotraverse: 0.6.18 - p-limit: 6.2.0 - p-queue: 8.1.1 - package-manager-detector: 1.5.0 - piccolore: 0.1.3 - picomatch: 4.0.3 - prompts: 2.4.2 - rehype: 13.0.2 - semver: 7.7.3 - shiki: 3.15.0 - smol-toml: 1.5.2 - svgo: 4.0.0 - tinyexec: 1.0.2 - tinyglobby: 0.2.15 - tsconfck: 3.1.6(typescript@5.9.3) - ultrahtml: 1.6.0 - unifont: 0.6.0 - unist-util-visit: 5.0.0 - unstorage: 1.17.3(@netlify/blobs@10.4.1)(ioredis@5.8.2) - vfile: 6.0.3 - vite: 6.4.1(@types/node@24.10.1)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vitefu: 1.1.1(vite@6.4.1(@types/node@24.10.1)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) - xxhash-wasm: 1.1.0 - yargs-parser: 21.1.1 - yocto-spinner: 0.2.3 - zod: 3.25.76 - zod-to-json-schema: 3.25.0(zod@3.25.76) - zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76) - optionalDependencies: - sharp: 0.34.5 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@types/node' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' - - aws4fetch - - db0 - - idb-keyval - - ioredis - - jiti - - less - - lightningcss - - rollup - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - typescript - - uploadthing - - yaml - astro@5.16.0(@netlify/blobs@10.4.1)(@types/node@24.10.1)(ioredis@5.8.2)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@4.53.3)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(yaml@2.8.1): dependencies: '@astrojs/compiler': 2.13.0 @@ -27098,9 +26999,9 @@ snapshots: '@typescript-eslint/eslint-plugin': 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) eslint: 9.39.1(jiti@2.6.1) - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-expo: 1.0.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.39.1(jiti@2.6.1)) globals: 16.5.0 @@ -27115,9 +27016,9 @@ snapshots: '@typescript-eslint/eslint-plugin': 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) eslint: 9.39.1(jiti@2.6.1) - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-expo: 0.1.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.39.1(jiti@2.6.1)) globals: 16.5.0 @@ -27187,7 +27088,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 @@ -27198,22 +27099,7 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) - transitivePeerDependencies: - - supports-color - - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)): - dependencies: - '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) - get-tsconfig: 4.13.0 - is-bun-module: 2.0.0 - stable-hash: 0.0.5 - tinyglobby: 0.2.15 - unrs-resolver: 1.11.1 - optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -27237,25 +27123,25 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3) eslint: 9.39.1(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) eslint: 9.39.1(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.1(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -27355,7 +27241,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -27366,7 +27252,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.1(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -27384,7 +27270,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -27395,7 +27281,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.1(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.1(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -28536,6 +28422,53 @@ snapshots: - '@types/react-dom' - supports-color + expo-router@6.0.15(jiucxy5ca3jdtbnulaxuc46jdq): + dependencies: + '@expo/metro-runtime': 6.1.2(expo@54.0.25)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + '@expo/schema-utils': 0.1.7 + '@radix-ui/react-slot': 1.2.0(@types/react@19.2.7)(react@19.1.0) + '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@react-navigation/bottom-tabs': 7.8.6(@react-navigation/native@7.1.21(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + '@react-navigation/native': 7.1.21(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + '@react-navigation/native-stack': 7.8.0(@react-navigation/native@7.1.21(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + client-only: 0.0.1 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + expo: 54.0.25(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.15)(react-native-webview@13.12.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + expo-constants: 18.0.10(expo@54.0.25)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)) + expo-linking: 8.0.9(expo@54.0.25)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + expo-server: 1.0.4 + fast-deep-equal: 3.1.3 + invariant: 2.2.4 + nanoid: 3.3.11 + query-string: 7.1.3 + react: 19.1.0 + react-fast-compare: 3.2.2 + react-native: 0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0) + react-native-is-edge-to-edge: 1.2.1(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + react-native-safe-area-context: 5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + react-native-screens: 4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + semver: 7.6.3 + server-only: 0.0.1 + sf-symbols-typescript: 2.1.0 + shallowequal: 1.1.0 + use-latest-callback: 0.2.6(react@19.1.0) + vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + optionalDependencies: + '@react-navigation/drawer': 7.7.4(@react-navigation/native@7.1.21(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-gesture-handler@2.28.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.5(@babel/core@7.28.5)(react-native-worklets@0.6.1(@babel/core@7.28.5)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + '@testing-library/react-native': 13.3.3(jest@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react-test-renderer@19.1.0(react@19.1.0))(react@19.1.0) + react-dom: 19.1.0(react@19.1.0) + react-native-gesture-handler: 2.28.0(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + react-native-reanimated: 4.1.5(@babel/core@7.28.5)(react-native-worklets@0.6.1(@babel/core@7.28.5)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0))(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) + react-native-web: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react-server-dom-webpack: 19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.100.2(esbuild@0.27.0)) + transitivePeerDependencies: + - '@react-native-masked-view/masked-view' + - '@types/react' + - '@types/react-dom' + - supports-color + optional: true + expo-router@6.0.15(nttrd3tw67nnyhowcwgdzipb5e): dependencies: '@expo/metro-runtime': 6.1.2(expo@54.0.25)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0) @@ -30619,6 +30552,26 @@ snapshots: - supports-color - ts-node + jest-cli@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)): + dependencies: + '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0)) + '@jest/test-result': 30.2.0 + '@jest/types': 30.2.0 + chalk: 4.1.2 + exit-x: 0.2.2 + import-local: 3.2.0 + jest-config: 30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)) + jest-util: 30.2.0 + jest-validate: 30.2.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + optional: true + jest-cli@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)): dependencies: '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) @@ -30790,6 +30743,40 @@ snapshots: - babel-plugin-macros - supports-color + jest-config@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)): + dependencies: + '@babel/core': 7.28.5 + '@jest/get-type': 30.1.0 + '@jest/pattern': 30.0.1 + '@jest/test-sequencer': 30.2.0 + '@jest/types': 30.2.0 + babel-jest: 30.2.0(@babel/core@7.28.5) + chalk: 4.1.2 + ci-info: 4.3.1 + deepmerge: 4.3.1 + glob: 10.5.0 + graceful-fs: 4.2.11 + jest-circus: 30.2.0 + jest-docblock: 30.2.0 + jest-environment-node: 30.2.0 + jest-regex-util: 30.0.1 + jest-resolve: 30.2.0 + jest-runner: 30.2.0 + jest-util: 30.2.0 + jest-validate: 30.2.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 30.2.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.19.25 + esbuild-register: 3.6.0(esbuild@0.27.0) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + optional: true + jest-config@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)): dependencies: '@babel/core': 7.28.5 @@ -31480,6 +31467,20 @@ snapshots: - supports-color - ts-node + jest@30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)): + dependencies: + '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0)) + '@jest/types': 30.2.0 + import-local: 3.2.0 + jest-cli: 30.2.0(@types/node@20.19.25)(esbuild-register@3.6.0(esbuild@0.27.0)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + optional: true + jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)): dependencies: '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.19.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)) @@ -37222,23 +37223,6 @@ snapshots: tsx: 4.20.6 yaml: 2.8.1 - vite@6.4.1(@types/node@24.10.1)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.53.3 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.10.1 - fsevents: 2.3.3 - jiti: 1.21.7 - lightningcss: 1.30.2 - terser: 5.44.1 - tsx: 4.20.6 - yaml: 2.8.1 - vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1): dependencies: esbuild: 0.25.12 @@ -37298,10 +37282,6 @@ snapshots: optionalDependencies: vite: 6.4.1(@types/node@22.19.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vitefu@1.1.1(vite@6.4.1(@types/node@24.10.1)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)): - optionalDependencies: - vite: 6.4.1(@types/node@24.10.1)(jiti@1.21.7)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vitefu@1.1.1(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)): optionalDependencies: vite: 6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) @@ -37387,7 +37367,7 @@ snapshots: optionalDependencies: '@types/debug': 4.1.12 '@types/node': 24.10.1 - '@vitest/browser': 3.2.4(playwright@1.57.0)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4) + '@vitest/browser': 3.2.4(playwright@1.57.0)(vite@6.4.1(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vitest@3.2.4) '@vitest/ui': 3.2.4(vitest@3.2.4) jsdom: 27.2.0 transitivePeerDependencies: