mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 17:41:09 +02:00
feat(manadeck): implement AI deck generation with Google Gemini
- Add AiService using Google Gemini Flash 2.0 for card generation - Support all card types: text, flashcard, quiz, mixed - Implement full generateDeckWithAI endpoint with: - Credit validation and consumption - Structured JSON output with response schema - Deck and card creation in PostgreSQL - Comprehensive error handling - Add @google/genai dependency - Update .env.example with GOOGLE_GENAI_API_KEY - Support difficulty levels (beginner/intermediate/advanced) - Support multiple languages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
be9df4aa85
commit
4bdb5dea85
7 changed files with 717 additions and 84 deletions
|
|
@ -5,16 +5,17 @@ PORT=8080
|
|||
# Mana Core Configuration
|
||||
MANA_SERVICE_URL=https://mana-core-middleware-111768794939.europe-west3.run.app
|
||||
APP_ID=your-app-id-from-mana
|
||||
SERVICE_KEY=your-service-key-from-mana-core # REQUIRED for credit operations
|
||||
MANA_SUPABASE_SECRET_KEY=your-service-key-from-mana-core # REQUIRED for credit operations
|
||||
SIGNUP_REDIRECT_URL=https://manadeck.com/welcome
|
||||
|
||||
# Supabase Configuration (Your app's database)
|
||||
SUPABASE_URL=https://your-project.supabase.co
|
||||
SUPABASE_ANON_KEY=your-anon-key
|
||||
SUPABASE_SERVICE_KEY=your-service-key
|
||||
# PostgreSQL Database (Drizzle ORM)
|
||||
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/manadeck
|
||||
|
||||
# AI Services (Google Gemini)
|
||||
GOOGLE_GENAI_API_KEY=your-google-genai-api-key # Get from https://aistudio.google.com/apikey
|
||||
|
||||
# JWT Configuration
|
||||
JWT_SECRET=your-jwt-secret
|
||||
|
||||
# CORS Configuration
|
||||
FRONTEND_URL=http://localhost:8081
|
||||
FRONTEND_URL=http://localhost:8081
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@
|
|||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@manacore/manadeck-database": "workspace:*",
|
||||
"@google/genai": "^1.14.0",
|
||||
"@mana-core/nestjs-integration": "git+https://github.com/Memo-2023/mana-core-nestjs-package.git",
|
||||
"@manacore/manadeck-database": "workspace:*",
|
||||
"@nestjs/axios": "^4.0.1",
|
||||
"@nestjs/common": "^11.0.1",
|
||||
"@nestjs/config": "^4.0.2",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { ApiController } from './controllers/api.controller';
|
|||
import { PublicController } from './controllers/public.controller';
|
||||
import { HealthController } from './controllers/health.controller';
|
||||
import { validationSchema } from './config/validation.schema';
|
||||
import { AiService } from './services/ai.service';
|
||||
import {
|
||||
DatabaseModule,
|
||||
DeckRepository,
|
||||
|
|
@ -64,6 +65,8 @@ import {
|
|||
],
|
||||
providers: [
|
||||
AppService,
|
||||
// AI Service
|
||||
AiService,
|
||||
// Database repositories
|
||||
DeckRepository,
|
||||
CardRepository,
|
||||
|
|
|
|||
|
|
@ -20,4 +20,7 @@ export const validationSchema = Joi.object({
|
|||
|
||||
// CORS
|
||||
FRONTEND_URL: Joi.string().uri().optional(),
|
||||
|
||||
// AI Services
|
||||
GOOGLE_GENAI_API_KEY: Joi.string().optional(),
|
||||
});
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import { Controller, Get, Post, Put, Delete, Body, Param, UseGuards, Logger, BadRequestException, NotImplementedException } from '@nestjs/common';
|
||||
import { Controller, Get, Post, Put, Delete, Body, Param, UseGuards, Logger, BadRequestException, ServiceUnavailableException } from '@nestjs/common';
|
||||
import { AuthGuard } from '@mana-core/nestjs-integration/guards';
|
||||
import { CurrentUser } from '@mana-core/nestjs-integration/decorators';
|
||||
import { CreditClientService } from '@mana-core/nestjs-integration';
|
||||
import { CreditOperationType, getCreditCost, getOperationDescription } from '../config/credit-operations';
|
||||
import { DeckRepository, CardRepository, UserStatsRepository } from '../database';
|
||||
import { AiService, CardType } from '../services/ai.service';
|
||||
|
||||
@Controller('api')
|
||||
@UseGuards(AuthGuard)
|
||||
|
|
@ -15,6 +16,7 @@ export class ApiController {
|
|||
private readonly deckRepository: DeckRepository,
|
||||
private readonly cardRepository: CardRepository,
|
||||
private readonly userStatsRepository: UserStatsRepository,
|
||||
private readonly aiService: AiService,
|
||||
) {}
|
||||
|
||||
@Get('profile')
|
||||
|
|
@ -151,12 +153,157 @@ export class ApiController {
|
|||
async generateDeckWithAI(@CurrentUser() user: any, @Body() requestData: any) {
|
||||
this.logger.log(`AI deck generation requested by user: ${user.sub}`);
|
||||
|
||||
// TODO: Implement AI deck generation with a self-hosted solution
|
||||
// This endpoint previously used Supabase Edge Functions which are no longer available
|
||||
throw new NotImplementedException({
|
||||
error: 'not_implemented',
|
||||
message: 'AI deck generation is currently being migrated to a new infrastructure. Please check back later.',
|
||||
});
|
||||
// Check if AI service is available
|
||||
if (!this.aiService.isAvailable()) {
|
||||
throw new ServiceUnavailableException({
|
||||
error: 'ai_service_unavailable',
|
||||
message: 'AI service is not configured. Please contact support.',
|
||||
});
|
||||
}
|
||||
|
||||
// Validate request
|
||||
const { prompt, deckTitle, deckDescription, cardCount = 10, cardTypes, difficulty, tags, language } = requestData;
|
||||
|
||||
if (!prompt || !deckTitle) {
|
||||
throw new BadRequestException({
|
||||
error: 'validation_failed',
|
||||
message: 'prompt and deckTitle are required',
|
||||
});
|
||||
}
|
||||
|
||||
if (cardCount < 1 || cardCount > 50) {
|
||||
throw new BadRequestException({
|
||||
error: 'validation_failed',
|
||||
message: 'cardCount must be between 1 and 50',
|
||||
});
|
||||
}
|
||||
|
||||
// Validate card types
|
||||
const validCardTypes: CardType[] = ['text', 'flashcard', 'quiz', 'mixed'];
|
||||
const requestedTypes: CardType[] = cardTypes || ['flashcard', 'quiz'];
|
||||
const invalidTypes = requestedTypes.filter(t => !validCardTypes.includes(t));
|
||||
if (invalidTypes.length > 0) {
|
||||
throw new BadRequestException({
|
||||
error: 'validation_failed',
|
||||
message: `Invalid card types: ${invalidTypes.join(', ')}. Valid types: ${validCardTypes.join(', ')}`,
|
||||
});
|
||||
}
|
||||
|
||||
const operationType = CreditOperationType.AI_DECK_GENERATION;
|
||||
const creditCost = getCreditCost(operationType);
|
||||
|
||||
try {
|
||||
// 1. Pre-flight credit validation
|
||||
const validation = await this.creditClient.validateCredits(
|
||||
user.sub,
|
||||
operationType,
|
||||
creditCost,
|
||||
);
|
||||
|
||||
if (!validation.hasCredits) {
|
||||
this.logger.warn(
|
||||
`User ${user.sub} has insufficient credits for AI deck generation. Required: ${creditCost}, Available: ${validation.availableCredits}`,
|
||||
);
|
||||
|
||||
throw new BadRequestException({
|
||||
error: 'insufficient_credits',
|
||||
message: `Insufficient mana. Required: ${creditCost}, Available: ${validation.availableCredits}`,
|
||||
requiredCredits: creditCost,
|
||||
availableCredits: validation.availableCredits,
|
||||
operation: getOperationDescription(operationType),
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Generate cards with AI
|
||||
this.logger.log(`Generating ${cardCount} cards with AI for user ${user.sub}...`);
|
||||
const aiResult = await this.aiService.generateDeck({
|
||||
prompt,
|
||||
deckTitle,
|
||||
deckDescription,
|
||||
cardCount,
|
||||
cardTypes: requestedTypes,
|
||||
difficulty: difficulty || 'intermediate',
|
||||
language: language || 'en',
|
||||
});
|
||||
|
||||
if (!aiResult.success || aiResult.cards.length === 0) {
|
||||
throw new BadRequestException({
|
||||
error: 'ai_generation_failed',
|
||||
message: aiResult.error || 'Failed to generate cards with AI',
|
||||
});
|
||||
}
|
||||
|
||||
// 3. Create deck in database
|
||||
const newDeck = await this.deckRepository.create({
|
||||
userId: user.sub,
|
||||
title: deckTitle,
|
||||
description: deckDescription,
|
||||
isPublic: false,
|
||||
settings: { aiGenerated: true, difficulty },
|
||||
tags: tags || [],
|
||||
metadata: {
|
||||
aiModel: aiResult.metadata.model,
|
||||
generationTime: aiResult.metadata.generationTime,
|
||||
prompt,
|
||||
},
|
||||
});
|
||||
|
||||
// 4. Create cards in database
|
||||
const cardsToCreate = aiResult.cards.map((card, index) => ({
|
||||
deckId: newDeck.id,
|
||||
title: card.title || `Card ${index + 1}`,
|
||||
content: card.content,
|
||||
cardType: card.cardType,
|
||||
position: index,
|
||||
aiModel: aiResult.metadata.model,
|
||||
aiPrompt: prompt,
|
||||
}));
|
||||
|
||||
await this.cardRepository.createMany(cardsToCreate);
|
||||
|
||||
// 5. Consume credits
|
||||
await this.creditClient.consumeCredits(
|
||||
user.sub,
|
||||
operationType,
|
||||
creditCost,
|
||||
`Generated AI deck: ${deckTitle}`,
|
||||
{
|
||||
deckId: newDeck.id,
|
||||
deckTitle,
|
||||
cardCount: aiResult.cards.length,
|
||||
prompt,
|
||||
},
|
||||
);
|
||||
|
||||
this.logger.log(
|
||||
`AI deck generated successfully for user ${user.sub}. ` +
|
||||
`${aiResult.cards.length} cards created in ${aiResult.metadata.generationTime}ms. ` +
|
||||
`${creditCost} credits consumed.`
|
||||
);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
userId: user.sub,
|
||||
deck: newDeck,
|
||||
cards: aiResult.cards,
|
||||
cardCount: aiResult.cards.length,
|
||||
creditsUsed: creditCost,
|
||||
metadata: aiResult.metadata,
|
||||
message: 'Deck generated successfully with AI',
|
||||
};
|
||||
} catch (error) {
|
||||
// If it's already a known exception, rethrow it
|
||||
if (error instanceof BadRequestException || error instanceof ServiceUnavailableException) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Log other errors
|
||||
this.logger.error(`Error generating AI deck for user ${user.sub}:`, error);
|
||||
throw new BadRequestException({
|
||||
error: 'deck_generation_failed',
|
||||
message: error.message || 'Failed to generate deck with AI',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Put('decks/:id')
|
||||
|
|
|
|||
305
manadeck/backend/src/services/ai.service.ts
Normal file
305
manadeck/backend/src/services/ai.service.ts
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { GoogleGenAI, Type } from '@google/genai';
|
||||
|
||||
export type CardType = 'text' | 'flashcard' | 'quiz' | 'mixed';
|
||||
|
||||
export interface TextContent {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface FlashcardContent {
|
||||
front: string;
|
||||
back: string;
|
||||
hint?: string;
|
||||
}
|
||||
|
||||
export interface QuizContent {
|
||||
question: string;
|
||||
options: string[];
|
||||
correctAnswer: number;
|
||||
explanation?: string;
|
||||
}
|
||||
|
||||
export interface GeneratedCard {
|
||||
cardType: CardType;
|
||||
title?: string;
|
||||
content: TextContent | FlashcardContent | QuizContent;
|
||||
}
|
||||
|
||||
export interface DeckGenerationRequest {
|
||||
prompt: string;
|
||||
deckTitle: string;
|
||||
deckDescription?: string;
|
||||
cardCount?: number;
|
||||
cardTypes?: CardType[];
|
||||
difficulty?: 'beginner' | 'intermediate' | 'advanced';
|
||||
language?: string;
|
||||
}
|
||||
|
||||
export interface DeckGenerationResult {
|
||||
success: boolean;
|
||||
cards: GeneratedCard[];
|
||||
metadata: {
|
||||
model: string;
|
||||
tokensUsed?: number;
|
||||
generationTime: number;
|
||||
};
|
||||
error?: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AiService {
|
||||
private readonly logger = new Logger(AiService.name);
|
||||
private readonly ai: GoogleGenAI | null;
|
||||
private readonly model = 'gemini-2.0-flash';
|
||||
|
||||
constructor(private readonly configService: ConfigService) {
|
||||
const apiKey = this.configService.get<string>('GOOGLE_GENAI_API_KEY');
|
||||
|
||||
if (apiKey) {
|
||||
this.ai = new GoogleGenAI({ apiKey });
|
||||
this.logger.log('Google Gemini AI initialized successfully');
|
||||
} else {
|
||||
this.ai = null;
|
||||
this.logger.warn('Google Gemini API key not configured - AI features disabled');
|
||||
}
|
||||
}
|
||||
|
||||
isAvailable(): boolean {
|
||||
return this.ai !== null;
|
||||
}
|
||||
|
||||
async generateDeck(request: DeckGenerationRequest): Promise<DeckGenerationResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
if (!this.ai) {
|
||||
return {
|
||||
success: false,
|
||||
cards: [],
|
||||
metadata: { model: this.model, generationTime: 0 },
|
||||
error: 'AI service not configured. Please set GOOGLE_GENAI_API_KEY.',
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
prompt,
|
||||
deckTitle,
|
||||
deckDescription,
|
||||
cardCount = 10,
|
||||
cardTypes = ['flashcard', 'quiz'],
|
||||
difficulty = 'intermediate',
|
||||
language = 'en',
|
||||
} = request;
|
||||
|
||||
try {
|
||||
const systemPrompt = this.buildSystemPrompt(cardTypes, difficulty, language);
|
||||
const userPrompt = this.buildUserPrompt(prompt, deckTitle, deckDescription, cardCount, cardTypes);
|
||||
|
||||
const response = await this.ai.models.generateContent({
|
||||
model: this.model,
|
||||
contents: userPrompt,
|
||||
config: {
|
||||
systemInstruction: systemPrompt,
|
||||
responseMimeType: 'application/json',
|
||||
responseSchema: this.buildResponseSchema(cardTypes),
|
||||
},
|
||||
});
|
||||
|
||||
const generationTime = Date.now() - startTime;
|
||||
const responseText = response.text?.trim();
|
||||
|
||||
if (!responseText) {
|
||||
return {
|
||||
success: false,
|
||||
cards: [],
|
||||
metadata: { model: this.model, generationTime },
|
||||
error: 'Empty response from AI',
|
||||
};
|
||||
}
|
||||
|
||||
const parsed = JSON.parse(responseText);
|
||||
const cards: GeneratedCard[] = parsed.cards || [];
|
||||
|
||||
this.logger.log(`Generated ${cards.length} cards in ${generationTime}ms`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
cards,
|
||||
metadata: {
|
||||
model: this.model,
|
||||
tokensUsed: response.usageMetadata?.totalTokenCount,
|
||||
generationTime,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
const generationTime = Date.now() - startTime;
|
||||
this.logger.error('AI deck generation failed:', error);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
cards: [],
|
||||
metadata: { model: this.model, generationTime },
|
||||
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private buildSystemPrompt(cardTypes: CardType[], difficulty: string, language: string): string {
|
||||
const cardTypeDescriptions = {
|
||||
text: 'Text cards contain informational content or explanations.',
|
||||
flashcard: 'Flashcards have a front (question/term) and back (answer/definition), optionally with a hint.',
|
||||
quiz: 'Quiz cards have a question, 4 options (A-D), correct answer index (0-3), and an explanation.',
|
||||
mixed: 'Mixed cards combine multiple content types.',
|
||||
};
|
||||
|
||||
const enabledTypes = cardTypes.map(t => `- ${t}: ${cardTypeDescriptions[t]}`).join('\n');
|
||||
|
||||
return `You are an expert educational content creator specializing in flashcards and study materials.
|
||||
|
||||
Your task is to generate high-quality learning cards for a deck based on the user's topic.
|
||||
|
||||
CARD TYPES YOU CAN CREATE:
|
||||
${enabledTypes}
|
||||
|
||||
DIFFICULTY LEVEL: ${difficulty}
|
||||
- beginner: Simple concepts, basic vocabulary, straightforward questions
|
||||
- intermediate: More complex topics, requires some prior knowledge
|
||||
- advanced: Deep understanding, nuanced questions, expert-level content
|
||||
|
||||
LANGUAGE: ${language === 'de' ? 'German' : language === 'en' ? 'English' : language}
|
||||
Generate all content in this language.
|
||||
|
||||
QUALITY GUIDELINES:
|
||||
1. Make content educational and accurate
|
||||
2. Vary question styles to keep learning engaging
|
||||
3. For flashcards: front should be concise, back should be complete but not verbose
|
||||
4. For quiz: all 4 options should be plausible, avoid obviously wrong answers
|
||||
5. Include helpful hints for difficult flashcards
|
||||
6. Add explanations for quiz questions to reinforce learning
|
||||
7. Progress from easier to harder cards when possible`;
|
||||
}
|
||||
|
||||
private buildUserPrompt(
|
||||
prompt: string,
|
||||
deckTitle: string,
|
||||
deckDescription?: string,
|
||||
cardCount: number = 10,
|
||||
cardTypes: CardType[] = ['flashcard', 'quiz'],
|
||||
): string {
|
||||
const typeDistribution = this.suggestTypeDistribution(cardCount, cardTypes);
|
||||
|
||||
return `Create a deck of ${cardCount} learning cards about:
|
||||
|
||||
DECK TITLE: ${deckTitle}
|
||||
${deckDescription ? `DESCRIPTION: ${deckDescription}` : ''}
|
||||
|
||||
USER'S REQUEST:
|
||||
${prompt}
|
||||
|
||||
CARD DISTRIBUTION:
|
||||
${typeDistribution}
|
||||
|
||||
Generate exactly ${cardCount} cards that cover the topic comprehensively.
|
||||
Ensure variety in the questions and good coverage of the subject matter.`;
|
||||
}
|
||||
|
||||
private suggestTypeDistribution(cardCount: number, cardTypes: CardType[]): string {
|
||||
if (cardTypes.length === 1) {
|
||||
return `- All ${cardCount} cards should be ${cardTypes[0]} type`;
|
||||
}
|
||||
|
||||
const hasFlashcard = cardTypes.includes('flashcard');
|
||||
const hasQuiz = cardTypes.includes('quiz');
|
||||
const hasText = cardTypes.includes('text');
|
||||
|
||||
if (hasFlashcard && hasQuiz && !hasText) {
|
||||
const flashcardCount = Math.ceil(cardCount * 0.6);
|
||||
const quizCount = cardCount - flashcardCount;
|
||||
return `- ${flashcardCount} flashcards for core concepts\n- ${quizCount} quiz cards to test understanding`;
|
||||
}
|
||||
|
||||
if (hasFlashcard && hasQuiz && hasText) {
|
||||
const textCount = Math.ceil(cardCount * 0.2);
|
||||
const flashcardCount = Math.ceil((cardCount - textCount) * 0.6);
|
||||
const quizCount = cardCount - textCount - flashcardCount;
|
||||
return `- ${textCount} text cards for introductions/explanations\n- ${flashcardCount} flashcards for key terms\n- ${quizCount} quiz cards for testing`;
|
||||
}
|
||||
|
||||
return `- Mix of ${cardTypes.join(', ')} cards as appropriate for the content`;
|
||||
}
|
||||
|
||||
private buildResponseSchema(cardTypes: CardType[]): any {
|
||||
const cardSchemas: any[] = [];
|
||||
|
||||
if (cardTypes.includes('flashcard')) {
|
||||
cardSchemas.push({
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
cardType: { type: Type.STRING, enum: ['flashcard'] },
|
||||
title: { type: Type.STRING },
|
||||
content: {
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
front: { type: Type.STRING },
|
||||
back: { type: Type.STRING },
|
||||
hint: { type: Type.STRING },
|
||||
},
|
||||
required: ['front', 'back'],
|
||||
},
|
||||
},
|
||||
required: ['cardType', 'content'],
|
||||
});
|
||||
}
|
||||
|
||||
if (cardTypes.includes('quiz')) {
|
||||
cardSchemas.push({
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
cardType: { type: Type.STRING, enum: ['quiz'] },
|
||||
title: { type: Type.STRING },
|
||||
content: {
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
question: { type: Type.STRING },
|
||||
options: { type: Type.ARRAY, items: { type: Type.STRING } },
|
||||
correctAnswer: { type: Type.NUMBER },
|
||||
explanation: { type: Type.STRING },
|
||||
},
|
||||
required: ['question', 'options', 'correctAnswer'],
|
||||
},
|
||||
},
|
||||
required: ['cardType', 'content'],
|
||||
});
|
||||
}
|
||||
|
||||
if (cardTypes.includes('text')) {
|
||||
cardSchemas.push({
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
cardType: { type: Type.STRING, enum: ['text'] },
|
||||
title: { type: Type.STRING },
|
||||
content: {
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
text: { type: Type.STRING },
|
||||
},
|
||||
required: ['text'],
|
||||
},
|
||||
},
|
||||
required: ['cardType', 'content'],
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
cards: {
|
||||
type: Type.ARRAY,
|
||||
items: cardSchemas.length === 1 ? cardSchemas[0] : { anyOf: cardSchemas },
|
||||
},
|
||||
},
|
||||
required: ['cards'],
|
||||
};
|
||||
}
|
||||
}
|
||||
313
pnpm-lock.yaml
generated
313
pnpm-lock.yaml
generated
|
|
@ -312,7 +312,7 @@ importers:
|
|||
version: 17.0.7(expo@54.0.25)(react@19.1.0)
|
||||
expo-router:
|
||||
specifier: ~6.0.14
|
||||
version: 6.0.15(jqlydxfw6sdg7rjjcbafgjr6wy)
|
||||
version: 6.0.15(wy3aqjqih33pc4tbjsiq2nsp7q)
|
||||
expo-secure-store:
|
||||
specifier: ~15.0.7
|
||||
version: 15.0.7(expo@54.0.25)
|
||||
|
|
@ -415,7 +415,7 @@ importers:
|
|||
version: 7.28.5
|
||||
'@testing-library/react-native':
|
||||
specifier: ^13.3.3
|
||||
version: 13.3.3(jest@29.5.0)(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)
|
||||
version: 13.3.3(jest@29.5.0(@types/node@22.19.1)(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)
|
||||
'@types/jest':
|
||||
specifier: ^29.5.12
|
||||
version: 29.5.14
|
||||
|
|
@ -433,10 +433,10 @@ importers:
|
|||
version: 10.0.0
|
||||
jest:
|
||||
specifier: ^29.2.1
|
||||
version: 29.5.0(@types/node@18.15.11)(ts-node@10.9.2(@types/node@18.15.11)(typescript@5.9.3))
|
||||
version: 29.5.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
jest-expo:
|
||||
specifier: ~54.0.13
|
||||
version: 54.0.13(@babel/core@7.28.5)(expo@54.0.25)(jest@29.5.0)(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)(webpack@5.100.2)
|
||||
version: 54.0.13(@babel/core@7.28.5)(expo@54.0.25)(jest@29.5.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(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)(webpack@5.100.2)
|
||||
patch-package:
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.1
|
||||
|
|
@ -557,6 +557,9 @@ importers:
|
|||
'@iconify-json/tabler':
|
||||
specifier: ^1.2.19
|
||||
version: 1.2.23
|
||||
'@manacore/shared-landing-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-landing-ui
|
||||
astro:
|
||||
specifier: ^5.16.0
|
||||
version: 5.16.0(@types/node@24.10.1)(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)
|
||||
|
|
@ -1008,9 +1011,6 @@ importers:
|
|||
'@manacore/shared-subscription-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-subscription-ui
|
||||
'@manacore/shared-supabase':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-supabase
|
||||
'@manacore/shared-tailwind':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-tailwind
|
||||
|
|
@ -1029,9 +1029,6 @@ importers:
|
|||
'@manacore/shared-utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-utils
|
||||
'@supabase/supabase-js':
|
||||
specifier: ^2.81.1
|
||||
version: 2.81.1
|
||||
svelte-i18n:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1(svelte@5.43.14)
|
||||
|
|
@ -1075,6 +1072,9 @@ importers:
|
|||
|
||||
manadeck/backend:
|
||||
dependencies:
|
||||
'@google/genai':
|
||||
specifier: ^1.14.0
|
||||
version: 1.30.0
|
||||
'@mana-core/nestjs-integration':
|
||||
specifier: git+https://github.com/Memo-2023/mana-core-nestjs-package.git
|
||||
version: git+https://git@github.com:Memo-2023/mana-core-nestjs-package.git#eca58cc09d6e55d4f9d34e719fa0e0ed8d0101c7(@nestjs/axios@4.0.1(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.13.2)(rxjs@7.8.2))(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/config@4.0.2(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2))(@nestjs/core@11.1.9)(axios@1.13.2)(rxjs@7.8.2)
|
||||
|
|
@ -1099,9 +1099,6 @@ importers:
|
|||
'@nestjs/terminus':
|
||||
specifier: ^11.0.0
|
||||
version: 11.0.0(@grpc/grpc-js@1.14.1)(@grpc/proto-loader@0.8.0)(@nestjs/axios@4.0.1(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.13.2)(rxjs@7.8.2))(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2)
|
||||
'@supabase/supabase-js':
|
||||
specifier: ^2.81.1
|
||||
version: 2.81.1
|
||||
axios:
|
||||
specifier: ^1.7.2
|
||||
version: 1.13.2
|
||||
|
|
@ -1211,8 +1208,11 @@ importers:
|
|||
'@iconify-json/mdi':
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3
|
||||
'@manacore/shared-landing-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-landing-ui
|
||||
astro:
|
||||
specifier: ^5.3.0
|
||||
specifier: ^5.16.0
|
||||
version: 5.16.0(@types/node@24.10.1)(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)
|
||||
astro-icon:
|
||||
specifier: ^1.1.5
|
||||
|
|
@ -1726,7 +1726,7 @@ importers:
|
|||
specifier: ^0.9.0
|
||||
version: 0.9.5(prettier-plugin-astro@0.14.1)(prettier@3.6.2)(typescript@5.9.3)
|
||||
astro:
|
||||
specifier: ^5.3.0
|
||||
specifier: ^5.16.0
|
||||
version: 5.16.0(@types/node@24.10.1)(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
|
||||
|
|
@ -1864,7 +1864,7 @@ importers:
|
|||
specifier: workspace:*
|
||||
version: link:../../packages/design-tokens
|
||||
astro:
|
||||
specifier: ^5.2.0
|
||||
specifier: ^5.16.0
|
||||
version: 5.16.0(@types/node@20.19.25)(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)
|
||||
astro-i18next:
|
||||
specifier: 1.0.0-beta.21
|
||||
|
|
@ -2075,6 +2075,30 @@ importers:
|
|||
|
||||
picture/apps/web:
|
||||
dependencies:
|
||||
'@manacore/shared-auth-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-auth-ui
|
||||
'@manacore/shared-branding':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-branding
|
||||
'@manacore/shared-i18n':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-i18n
|
||||
'@manacore/shared-subscription-types':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-subscription-types
|
||||
'@manacore/shared-subscription-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-subscription-ui
|
||||
'@manacore/shared-tailwind':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-tailwind
|
||||
'@manacore/shared-theme-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-theme-ui
|
||||
'@manacore/shared-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../../../packages/shared-ui
|
||||
'@picture/design-tokens':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/design-tokens
|
||||
|
|
@ -2090,6 +2114,9 @@ importers:
|
|||
posthog-js:
|
||||
specifier: ^1.273.1
|
||||
version: 1.297.2
|
||||
svelte-i18n:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1(svelte@5.43.14)
|
||||
devDependencies:
|
||||
'@eslint/compat':
|
||||
specifier: ^1.4.0
|
||||
|
|
@ -17545,6 +17572,41 @@ snapshots:
|
|||
- supports-color
|
||||
- ts-node
|
||||
|
||||
'@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@jest/console': 29.7.0
|
||||
'@jest/reporters': 29.7.0
|
||||
'@jest/test-result': 29.7.0
|
||||
'@jest/transform': 29.7.0
|
||||
'@jest/types': 29.6.3
|
||||
'@types/node': 22.19.1
|
||||
ansi-escapes: 4.3.2
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.9.0
|
||||
exit: 0.1.2
|
||||
graceful-fs: 4.2.11
|
||||
jest-changed-files: 29.7.0
|
||||
jest-config: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
jest-haste-map: 29.7.0
|
||||
jest-message-util: 29.7.0
|
||||
jest-regex-util: 29.6.3
|
||||
jest-resolve: 29.7.0
|
||||
jest-resolve-dependencies: 29.7.0
|
||||
jest-runner: 29.7.0
|
||||
jest-runtime: 29.7.0
|
||||
jest-snapshot: 29.7.0
|
||||
jest-util: 29.7.0
|
||||
jest-validate: 29.7.0
|
||||
jest-watcher: 29.7.0
|
||||
micromatch: 4.0.8
|
||||
pretty-format: 29.7.0
|
||||
slash: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
transitivePeerDependencies:
|
||||
- babel-plugin-macros
|
||||
- supports-color
|
||||
- ts-node
|
||||
|
||||
'@jest/core@30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))':
|
||||
dependencies:
|
||||
'@jest/console': 30.2.0
|
||||
|
|
@ -19543,7 +19605,7 @@ snapshots:
|
|||
tailwindcss: 4.1.17
|
||||
vite: 7.2.4(@types/node@20.19.25)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)
|
||||
|
||||
'@testing-library/react-native@13.3.3(jest@29.5.0)(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)':
|
||||
'@testing-library/react-native@13.3.3(jest@29.5.0(@types/node@22.19.1)(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
|
||||
picocolors: 1.1.1
|
||||
|
|
@ -19553,7 +19615,7 @@ snapshots:
|
|||
react-test-renderer: 19.1.0(react@19.1.0)
|
||||
redent: 3.0.0
|
||||
optionalDependencies:
|
||||
jest: 29.5.0(@types/node@18.15.11)(ts-node@10.9.2(@types/node@18.15.11)(typescript@5.9.3))
|
||||
jest: 29.5.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
|
||||
'@testing-library/react-native@13.3.3(jest@30.2.0(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:
|
||||
|
|
@ -19565,7 +19627,7 @@ snapshots:
|
|||
react-test-renderer: 19.1.0(react@19.1.0)
|
||||
redent: 3.0.0
|
||||
optionalDependencies:
|
||||
jest: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
jest: 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))
|
||||
optional: true
|
||||
|
||||
'@testing-library/react-native@13.3.3(jest@30.2.0(esbuild-register@3.6.0(esbuild@0.27.0)))(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)':
|
||||
|
|
@ -19578,7 +19640,7 @@ snapshots:
|
|||
react-test-renderer: 19.1.0(react@19.1.0)
|
||||
redent: 3.0.0
|
||||
optionalDependencies:
|
||||
jest: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
jest: 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))
|
||||
optional: true
|
||||
|
||||
'@tokenizer/inflate@0.2.7':
|
||||
|
|
@ -22070,6 +22132,21 @@ snapshots:
|
|||
- supports-color
|
||||
- ts-node
|
||||
|
||||
create-jest@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@jest/types': 29.6.3
|
||||
chalk: 4.1.2
|
||||
exit: 0.1.2
|
||||
graceful-fs: 4.2.11
|
||||
jest-config: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
jest-util: 29.7.0
|
||||
prompts: 2.4.2
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- babel-plugin-macros
|
||||
- supports-color
|
||||
- ts-node
|
||||
|
||||
create-require@1.1.1: {}
|
||||
|
||||
cross-fetch@3.2.0:
|
||||
|
|
@ -24124,52 +24201,6 @@ snapshots:
|
|||
- '@types/react-dom'
|
||||
- supports-color
|
||||
|
||||
expo-router@6.0.15(jqlydxfw6sdg7rjjcbafgjr6wy):
|
||||
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)
|
||||
'@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.5(@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.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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)
|
||||
'@react-navigation/native': 7.1.21(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
|
||||
'@react-navigation/native-stack': 7.7.0(@react-navigation/native@7.1.21(react-native@0.81.5(@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.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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)
|
||||
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@0.81.5(@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.5(@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.5(@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.5(@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.5(@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.5(@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.5(@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.5(@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.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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)
|
||||
'@testing-library/react-native': 13.3.3(jest@29.5.0)(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)
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
react-native-gesture-handler: 2.28.0(react-native@0.81.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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)
|
||||
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)
|
||||
transitivePeerDependencies:
|
||||
- '@react-native-masked-view/masked-view'
|
||||
- '@types/react'
|
||||
- '@types/react-dom'
|
||||
- supports-color
|
||||
|
||||
expo-router@6.0.15(qjp3usx4acoq47dkosl6pmu254):
|
||||
dependencies:
|
||||
'@expo/metro-runtime': 6.1.2(expo@54.0.13)(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)
|
||||
|
|
@ -24262,6 +24293,52 @@ snapshots:
|
|||
- '@types/react-dom'
|
||||
- supports-color
|
||||
|
||||
expo-router@6.0.15(wy3aqjqih33pc4tbjsiq2nsp7q):
|
||||
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)
|
||||
'@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.5(@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.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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)
|
||||
'@react-navigation/native': 7.1.21(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
|
||||
'@react-navigation/native-stack': 7.7.0(@react-navigation/native@7.1.21(react-native@0.81.5(@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.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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)
|
||||
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@0.81.5(@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.5(@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.5(@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.5(@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.5(@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.5(@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.5(@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.5(@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.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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)
|
||||
'@testing-library/react-native': 13.3.3(jest@29.5.0(@types/node@22.19.1)(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)
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
react-native-gesture-handler: 2.28.0(react-native@0.81.5(@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.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@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)
|
||||
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)
|
||||
transitivePeerDependencies:
|
||||
- '@react-native-masked-view/masked-view'
|
||||
- '@types/react'
|
||||
- '@types/react-dom'
|
||||
- supports-color
|
||||
|
||||
expo-secure-store@15.0.7(expo@54.0.13):
|
||||
dependencies:
|
||||
expo: 54.0.13(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.15)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
|
||||
|
|
@ -25989,6 +26066,25 @@ snapshots:
|
|||
- supports-color
|
||||
- ts-node
|
||||
|
||||
jest-cli@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
'@jest/test-result': 29.7.0
|
||||
'@jest/types': 29.6.3
|
||||
chalk: 4.1.2
|
||||
create-jest: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
exit: 0.1.2
|
||||
import-local: 3.2.0
|
||||
jest-config: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
jest-util: 29.7.0
|
||||
jest-validate: 29.7.0
|
||||
yargs: 17.7.2
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- babel-plugin-macros
|
||||
- supports-color
|
||||
- ts-node
|
||||
|
||||
jest-cli@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(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.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
|
|
@ -26008,6 +26104,26 @@ snapshots:
|
|||
- supports-color
|
||||
- ts-node
|
||||
|
||||
jest-cli@30.2.0(esbuild-register@3.6.0(esbuild@0.27.0)):
|
||||
dependencies:
|
||||
'@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
'@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@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
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-config@29.7.0(@types/node@18.15.11)(ts-node@10.9.2(@types/node@18.15.11)(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
|
|
@ -26070,6 +26186,37 @@ snapshots:
|
|||
- babel-plugin-macros
|
||||
- supports-color
|
||||
|
||||
jest-config@29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
'@jest/test-sequencer': 29.7.0
|
||||
'@jest/types': 29.6.3
|
||||
babel-jest: 29.7.0(@babel/core@7.28.5)
|
||||
chalk: 4.1.2
|
||||
ci-info: 3.9.0
|
||||
deepmerge: 4.3.1
|
||||
glob: 7.2.3
|
||||
graceful-fs: 4.2.11
|
||||
jest-circus: 29.7.0
|
||||
jest-environment-node: 29.7.0
|
||||
jest-get-type: 29.6.3
|
||||
jest-regex-util: 29.6.3
|
||||
jest-resolve: 29.7.0
|
||||
jest-runner: 29.7.0
|
||||
jest-util: 29.7.0
|
||||
jest-validate: 29.7.0
|
||||
micromatch: 4.0.8
|
||||
parse-json: 5.2.0
|
||||
pretty-format: 29.7.0
|
||||
slash: 3.0.0
|
||||
strip-json-comments: 3.1.1
|
||||
optionalDependencies:
|
||||
'@types/node': 22.19.1
|
||||
ts-node: 10.9.2(@types/node@22.19.1)(typescript@5.9.3)
|
||||
transitivePeerDependencies:
|
||||
- babel-plugin-macros
|
||||
- supports-color
|
||||
|
||||
jest-config@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@babel/core': 7.28.5
|
||||
|
|
@ -26176,7 +26323,7 @@ snapshots:
|
|||
jest-util: 30.2.0
|
||||
jest-validate: 30.2.0
|
||||
|
||||
jest-expo@54.0.13(@babel/core@7.28.5)(expo@54.0.25)(jest@29.5.0)(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)(webpack@5.100.2):
|
||||
jest-expo@54.0.13(@babel/core@7.28.5)(expo@54.0.25)(jest@29.5.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(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)(webpack@5.100.2):
|
||||
dependencies:
|
||||
'@expo/config': 12.0.10
|
||||
'@expo/json-file': 10.0.7
|
||||
|
|
@ -26187,7 +26334,7 @@ snapshots:
|
|||
jest-environment-jsdom: 29.7.0
|
||||
jest-snapshot: 29.7.0
|
||||
jest-watch-select-projects: 2.0.0
|
||||
jest-watch-typeahead: 2.2.1(jest@29.5.0)
|
||||
jest-watch-typeahead: 2.2.1(jest@29.5.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))
|
||||
json5: 2.2.3
|
||||
lodash: 4.17.21
|
||||
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
|
||||
|
|
@ -26548,11 +26695,11 @@ snapshots:
|
|||
chalk: 3.0.0
|
||||
prompts: 2.4.2
|
||||
|
||||
jest-watch-typeahead@2.2.1(jest@29.5.0):
|
||||
jest-watch-typeahead@2.2.1(jest@29.5.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))):
|
||||
dependencies:
|
||||
ansi-escapes: 6.2.1
|
||||
chalk: 4.1.2
|
||||
jest: 29.5.0(@types/node@18.15.11)(ts-node@10.9.2(@types/node@18.15.11)(typescript@5.9.3))
|
||||
jest: 29.5.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
jest-regex-util: 29.6.3
|
||||
jest-watcher: 29.7.0
|
||||
slash: 5.1.0
|
||||
|
|
@ -26614,6 +26761,18 @@ snapshots:
|
|||
- supports-color
|
||||
- ts-node
|
||||
|
||||
jest@29.5.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
|
||||
dependencies:
|
||||
'@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
'@jest/types': 29.6.3
|
||||
import-local: 3.2.0
|
||||
jest-cli: 29.7.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- babel-plugin-macros
|
||||
- supports-color
|
||||
- ts-node
|
||||
|
||||
jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.27.0))(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.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
|
|
@ -26627,6 +26786,20 @@ snapshots:
|
|||
- supports-color
|
||||
- ts-node
|
||||
|
||||
jest@30.2.0(esbuild-register@3.6.0(esbuild@0.27.0)):
|
||||
dependencies:
|
||||
'@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
|
||||
'@jest/types': 30.2.0
|
||||
import-local: 3.2.0
|
||||
jest-cli: 30.2.0(esbuild-register@3.6.0(esbuild@0.27.0))
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- babel-plugin-macros
|
||||
- esbuild-register
|
||||
- supports-color
|
||||
- ts-node
|
||||
optional: true
|
||||
|
||||
jimp-compact@0.16.1: {}
|
||||
|
||||
jiti@1.21.7: {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue