diff --git a/docs/MANADECK_POSTGRES_MIGRATION.md b/docs/MANADECK_POSTGRES_MIGRATION.md
new file mode 100644
index 000000000..e53697753
--- /dev/null
+++ b/docs/MANADECK_POSTGRES_MIGRATION.md
@@ -0,0 +1,840 @@
+# ManaDeck: Migration zu PostgreSQL + Drizzle ORM
+
+## Übersicht
+
+Dieses Dokument beschreibt die Migration von ManaDeck von Supabase zu einer selbst-gehosteten PostgreSQL-Datenbank mit Drizzle ORM.
+
+---
+
+## Aktuelle Architektur
+
+```
+┌─────────────────┐ ┌─────────────────┐
+│ ManaDeck Web │ │ ManaDeck Mobile │
+│ (SvelteKit) │ │ (Expo) │
+└────────┬────────┘ └────────┬────────┘
+ │ │
+ └───────────┬───────────┘
+ │
+ ┌───────────▼───────────┐
+ │ ManaDeck Backend │
+ │ (NestJS) │
+ └───────────┬───────────┘
+ │
+ ┌────────────────┼────────────────┐
+ │ │ │
+ ▼ ▼ ▼
+┌────────┐ ┌──────────┐ ┌──────────┐
+│Supabase│ │Mana Core │ │ OpenAI │
+│ DB │ │ (Auth) │ │ API │
+└────────┘ └──────────┘ └──────────┘
+```
+
+---
+
+## Ziel-Architektur
+
+```
+┌─────────────────┐ ┌─────────────────┐
+│ ManaDeck Web │ │ ManaDeck Mobile │
+│ (SvelteKit) │ │ (Expo) │
+└────────┬────────┘ └────────┬────────┘
+ │ │
+ └───────────┬───────────┘
+ │
+ ┌───────────▼───────────┐
+ │ ManaDeck Backend │
+ │ (NestJS + Drizzle) │
+ └───────────┬───────────┘
+ │
+ ┌────────────────┼────────────────┐
+ │ │ │
+ ▼ ▼ ▼
+┌────────┐ ┌──────────┐ ┌──────────┐
+│ PostgreSQL │ │Mana Core │ │ OpenAI │
+│ (Self) │ │ (Auth) │ │ API │
+└────────────┘ └──────────┘ └──────────┘
+```
+
+---
+
+## Datenbank-Schema
+
+### Tabellen
+
+#### 1. `decks`
+```sql
+CREATE TABLE decks (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ user_id UUID NOT NULL, -- Mana Core User ID
+ title VARCHAR(255) NOT NULL,
+ description TEXT,
+ cover_image_url TEXT,
+ is_public BOOLEAN DEFAULT false,
+ is_featured BOOLEAN DEFAULT false,
+ featured_at TIMESTAMPTZ,
+ settings JSONB DEFAULT '{}',
+ tags TEXT[] DEFAULT '{}',
+ metadata JSONB DEFAULT '{}',
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+CREATE INDEX idx_decks_user_id ON decks(user_id);
+CREATE INDEX idx_decks_is_public ON decks(is_public);
+CREATE INDEX idx_decks_is_featured ON decks(is_featured);
+```
+
+#### 2. `cards`
+```sql
+CREATE TABLE cards (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ deck_id UUID NOT NULL REFERENCES decks(id) ON DELETE CASCADE,
+ position INTEGER NOT NULL DEFAULT 0,
+ title VARCHAR(255),
+ content JSONB NOT NULL,
+ card_type VARCHAR(20) NOT NULL CHECK (card_type IN ('text', 'flashcard', 'quiz', 'mixed')),
+ ai_model VARCHAR(100),
+ ai_prompt TEXT,
+ version INTEGER DEFAULT 1,
+ is_favorite BOOLEAN DEFAULT false,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+CREATE INDEX idx_cards_deck_id ON cards(deck_id);
+CREATE INDEX idx_cards_position ON cards(deck_id, position);
+```
+
+#### 3. `study_sessions`
+```sql
+CREATE TABLE study_sessions (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ deck_id UUID NOT NULL REFERENCES decks(id) ON DELETE CASCADE,
+ user_id UUID NOT NULL,
+ mode VARCHAR(20) NOT NULL CHECK (mode IN ('all', 'new', 'review', 'favorites', 'random')),
+ total_cards INTEGER NOT NULL DEFAULT 0,
+ completed_cards INTEGER NOT NULL DEFAULT 0,
+ correct_cards INTEGER NOT NULL DEFAULT 0,
+ started_at TIMESTAMPTZ DEFAULT NOW(),
+ completed_at TIMESTAMPTZ,
+ time_spent_seconds INTEGER DEFAULT 0
+);
+
+CREATE INDEX idx_study_sessions_user_id ON study_sessions(user_id);
+CREATE INDEX idx_study_sessions_deck_id ON study_sessions(deck_id);
+```
+
+#### 4. `card_progress`
+```sql
+CREATE TABLE card_progress (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ user_id UUID NOT NULL,
+ card_id UUID NOT NULL REFERENCES cards(id) ON DELETE CASCADE,
+ ease_factor DECIMAL(4,2) DEFAULT 2.5,
+ interval INTEGER DEFAULT 0,
+ repetitions INTEGER DEFAULT 0,
+ last_reviewed TIMESTAMPTZ,
+ next_review TIMESTAMPTZ,
+ status VARCHAR(20) DEFAULT 'new' CHECK (status IN ('new', 'learning', 'review', 'relearning')),
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW(),
+ UNIQUE(user_id, card_id)
+);
+
+CREATE INDEX idx_card_progress_user_id ON card_progress(user_id);
+CREATE INDEX idx_card_progress_next_review ON card_progress(next_review);
+```
+
+#### 5. `deck_templates`
+```sql
+CREATE TABLE deck_templates (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ title VARCHAR(255) NOT NULL,
+ description TEXT,
+ category VARCHAR(100),
+ template_data JSONB NOT NULL,
+ is_active BOOLEAN DEFAULT true,
+ is_public BOOLEAN DEFAULT true,
+ popularity INTEGER DEFAULT 0,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+CREATE INDEX idx_deck_templates_category ON deck_templates(category);
+CREATE INDEX idx_deck_templates_is_active ON deck_templates(is_active);
+```
+
+#### 6. `ai_generations`
+```sql
+CREATE TABLE ai_generations (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ user_id UUID NOT NULL,
+ deck_id UUID REFERENCES decks(id) ON DELETE SET NULL,
+ function_name VARCHAR(100) NOT NULL,
+ prompt TEXT NOT NULL,
+ model VARCHAR(100),
+ status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'completed', 'failed')),
+ metadata JSONB DEFAULT '{}',
+ completed_at TIMESTAMPTZ,
+ created_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+CREATE INDEX idx_ai_generations_user_id ON ai_generations(user_id);
+CREATE INDEX idx_ai_generations_status ON ai_generations(status);
+```
+
+#### 7. `user_stats` (für Leaderboard)
+```sql
+CREATE TABLE user_stats (
+ user_id UUID PRIMARY KEY,
+ total_wins INTEGER DEFAULT 0,
+ total_sessions INTEGER DEFAULT 0,
+ total_cards_studied INTEGER DEFAULT 0,
+ total_time_seconds INTEGER DEFAULT 0,
+ average_accuracy DECIMAL(5,2) DEFAULT 0,
+ streak_days INTEGER DEFAULT 0,
+ last_study_date DATE,
+ created_at TIMESTAMPTZ DEFAULT NOW(),
+ updated_at TIMESTAMPTZ DEFAULT NOW()
+);
+```
+
+---
+
+## Drizzle Schema
+
+### Dateistruktur
+
+```
+manadeck/
+├── packages/
+│ └── database/ # Neues shared database package
+│ ├── src/
+│ │ ├── schema/
+│ │ │ ├── decks.ts
+│ │ │ ├── cards.ts
+│ │ │ ├── studySessions.ts
+│ │ │ ├── cardProgress.ts
+│ │ │ ├── deckTemplates.ts
+│ │ │ ├── aiGenerations.ts
+│ │ │ ├── userStats.ts
+│ │ │ └── index.ts
+│ │ ├── client.ts
+│ │ ├── migrate.ts
+│ │ └── index.ts
+│ ├── drizzle/
+│ │ └── migrations/
+│ ├── drizzle.config.ts
+│ ├── package.json
+│ └── tsconfig.json
+```
+
+### Schema-Definitionen (Drizzle)
+
+#### `schema/decks.ts`
+```typescript
+import { pgTable, uuid, varchar, text, boolean, timestamp, jsonb } from 'drizzle-orm/pg-core';
+
+export const decks = pgTable('decks', {
+ id: uuid('id').primaryKey().defaultRandom(),
+ userId: uuid('user_id').notNull(),
+ title: varchar('title', { length: 255 }).notNull(),
+ description: text('description'),
+ coverImageUrl: text('cover_image_url'),
+ isPublic: boolean('is_public').default(false),
+ isFeatured: boolean('is_featured').default(false),
+ featuredAt: timestamp('featured_at', { withTimezone: true }),
+ settings: jsonb('settings').default({}),
+ tags: text('tags').array().default([]),
+ metadata: jsonb('metadata').default({}),
+ createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
+ updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow(),
+});
+
+export type Deck = typeof decks.$inferSelect;
+export type NewDeck = typeof decks.$inferInsert;
+```
+
+#### `schema/cards.ts`
+```typescript
+import { pgTable, uuid, varchar, text, integer, boolean, timestamp, jsonb } from 'drizzle-orm/pg-core';
+import { decks } from './decks';
+
+export const cardTypeEnum = pgEnum('card_type', ['text', 'flashcard', 'quiz', 'mixed']);
+
+export const cards = pgTable('cards', {
+ id: uuid('id').primaryKey().defaultRandom(),
+ deckId: uuid('deck_id').notNull().references(() => decks.id, { onDelete: 'cascade' }),
+ position: integer('position').notNull().default(0),
+ title: varchar('title', { length: 255 }),
+ content: jsonb('content').notNull(),
+ cardType: cardTypeEnum('card_type').notNull(),
+ aiModel: varchar('ai_model', { length: 100 }),
+ aiPrompt: text('ai_prompt'),
+ version: integer('version').default(1),
+ isFavorite: boolean('is_favorite').default(false),
+ createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
+ updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow(),
+});
+
+export type Card = typeof cards.$inferSelect;
+export type NewCard = typeof cards.$inferInsert;
+```
+
+#### `schema/index.ts`
+```typescript
+export * from './decks';
+export * from './cards';
+export * from './studySessions';
+export * from './cardProgress';
+export * from './deckTemplates';
+export * from './aiGenerations';
+export * from './userStats';
+
+// Relations
+export { decksRelations } from './decks';
+export { cardsRelations } from './cards';
+```
+
+### Client Setup
+
+#### `client.ts`
+```typescript
+import { drizzle } from 'drizzle-orm/postgres-js';
+import postgres from 'postgres';
+import * as schema from './schema';
+
+const connectionString = process.env.DATABASE_URL!;
+
+// For connection pooling in serverless environments
+const client = postgres(connectionString, {
+ max: 10,
+ idle_timeout: 20,
+ connect_timeout: 10,
+});
+
+export const db = drizzle(client, { schema });
+export type Database = typeof db;
+```
+
+---
+
+## Migrationsschritte
+
+### Phase 1: Setup (Tag 1-2)
+
+#### 1.1 PostgreSQL Server aufsetzen
+```bash
+# Option A: Railway.app (empfohlen für Staging)
+# Erstelle neues Projekt auf railway.app
+# Füge PostgreSQL Plugin hinzu
+
+# Option B: Docker lokal
+docker run -d \
+ --name manadeck-postgres \
+ -e POSTGRES_USER=manadeck \
+ -e POSTGRES_PASSWORD=secure_password \
+ -e POSTGRES_DB=manadeck \
+ -p 5432:5432 \
+ postgres:16-alpine
+
+# Option C: Neon.tech (Serverless)
+# Erstelle neues Projekt auf neon.tech
+```
+
+#### 1.2 Database Package erstellen
+```bash
+cd /Users/tillschneider/Documents/__00__Code/manacore-monorepo
+mkdir -p packages/manadeck-database
+cd packages/manadeck-database
+pnpm init
+```
+
+#### 1.3 Dependencies installieren
+```bash
+pnpm add drizzle-orm postgres
+pnpm add -D drizzle-kit typescript @types/node
+```
+
+### Phase 2: Schema & Migration (Tag 2-3)
+
+#### 2.1 Drizzle Schema erstellen
+- Alle Tabellen wie oben definiert
+- Relations definieren
+- Indexes definieren
+
+#### 2.2 Initial Migration generieren
+```bash
+pnpm drizzle-kit generate
+pnpm drizzle-kit migrate
+```
+
+#### 2.3 Daten von Supabase exportieren
+```bash
+# In Supabase Dashboard: SQL Editor
+# Export alle Tabellen als CSV oder pg_dump
+
+# Oder via CLI:
+pg_dump -h db.your-project.supabase.co \
+ -U postgres \
+ -d postgres \
+ --data-only \
+ --table=decks \
+ --table=cards \
+ --table=study_sessions \
+ --table=card_progress \
+ --table=deck_templates \
+ --table=ai_generations \
+ --table=user_stats \
+ > manadeck_data.sql
+```
+
+### Phase 3: Backend Migration (Tag 3-5)
+
+#### 3.1 Repository Pattern implementieren
+
+```typescript
+// repositories/deck.repository.ts
+import { db } from '@manadeck/database';
+import { decks, cards } from '@manadeck/database/schema';
+import { eq, and, or, desc } from 'drizzle-orm';
+
+export class DeckRepository {
+ async findAllByUser(userId: string) {
+ return db.query.decks.findMany({
+ where: eq(decks.userId, userId),
+ orderBy: desc(decks.updatedAt),
+ with: {
+ cards: true,
+ },
+ });
+ }
+
+ async findById(id: string) {
+ return db.query.decks.findFirst({
+ where: eq(decks.id, id),
+ with: {
+ cards: {
+ orderBy: (cards, { asc }) => [asc(cards.position)],
+ },
+ },
+ });
+ }
+
+ async findPublicAndUserDecks(userId: string) {
+ return db.query.decks.findMany({
+ where: or(
+ eq(decks.userId, userId),
+ and(eq(decks.isPublic, true), eq(decks.isFeatured, true))
+ ),
+ orderBy: desc(decks.updatedAt),
+ });
+ }
+
+ async create(data: NewDeck) {
+ const [deck] = await db.insert(decks).values(data).returning();
+ return deck;
+ }
+
+ async update(id: string, userId: string, data: Partial) {
+ const [deck] = await db
+ .update(decks)
+ .set({ ...data, updatedAt: new Date() })
+ .where(and(eq(decks.id, id), eq(decks.userId, userId)))
+ .returning();
+ return deck;
+ }
+
+ async delete(id: string, userId: string) {
+ await db
+ .delete(decks)
+ .where(and(eq(decks.id, id), eq(decks.userId, userId)));
+ }
+}
+```
+
+#### 3.2 Service Layer aktualisieren
+
+```typescript
+// services/deck.service.ts
+import { DeckRepository } from '../repositories/deck.repository';
+
+export class DeckService {
+ constructor(private deckRepo = new DeckRepository()) {}
+
+ async getUserDecks(userId: string) {
+ return this.deckRepo.findPublicAndUserDecks(userId);
+ }
+
+ async getDeck(id: string) {
+ return this.deckRepo.findById(id);
+ }
+
+ async createDeck(userId: string, data: CreateDeckInput) {
+ return this.deckRepo.create({
+ ...data,
+ userId,
+ });
+ }
+
+ async updateDeck(id: string, userId: string, data: UpdateDeckInput) {
+ return this.deckRepo.update(id, userId, data);
+ }
+
+ async deleteDeck(id: string, userId: string) {
+ return this.deckRepo.delete(id, userId);
+ }
+}
+```
+
+### Phase 4: Frontend Migration (Tag 5-7)
+
+#### 4.1 API Client erstellen (ersetzt Supabase SDK)
+
+```typescript
+// lib/api/client.ts
+import { getToken } from '$lib/auth';
+
+const API_URL = import.meta.env.VITE_API_URL;
+
+async function fetchApi(
+ endpoint: string,
+ options: RequestInit = {}
+): Promise {
+ const token = getToken();
+
+ const response = await fetch(`${API_URL}${endpoint}`, {
+ ...options,
+ headers: {
+ 'Content-Type': 'application/json',
+ ...(token && { Authorization: `Bearer ${token}` }),
+ ...options.headers,
+ },
+ });
+
+ if (!response.ok) {
+ const error = await response.json();
+ throw new Error(error.message || 'API Error');
+ }
+
+ return response.json();
+}
+
+export const api = {
+ get: (endpoint: string) => fetchApi(endpoint),
+ post: (endpoint: string, data: unknown) =>
+ fetchApi(endpoint, { method: 'POST', body: JSON.stringify(data) }),
+ put: (endpoint: string, data: unknown) =>
+ fetchApi(endpoint, { method: 'PUT', body: JSON.stringify(data) }),
+ delete: (endpoint: string) =>
+ fetchApi(endpoint, { method: 'DELETE' }),
+};
+```
+
+#### 4.2 Deck Store migrieren
+
+```typescript
+// stores/deckStore.svelte.ts
+import { api } from '$lib/api/client';
+import type { Deck, CreateDeckInput, UpdateDeckInput } from '$lib/types/deck';
+
+function createDeckStore() {
+ let decks = $state([]);
+ let currentDeck = $state(null);
+ let loading = $state(false);
+ let error = $state(null);
+
+ return {
+ get decks() { return decks; },
+ get currentDeck() { return currentDeck; },
+ get loading() { return loading; },
+ get error() { return error; },
+
+ async fetchDecks() {
+ loading = true;
+ error = null;
+ try {
+ decks = await api.get('/api/decks');
+ } catch (e) {
+ error = e instanceof Error ? e.message : 'Failed to fetch decks';
+ } finally {
+ loading = false;
+ }
+ },
+
+ async fetchDeck(id: string) {
+ loading = true;
+ error = null;
+ try {
+ currentDeck = await api.get(`/api/decks/${id}`);
+ } catch (e) {
+ error = e instanceof Error ? e.message : 'Failed to fetch deck';
+ } finally {
+ loading = false;
+ }
+ },
+
+ async createDeck(data: CreateDeckInput) {
+ loading = true;
+ error = null;
+ try {
+ const deck = await api.post('/api/decks', data);
+ decks = [deck, ...decks];
+ return deck;
+ } catch (e) {
+ error = e instanceof Error ? e.message : 'Failed to create deck';
+ throw e;
+ } finally {
+ loading = false;
+ }
+ },
+
+ async updateDeck(id: string, data: UpdateDeckInput) {
+ loading = true;
+ error = null;
+ try {
+ const deck = await api.put(`/api/decks/${id}`, data);
+ decks = decks.map(d => d.id === id ? deck : d);
+ if (currentDeck?.id === id) currentDeck = deck;
+ return deck;
+ } catch (e) {
+ error = e instanceof Error ? e.message : 'Failed to update deck';
+ throw e;
+ } finally {
+ loading = false;
+ }
+ },
+
+ async deleteDeck(id: string) {
+ loading = true;
+ error = null;
+ try {
+ await api.delete(`/api/decks/${id}`);
+ decks = decks.filter(d => d.id !== id);
+ if (currentDeck?.id === id) currentDeck = null;
+ } catch (e) {
+ error = e instanceof Error ? e.message : 'Failed to delete deck';
+ throw e;
+ } finally {
+ loading = false;
+ }
+ },
+ };
+}
+
+export const deckStore = createDeckStore();
+```
+
+### Phase 5: Testing & Cutover (Tag 7-10)
+
+#### 5.1 Integration Tests
+```typescript
+// tests/deck.integration.test.ts
+import { describe, it, expect, beforeAll, afterAll } from 'vitest';
+import { db } from '@manadeck/database';
+import { decks } from '@manadeck/database/schema';
+import { DeckService } from '../services/deck.service';
+
+describe('DeckService', () => {
+ const service = new DeckService();
+ const testUserId = 'test-user-id';
+
+ afterAll(async () => {
+ await db.delete(decks).where(eq(decks.userId, testUserId));
+ });
+
+ it('should create a deck', async () => {
+ const deck = await service.createDeck(testUserId, {
+ title: 'Test Deck',
+ description: 'A test deck',
+ });
+
+ expect(deck.id).toBeDefined();
+ expect(deck.title).toBe('Test Deck');
+ });
+
+ it('should fetch user decks', async () => {
+ const userDecks = await service.getUserDecks(testUserId);
+ expect(userDecks.length).toBeGreaterThan(0);
+ });
+});
+```
+
+#### 5.2 Datenmigrations-Script
+```typescript
+// scripts/migrate-data.ts
+import { db as newDb } from '@manadeck/database';
+import { createClient } from '@supabase/supabase-js';
+import { decks, cards } from '@manadeck/database/schema';
+
+const supabase = createClient(
+ process.env.SUPABASE_URL!,
+ process.env.SUPABASE_SERVICE_KEY!
+);
+
+async function migrateDecks() {
+ console.log('Migrating decks...');
+
+ const { data: supabaseDecks, error } = await supabase
+ .from('decks')
+ .select('*');
+
+ if (error) throw error;
+
+ for (const deck of supabaseDecks) {
+ await newDb.insert(decks).values({
+ id: deck.id,
+ userId: deck.user_id,
+ title: deck.title,
+ description: deck.description,
+ coverImageUrl: deck.cover_image_url,
+ isPublic: deck.is_public,
+ isFeatured: deck.is_featured,
+ featuredAt: deck.featured_at,
+ settings: deck.settings,
+ tags: deck.tags,
+ metadata: deck.metadata,
+ createdAt: deck.created_at,
+ updatedAt: deck.updated_at,
+ }).onConflictDoNothing();
+ }
+
+ console.log(`Migrated ${supabaseDecks.length} decks`);
+}
+
+async function migrateCards() {
+ console.log('Migrating cards...');
+
+ const { data: supabaseCards, error } = await supabase
+ .from('cards')
+ .select('*');
+
+ if (error) throw error;
+
+ for (const card of supabaseCards) {
+ await newDb.insert(cards).values({
+ id: card.id,
+ deckId: card.deck_id,
+ position: card.position,
+ title: card.title,
+ content: card.content,
+ cardType: card.card_type,
+ aiModel: card.ai_model,
+ aiPrompt: card.ai_prompt,
+ version: card.version,
+ isFavorite: card.is_favorite,
+ createdAt: card.created_at,
+ updatedAt: card.updated_at,
+ }).onConflictDoNothing();
+ }
+
+ console.log(`Migrated ${supabaseCards.length} cards`);
+}
+
+async function main() {
+ try {
+ await migrateDecks();
+ await migrateCards();
+ // ... andere Tabellen
+ console.log('Migration completed successfully!');
+ } catch (error) {
+ console.error('Migration failed:', error);
+ process.exit(1);
+ }
+}
+
+main();
+```
+
+---
+
+## Zeitplan
+
+| Phase | Beschreibung | Dauer | Status |
+|-------|--------------|-------|--------|
+| 1 | Setup (PostgreSQL, Package) | 1-2 Tage | ⬜ Pending |
+| 2 | Schema & Migration | 1-2 Tage | ⬜ Pending |
+| 3 | Backend Migration | 2-3 Tage | ⬜ Pending |
+| 4 | Frontend Migration | 2-3 Tage | ⬜ Pending |
+| 5 | Testing & Cutover | 2-3 Tage | ⬜ Pending |
+
+**Gesamtdauer: ~10-13 Tage**
+
+---
+
+## Checkliste
+
+### Pre-Migration
+- [ ] PostgreSQL Server aufgesetzt
+- [ ] Database Package erstellt
+- [ ] Drizzle Schema definiert
+- [ ] Initial Migration durchgeführt
+- [ ] Supabase Daten exportiert
+
+### Backend
+- [ ] Repository Pattern implementiert
+- [ ] DeckRepository
+- [ ] CardRepository
+- [ ] StudySessionRepository
+- [ ] CardProgressRepository
+- [ ] DeckTemplateRepository
+- [ ] AIGenerationRepository
+- [ ] UserStatsRepository
+- [ ] Service Layer aktualisiert
+- [ ] Controller aktualisiert
+- [ ] Authorization Middleware (ersetzt RLS)
+
+### Frontend
+- [ ] API Client erstellt
+- [ ] deckStore migriert
+- [ ] Supabase imports entfernt
+- [ ] Environment Variables aktualisiert
+
+### Testing
+- [ ] Unit Tests für Repositories
+- [ ] Integration Tests für Services
+- [ ] E2E Tests für API
+- [ ] Manual Testing aller Features
+
+### Cutover
+- [ ] Daten migriert (Script ausgeführt)
+- [ ] DNS/Environment umgestellt
+- [ ] Rollback Plan dokumentiert
+- [ ] Monitoring eingerichtet
+
+---
+
+## Rollback Plan
+
+Falls kritische Probleme auftreten:
+
+1. **Environment Variables zurücksetzen** auf Supabase
+2. **Feature Flag** für alte Implementierung aktivieren
+3. **DNS** auf alten Service zeigen lassen
+
+Supabase-Daten bleiben während der Migration unberührt.
+
+---
+
+## Kosten nach Migration
+
+| Service | Geschätzte Kosten |
+|---------|-------------------|
+| PostgreSQL (Railway) | ~$5-20/Monat |
+| PostgreSQL (Neon Free) | $0/Monat |
+| Backup (optional) | ~$5/Monat |
+| **Gesamt** | **$5-25/Monat** |
+
+vs. Supabase Pro: $25-300/Monat
+
+---
+
+## Nächste Schritte
+
+1. **Entscheidung**: PostgreSQL Hosting (Railway vs Neon vs Self-hosted)
+2. **Setup**: Database Package im Monorepo erstellen
+3. **Schema**: Drizzle Schema implementieren
+4. **Start**: Phase 1 beginnen
+
+Bereit zum Start?
diff --git a/maerchenzauber/apps/web/src/lib/i18n/index.ts b/maerchenzauber/apps/web/src/lib/i18n/index.ts
index 3036ebce3..48d6d2300 100644
--- a/maerchenzauber/apps/web/src/lib/i18n/index.ts
+++ b/maerchenzauber/apps/web/src/lib/i18n/index.ts
@@ -4,9 +4,12 @@ import { init, register, locale, waitLocale } from 'svelte-i18n';
// Register all available locales
register('de', () => import('./locales/de.json'));
register('en', () => import('./locales/en.json'));
+register('it', () => import('./locales/it.json'));
+register('fr', () => import('./locales/fr.json'));
+register('es', () => import('./locales/es.json'));
// List of supported locales
-export const supportedLocales = ['de', 'en'] as const;
+export const supportedLocales = ['de', 'en', 'it', 'fr', 'es'] as const;
export type SupportedLocale = (typeof supportedLocales)[number];
// Default locale
diff --git a/maerchenzauber/apps/web/src/routes/(auth)/login/+page.svelte b/maerchenzauber/apps/web/src/routes/(auth)/login/+page.svelte
index 71a18771d..f5f5eb993 100644
--- a/maerchenzauber/apps/web/src/routes/(auth)/login/+page.svelte
+++ b/maerchenzauber/apps/web/src/routes/(auth)/login/+page.svelte
@@ -1,11 +1,16 @@
@@ -121,7 +164,7 @@
class="mb-6 text-center text-xl font-semibold"
style="color: {isDark ? 'rgba(255, 255, 255, 0.9)' : 'rgba(0, 0, 0, 0.9)'};"
>
- {mode === 'form' ? 'Reset Password' : 'Email Sent'}
+ {mode === 'form' ? t.titleForm : t.titleSuccess}
@@ -144,14 +187,14 @@
class="mb-4 text-sm"
style="color: {isDark ? 'rgba(255, 255, 255, 0.7)' : 'rgba(0, 0, 0, 0.7)'};"
>
- Enter your email address and we'll send you a link to reset your password.
+ {t.description}
- {loading ? 'Sending...' : 'Send Reset Link'}
+ {loading ? t.sending : t.sendResetLinkButton}
@@ -177,7 +220,7 @@
style="color: {isDark ? '#ffffff' : '#000000'};"
>
- Back to Login
+ {t.backToLogin}
@@ -196,8 +239,7 @@
class="text-sm text-center px-2"
style="color: {isDark ? 'rgba(255, 255, 255, 0.7)' : 'rgba(0, 0, 0, 0.7)'};"
>
- We've sent a password reset link to {resetEmail}. Please check your
- inbox.
+ {@html getSuccessMessage(resetEmail).replace(resetEmail, `${resetEmail}`)}
@@ -208,7 +250,7 @@
style="background-color: {primaryColor}60; border-color: {primaryColor}; color: {isDark ? '#ffffff' : '#000000'};"
>
- Back to Login
+ {t.backToLogin}
diff --git a/packages/shared-auth-ui/src/pages/LoginPage.svelte b/packages/shared-auth-ui/src/pages/LoginPage.svelte
index ae34928b8..91afa4dcd 100644
--- a/packages/shared-auth-ui/src/pages/LoginPage.svelte
+++ b/packages/shared-auth-ui/src/pages/LoginPage.svelte
@@ -5,6 +5,60 @@
import GoogleSignInButton from '../components/GoogleSignInButton.svelte';
import AppleSignInButton from '../components/AppleSignInButton.svelte';
+ /** Translation strings for the login page */
+ export interface LoginTranslations {
+ title: string;
+ subtitle: string;
+ emailPlaceholder: string;
+ passwordPlaceholder: string;
+ rememberMe: string;
+ forgotPassword: string;
+ signInButton: string;
+ signingIn: string;
+ success: string;
+ orDivider: string;
+ noAccount: string;
+ createAccount: string;
+ skipToForm: string;
+ showPassword: string;
+ hidePassword: string;
+ // Error messages
+ emailRequired: string;
+ emailInvalid: string;
+ passwordRequired: string;
+ signInFailed: string;
+ googleSignInFailed: string;
+ // Success messages
+ signInSuccess: string;
+ googleSignInSuccess: string;
+ }
+
+ /** Default English translations */
+ const defaultTranslations: LoginTranslations = {
+ title: 'Sign In',
+ subtitle: 'Sign in with your Mana account',
+ emailPlaceholder: 'Email',
+ passwordPlaceholder: 'Password',
+ rememberMe: 'Remember me',
+ forgotPassword: 'Forgot password?',
+ signInButton: 'Sign In',
+ signingIn: 'Signing in...',
+ success: 'Success!',
+ orDivider: 'or',
+ noAccount: "Don't have an account?",
+ createAccount: 'Create one',
+ skipToForm: 'Skip to login form',
+ showPassword: 'Show password',
+ hidePassword: 'Hide password',
+ emailRequired: 'Email is required',
+ emailInvalid: 'Please enter a valid email address',
+ passwordRequired: 'Password is required',
+ signInFailed: 'Sign in failed',
+ googleSignInFailed: 'Google sign in failed',
+ signInSuccess: 'Successfully signed in. Redirecting...',
+ googleSignInSuccess: 'Successfully signed in with Google. Redirecting...'
+ };
+
interface Props {
/** App name */
appName: string;
@@ -38,6 +92,8 @@
appSlider?: Snippet;
/** Header snippet for controls like theme toggle and language selector */
headerControls?: Snippet;
+ /** Translations for i18n support */
+ translations?: Partial;
}
let {
@@ -56,9 +112,13 @@
lightBackground = '#f5f5f5',
darkBackground = '#121212',
appSlider,
- headerControls
+ headerControls,
+ translations = {}
}: Props = $props();
+ // Merge provided translations with defaults
+ const t = $derived({ ...defaultTranslations, ...translations });
+
let loading = $state(false);
let error = $state(null);
let errorField = $state<'email' | 'password' | 'general' | null>(null);
@@ -135,19 +195,19 @@
clearError();
if (!email) {
- setError('Email is required', 'email');
+ setError(t.emailRequired, 'email');
loading = false;
return;
}
if (!isValidEmail(email)) {
- setError('Please enter a valid email address', 'email');
+ setError(t.emailInvalid, 'email');
loading = false;
return;
}
if (!password) {
- setError('Password is required', 'password');
+ setError(t.passwordRequired, 'password');
loading = false;
return;
}
@@ -159,12 +219,12 @@
if (result.success) {
// Show success feedback before redirect
showSuccess = true;
- successAnnouncement = 'Successfully signed in. Redirecting...';
+ successAnnouncement = t.signInSuccess;
setTimeout(() => {
goto(successRedirect);
}, 600);
} else {
- setError(result.error || 'Sign in failed', 'general');
+ setError(result.error || t.signInFailed, 'general');
}
}
@@ -179,12 +239,12 @@
if (result.success) {
showSuccess = true;
- successAnnouncement = 'Successfully signed in with Google. Redirecting...';
+ successAnnouncement = t.googleSignInSuccess;
setTimeout(() => {
goto(successRedirect);
}, 600);
} else {
- setError(result.error || 'Google sign in failed', 'general');
+ setError(result.error || t.googleSignInFailed, 'general');
}
}
@@ -285,7 +345,7 @@
onclick={skipToForm}
type="button"
>
- Skip to login form
+ {t.skipToForm}
@@ -340,13 +400,13 @@
class="text-center text-xl font-semibold"
style="color: {isDark ? 'rgba(255, 255, 255, 0.9)' : 'rgba(0, 0, 0, 0.9)'};"
>
- Sign In
+ {t.title}
- Sign in with your Mana account
+ {t.subtitle}
@@ -375,13 +435,13 @@
>
-
+
-
+
(showPassword = !showPassword)}
class="absolute right-3 top-1/2 -translate-y-1/2 p-2 rounded-lg hover:bg-black/10 dark:hover:bg-white/10 transition-colors touch-target flex items-center justify-center"
- aria-label={showPassword ? 'Hide password' : 'Show password'}
+ aria-label={showPassword ? t.hidePassword : t.showPassword}
aria-pressed={showPassword}
- title={showPassword ? 'Hide password' : 'Show password'}
+ title={showPassword ? t.hidePassword : t.showPassword}
>
- Remember me
+ {t.rememberMe}
@@ -446,7 +506,7 @@
class="text-sm font-medium transition-opacity hover:opacity-70 touch-target flex items-center justify-center px-2"
style="color: {primaryColor};"
>
- Forgot password?
+ {t.forgotPassword}
@@ -470,13 +530,13 @@
-
Signing in...
+
{t.signingIn}
{:else if showSuccess}
-
Success!
+
{t.success}
{:else}
-
Sign In
+
{t.signInButton}
{/if}
@@ -485,7 +545,7 @@
{#if enableGoogle || enableApple}
@@ -505,14 +565,14 @@
class="text-sm"
style="color: {isDark ? 'rgba(255, 255, 255, 0.6)' : 'rgba(0, 0, 0, 0.6)'};"
>
- Don't have an account?
+ {t.noAccount}
diff --git a/packages/shared-auth-ui/src/pages/RegisterPage.svelte b/packages/shared-auth-ui/src/pages/RegisterPage.svelte
index f86bad4ca..cb9be2713 100644
--- a/packages/shared-auth-ui/src/pages/RegisterPage.svelte
+++ b/packages/shared-auth-ui/src/pages/RegisterPage.svelte
@@ -5,6 +5,52 @@
import type { Snippet } from 'svelte';
+ /** Translation strings for the register page */
+ export interface RegisterTranslations {
+ title: string;
+ emailPlaceholder: string;
+ passwordPlaceholder: string;
+ confirmPasswordPlaceholder: string;
+ passwordRequirements: string;
+ createAccountButton: string;
+ creatingAccount: string;
+ backToLogin: string;
+ showPassword: string;
+ hidePassword: string;
+ // Error messages
+ emailRequired: string;
+ passwordRequired: string;
+ confirmPasswordRequired: string;
+ passwordsDoNotMatch: string;
+ passwordTooShort: string;
+ passwordStrengthError: string;
+ registrationFailed: string;
+ // Success messages
+ accountCreated: string;
+ }
+
+ /** Default English translations */
+ const defaultTranslations: RegisterTranslations = {
+ title: 'Create Account',
+ emailPlaceholder: 'Email',
+ passwordPlaceholder: 'Password',
+ confirmPasswordPlaceholder: 'Confirm Password',
+ passwordRequirements: 'Password must be at least 8 characters with lowercase, uppercase, number, and special character.',
+ createAccountButton: 'Create Account',
+ creatingAccount: 'Creating Account...',
+ backToLogin: 'Back to Login',
+ showPassword: 'Show password',
+ hidePassword: 'Hide password',
+ emailRequired: 'Email is required',
+ passwordRequired: 'Password is required',
+ confirmPasswordRequired: 'Please confirm your password',
+ passwordsDoNotMatch: 'Passwords do not match',
+ passwordTooShort: 'Password must be at least 8 characters',
+ passwordStrengthError: 'Password must include lowercase, uppercase, number, and special character',
+ registrationFailed: 'Registration failed',
+ accountCreated: 'Account created! Please check your email to verify your account.'
+ };
+
interface Props {
/** App name */
appName: string;
@@ -26,6 +72,8 @@
darkBackground?: string;
/** App slider snippet */
appSlider?: Snippet;
+ /** Translations for i18n support */
+ translations?: Partial;
}
let {
@@ -38,9 +86,13 @@
loginPath = '/login',
lightBackground = '#f5f5f5',
darkBackground = '#121212',
- appSlider
+ appSlider,
+ translations = {}
}: Props = $props();
+ // Merge provided translations with defaults
+ const t = $derived({ ...defaultTranslations, ...translations });
+
let loading = $state(false);
let error = $state(null);
let success = $state(false);
@@ -98,31 +150,31 @@
// Validation
if (!email) {
- error = 'Email is required';
+ error = t.emailRequired;
loading = false;
return;
}
if (!password) {
- error = 'Password is required';
+ error = t.passwordRequired;
loading = false;
return;
}
if (!confirmPassword) {
- error = 'Please confirm your password';
+ error = t.confirmPasswordRequired;
loading = false;
return;
}
if (password !== confirmPassword) {
- error = 'Passwords do not match';
+ error = t.passwordsDoNotMatch;
loading = false;
return;
}
if (password.length < 8) {
- error = 'Password must be at least 8 characters';
+ error = t.passwordTooShort;
loading = false;
return;
}
@@ -134,7 +186,7 @@
const hasSymbol = /[^a-zA-Z0-9]/.test(password);
if (!hasLowercase || !hasUppercase || !hasDigit || !hasSymbol) {
- error = 'Password must include lowercase, uppercase, number, and special character';
+ error = t.passwordStrengthError;
loading = false;
return;
}
@@ -153,7 +205,7 @@
goto(successRedirect);
}
} else {
- error = result.error || 'Registration failed';
+ error = result.error || t.registrationFailed;
}
}
@@ -192,7 +244,7 @@
class="mb-6 text-center text-xl font-semibold"
style="color: {isDark ? 'rgba(255, 255, 255, 0.9)' : 'rgba(0, 0, 0, 0.9)'};"
>
- Create Account
+ {t.title}
@@ -206,7 +258,7 @@
{#if success && needsVerification}
- Account created! Please check your email to verify your account.
+ {t.accountCreated}
{/if}
@@ -223,7 +275,7 @@
(showPassword = !showPassword)}
class="absolute right-3 top-1/2 -translate-y-1/2 p-2 rounded-lg hover:bg-black/10 dark:hover:bg-white/10 transition-colors"
+ aria-label={showPassword ? t.hidePassword : t.showPassword}
>
(showConfirmPassword = !showConfirmPassword)}
class="absolute right-3 top-1/2 -translate-y-1/2 p-2 rounded-lg hover:bg-black/10 dark:hover:bg-white/10 transition-colors"
+ aria-label={showConfirmPassword ? t.hidePassword : t.showPassword}
>
- Password must be at least 8 characters with lowercase, uppercase, number, and special
- character.
+ {t.passwordRequirements}
@@ -304,7 +357,7 @@
style="color: {isDark ? '#ffffff' : '#000000'};"
>
- Back to Login
+ {t.backToLogin}
diff --git a/packages/shared-i18n/src/index.ts b/packages/shared-i18n/src/index.ts
index 288aeb1e7..787c3a846 100644
--- a/packages/shared-i18n/src/index.ts
+++ b/packages/shared-i18n/src/index.ts
@@ -45,5 +45,21 @@ export {
mergeWithCommon,
} from './translations/common';
+// Auth translations
+export {
+ en as authTranslationsEn,
+ de as authTranslationsDe,
+ it as authTranslationsIt,
+ fr as authTranslationsFr,
+ es as authTranslationsEs,
+ type AuthTranslations,
+ type AuthLocale,
+ authTranslations,
+ getAuthTranslations,
+ getLoginTranslations,
+ getRegisterTranslations,
+ getForgotPasswordTranslations,
+} from './translations/auth';
+
// Components
export { LanguageSelector } from './components';
diff --git a/packages/shared-i18n/src/translations/auth/de.json b/packages/shared-i18n/src/translations/auth/de.json
new file mode 100644
index 000000000..a6de162c7
--- /dev/null
+++ b/packages/shared-i18n/src/translations/auth/de.json
@@ -0,0 +1,59 @@
+{
+ "login": {
+ "title": "Anmelden",
+ "subtitle": "Melde dich mit deinem Mana-Konto an",
+ "emailPlaceholder": "E-Mail",
+ "passwordPlaceholder": "Passwort",
+ "rememberMe": "Angemeldet bleiben",
+ "forgotPassword": "Passwort vergessen?",
+ "signInButton": "Anmelden",
+ "signingIn": "Anmeldung...",
+ "success": "Erfolgreich!",
+ "orDivider": "oder",
+ "noAccount": "Noch kein Konto?",
+ "createAccount": "Jetzt erstellen",
+ "skipToForm": "Zum Anmeldeformular springen",
+ "showPassword": "Passwort anzeigen",
+ "hidePassword": "Passwort verbergen",
+ "emailRequired": "E-Mail ist erforderlich",
+ "emailInvalid": "Bitte gib eine gültige E-Mail-Adresse ein",
+ "passwordRequired": "Passwort ist erforderlich",
+ "signInFailed": "Anmeldung fehlgeschlagen",
+ "googleSignInFailed": "Google-Anmeldung fehlgeschlagen",
+ "signInSuccess": "Erfolgreich angemeldet. Weiterleitung...",
+ "googleSignInSuccess": "Erfolgreich mit Google angemeldet. Weiterleitung..."
+ },
+ "register": {
+ "title": "Konto erstellen",
+ "emailPlaceholder": "E-Mail",
+ "passwordPlaceholder": "Passwort",
+ "confirmPasswordPlaceholder": "Passwort bestätigen",
+ "passwordRequirements": "Das Passwort muss mindestens 8 Zeichen mit Kleinbuchstaben, Großbuchstaben, Zahl und Sonderzeichen enthalten.",
+ "createAccountButton": "Konto erstellen",
+ "creatingAccount": "Konto wird erstellt...",
+ "backToLogin": "Zurück zur Anmeldung",
+ "showPassword": "Passwort anzeigen",
+ "hidePassword": "Passwort verbergen",
+ "emailRequired": "E-Mail ist erforderlich",
+ "passwordRequired": "Passwort ist erforderlich",
+ "confirmPasswordRequired": "Bitte bestätige dein Passwort",
+ "passwordsDoNotMatch": "Passwörter stimmen nicht überein",
+ "passwordTooShort": "Passwort muss mindestens 8 Zeichen lang sein",
+ "passwordStrengthError": "Passwort muss Kleinbuchstaben, Großbuchstaben, Zahl und Sonderzeichen enthalten",
+ "registrationFailed": "Registrierung fehlgeschlagen",
+ "accountCreated": "Konto erstellt! Bitte überprüfe deine E-Mails, um dein Konto zu bestätigen."
+ },
+ "forgotPassword": {
+ "titleForm": "Passwort zurücksetzen",
+ "titleSuccess": "E-Mail gesendet",
+ "description": "Gib deine E-Mail-Adresse ein und wir senden dir einen Link zum Zurücksetzen deines Passworts.",
+ "emailPlaceholder": "E-Mail",
+ "sendResetLinkButton": "Link senden",
+ "sending": "Wird gesendet...",
+ "backToLogin": "Zurück zur Anmeldung",
+ "resendEmail": "E-Mail erneut senden",
+ "successMessage": "Wir haben einen Link zum Zurücksetzen des Passworts an {email} gesendet. Bitte überprüfe deinen Posteingang.",
+ "emailRequired": "E-Mail ist erforderlich",
+ "sendFailed": "E-Mail konnte nicht gesendet werden"
+ }
+}
diff --git a/packages/shared-i18n/src/translations/auth/en.json b/packages/shared-i18n/src/translations/auth/en.json
new file mode 100644
index 000000000..c7a6130a1
--- /dev/null
+++ b/packages/shared-i18n/src/translations/auth/en.json
@@ -0,0 +1,59 @@
+{
+ "login": {
+ "title": "Sign In",
+ "subtitle": "Sign in with your Mana account",
+ "emailPlaceholder": "Email",
+ "passwordPlaceholder": "Password",
+ "rememberMe": "Remember me",
+ "forgotPassword": "Forgot password?",
+ "signInButton": "Sign In",
+ "signingIn": "Signing in...",
+ "success": "Success!",
+ "orDivider": "or",
+ "noAccount": "Don't have an account?",
+ "createAccount": "Create one",
+ "skipToForm": "Skip to login form",
+ "showPassword": "Show password",
+ "hidePassword": "Hide password",
+ "emailRequired": "Email is required",
+ "emailInvalid": "Please enter a valid email address",
+ "passwordRequired": "Password is required",
+ "signInFailed": "Sign in failed",
+ "googleSignInFailed": "Google sign in failed",
+ "signInSuccess": "Successfully signed in. Redirecting...",
+ "googleSignInSuccess": "Successfully signed in with Google. Redirecting..."
+ },
+ "register": {
+ "title": "Create Account",
+ "emailPlaceholder": "Email",
+ "passwordPlaceholder": "Password",
+ "confirmPasswordPlaceholder": "Confirm Password",
+ "passwordRequirements": "Password must be at least 8 characters with lowercase, uppercase, number, and special character.",
+ "createAccountButton": "Create Account",
+ "creatingAccount": "Creating Account...",
+ "backToLogin": "Back to Login",
+ "showPassword": "Show password",
+ "hidePassword": "Hide password",
+ "emailRequired": "Email is required",
+ "passwordRequired": "Password is required",
+ "confirmPasswordRequired": "Please confirm your password",
+ "passwordsDoNotMatch": "Passwords do not match",
+ "passwordTooShort": "Password must be at least 8 characters",
+ "passwordStrengthError": "Password must include lowercase, uppercase, number, and special character",
+ "registrationFailed": "Registration failed",
+ "accountCreated": "Account created! Please check your email to verify your account."
+ },
+ "forgotPassword": {
+ "titleForm": "Reset Password",
+ "titleSuccess": "Email Sent",
+ "description": "Enter your email address and we'll send you a link to reset your password.",
+ "emailPlaceholder": "Email",
+ "sendResetLinkButton": "Send Reset Link",
+ "sending": "Sending...",
+ "backToLogin": "Back to Login",
+ "resendEmail": "Resend Email",
+ "successMessage": "We've sent a password reset link to {email}. Please check your inbox.",
+ "emailRequired": "Email is required",
+ "sendFailed": "Failed to send reset email"
+ }
+}
diff --git a/packages/shared-i18n/src/translations/auth/es.json b/packages/shared-i18n/src/translations/auth/es.json
new file mode 100644
index 000000000..8bbd9f24a
--- /dev/null
+++ b/packages/shared-i18n/src/translations/auth/es.json
@@ -0,0 +1,59 @@
+{
+ "login": {
+ "title": "Iniciar Sesión",
+ "subtitle": "Inicia sesión con tu cuenta Mana",
+ "emailPlaceholder": "Correo electrónico",
+ "passwordPlaceholder": "Contraseña",
+ "rememberMe": "Recordarme",
+ "forgotPassword": "¿Olvidaste tu contraseña?",
+ "signInButton": "Iniciar Sesión",
+ "signingIn": "Iniciando sesión...",
+ "success": "¡Éxito!",
+ "orDivider": "o",
+ "noAccount": "¿No tienes cuenta?",
+ "createAccount": "Crear una",
+ "skipToForm": "Ir al formulario de inicio de sesión",
+ "showPassword": "Mostrar contraseña",
+ "hidePassword": "Ocultar contraseña",
+ "emailRequired": "El correo electrónico es obligatorio",
+ "emailInvalid": "Por favor ingresa un correo electrónico válido",
+ "passwordRequired": "La contraseña es obligatoria",
+ "signInFailed": "Error al iniciar sesión",
+ "googleSignInFailed": "Error al iniciar sesión con Google",
+ "signInSuccess": "Sesión iniciada correctamente. Redirigiendo...",
+ "googleSignInSuccess": "Sesión iniciada con Google correctamente. Redirigiendo..."
+ },
+ "register": {
+ "title": "Crear Cuenta",
+ "emailPlaceholder": "Correo electrónico",
+ "passwordPlaceholder": "Contraseña",
+ "confirmPasswordPlaceholder": "Confirmar Contraseña",
+ "passwordRequirements": "La contraseña debe tener al menos 8 caracteres con minúsculas, mayúsculas, números y caracteres especiales.",
+ "createAccountButton": "Crear Cuenta",
+ "creatingAccount": "Creando cuenta...",
+ "backToLogin": "Volver al inicio de sesión",
+ "showPassword": "Mostrar contraseña",
+ "hidePassword": "Ocultar contraseña",
+ "emailRequired": "El correo electrónico es obligatorio",
+ "passwordRequired": "La contraseña es obligatoria",
+ "confirmPasswordRequired": "Por favor confirma tu contraseña",
+ "passwordsDoNotMatch": "Las contraseñas no coinciden",
+ "passwordTooShort": "La contraseña debe tener al menos 8 caracteres",
+ "passwordStrengthError": "La contraseña debe incluir minúsculas, mayúsculas, números y caracteres especiales",
+ "registrationFailed": "Error en el registro",
+ "accountCreated": "¡Cuenta creada! Por favor revisa tu correo para verificar tu cuenta."
+ },
+ "forgotPassword": {
+ "titleForm": "Restablecer Contraseña",
+ "titleSuccess": "Correo Enviado",
+ "description": "Ingresa tu correo electrónico y te enviaremos un enlace para restablecer tu contraseña.",
+ "emailPlaceholder": "Correo electrónico",
+ "sendResetLinkButton": "Enviar Enlace",
+ "sending": "Enviando...",
+ "backToLogin": "Volver al inicio de sesión",
+ "resendEmail": "Reenviar correo",
+ "successMessage": "Hemos enviado un enlace de restablecimiento a {email}. Por favor revisa tu bandeja de entrada.",
+ "emailRequired": "El correo electrónico es obligatorio",
+ "sendFailed": "No se pudo enviar el correo"
+ }
+}
diff --git a/packages/shared-i18n/src/translations/auth/fr.json b/packages/shared-i18n/src/translations/auth/fr.json
new file mode 100644
index 000000000..7e666ffaf
--- /dev/null
+++ b/packages/shared-i18n/src/translations/auth/fr.json
@@ -0,0 +1,59 @@
+{
+ "login": {
+ "title": "Connexion",
+ "subtitle": "Connectez-vous avec votre compte Mana",
+ "emailPlaceholder": "Email",
+ "passwordPlaceholder": "Mot de passe",
+ "rememberMe": "Se souvenir de moi",
+ "forgotPassword": "Mot de passe oublié ?",
+ "signInButton": "Se connecter",
+ "signingIn": "Connexion...",
+ "success": "Succès !",
+ "orDivider": "ou",
+ "noAccount": "Pas encore de compte ?",
+ "createAccount": "Créer un compte",
+ "skipToForm": "Aller au formulaire de connexion",
+ "showPassword": "Afficher le mot de passe",
+ "hidePassword": "Masquer le mot de passe",
+ "emailRequired": "L'email est requis",
+ "emailInvalid": "Veuillez entrer une adresse email valide",
+ "passwordRequired": "Le mot de passe est requis",
+ "signInFailed": "Échec de la connexion",
+ "googleSignInFailed": "Échec de la connexion Google",
+ "signInSuccess": "Connexion réussie. Redirection...",
+ "googleSignInSuccess": "Connexion Google réussie. Redirection..."
+ },
+ "register": {
+ "title": "Créer un compte",
+ "emailPlaceholder": "Email",
+ "passwordPlaceholder": "Mot de passe",
+ "confirmPasswordPlaceholder": "Confirmer le mot de passe",
+ "passwordRequirements": "Le mot de passe doit contenir au moins 8 caractères avec des minuscules, majuscules, chiffres et caractères spéciaux.",
+ "createAccountButton": "Créer un compte",
+ "creatingAccount": "Création du compte...",
+ "backToLogin": "Retour à la connexion",
+ "showPassword": "Afficher le mot de passe",
+ "hidePassword": "Masquer le mot de passe",
+ "emailRequired": "L'email est requis",
+ "passwordRequired": "Le mot de passe est requis",
+ "confirmPasswordRequired": "Veuillez confirmer votre mot de passe",
+ "passwordsDoNotMatch": "Les mots de passe ne correspondent pas",
+ "passwordTooShort": "Le mot de passe doit contenir au moins 8 caractères",
+ "passwordStrengthError": "Le mot de passe doit contenir des minuscules, majuscules, chiffres et caractères spéciaux",
+ "registrationFailed": "Échec de l'inscription",
+ "accountCreated": "Compte créé ! Veuillez vérifier votre email pour activer votre compte."
+ },
+ "forgotPassword": {
+ "titleForm": "Réinitialiser le mot de passe",
+ "titleSuccess": "Email envoyé",
+ "description": "Entrez votre adresse email et nous vous enverrons un lien pour réinitialiser votre mot de passe.",
+ "emailPlaceholder": "Email",
+ "sendResetLinkButton": "Envoyer le lien",
+ "sending": "Envoi en cours...",
+ "backToLogin": "Retour à la connexion",
+ "resendEmail": "Renvoyer l'email",
+ "successMessage": "Nous avons envoyé un lien de réinitialisation à {email}. Veuillez vérifier votre boîte de réception.",
+ "emailRequired": "L'email est requis",
+ "sendFailed": "Impossible d'envoyer l'email"
+ }
+}
diff --git a/packages/shared-i18n/src/translations/auth/index.ts b/packages/shared-i18n/src/translations/auth/index.ts
new file mode 100644
index 000000000..df67a0943
--- /dev/null
+++ b/packages/shared-i18n/src/translations/auth/index.ts
@@ -0,0 +1,123 @@
+/**
+ * Auth translations exports
+ */
+
+import en from './en.json';
+import de from './de.json';
+import it from './it.json';
+import fr from './fr.json';
+import es from './es.json';
+
+export { en, de, it, fr, es };
+
+/**
+ * Auth translations type structure
+ */
+export interface AuthTranslations {
+ login: {
+ title: string;
+ subtitle: string;
+ emailPlaceholder: string;
+ passwordPlaceholder: string;
+ rememberMe: string;
+ forgotPassword: string;
+ signInButton: string;
+ signingIn: string;
+ success: string;
+ orDivider: string;
+ noAccount: string;
+ createAccount: string;
+ skipToForm: string;
+ showPassword: string;
+ hidePassword: string;
+ emailRequired: string;
+ emailInvalid: string;
+ passwordRequired: string;
+ signInFailed: string;
+ googleSignInFailed: string;
+ signInSuccess: string;
+ googleSignInSuccess: string;
+ };
+ register: {
+ title: string;
+ emailPlaceholder: string;
+ passwordPlaceholder: string;
+ confirmPasswordPlaceholder: string;
+ passwordRequirements: string;
+ createAccountButton: string;
+ creatingAccount: string;
+ backToLogin: string;
+ showPassword: string;
+ hidePassword: string;
+ emailRequired: string;
+ passwordRequired: string;
+ confirmPasswordRequired: string;
+ passwordsDoNotMatch: string;
+ passwordTooShort: string;
+ passwordStrengthError: string;
+ registrationFailed: string;
+ accountCreated: string;
+ };
+ forgotPassword: {
+ titleForm: string;
+ titleSuccess: string;
+ description: string;
+ emailPlaceholder: string;
+ sendResetLinkButton: string;
+ sending: string;
+ backToLogin: string;
+ resendEmail: string;
+ successMessage: string;
+ emailRequired: string;
+ sendFailed: string;
+ };
+}
+
+/**
+ * Supported auth locales
+ */
+export type AuthLocale = 'en' | 'de' | 'it' | 'fr' | 'es';
+
+/**
+ * All auth translations by locale
+ */
+export const authTranslations: Record = {
+ en,
+ de,
+ it,
+ fr,
+ es
+};
+
+/**
+ * Get auth translations by locale
+ */
+export function getAuthTranslations(locale: string): AuthTranslations {
+ const supportedLocale = locale as AuthLocale;
+ if (supportedLocale in authTranslations) {
+ return authTranslations[supportedLocale];
+ }
+ // Default to English
+ return authTranslations.en;
+}
+
+/**
+ * Get login translations for a specific locale
+ */
+export function getLoginTranslations(locale: string): AuthTranslations['login'] {
+ return getAuthTranslations(locale).login;
+}
+
+/**
+ * Get register translations for a specific locale
+ */
+export function getRegisterTranslations(locale: string): AuthTranslations['register'] {
+ return getAuthTranslations(locale).register;
+}
+
+/**
+ * Get forgot password translations for a specific locale
+ */
+export function getForgotPasswordTranslations(locale: string): AuthTranslations['forgotPassword'] {
+ return getAuthTranslations(locale).forgotPassword;
+}
diff --git a/packages/shared-i18n/src/translations/auth/it.json b/packages/shared-i18n/src/translations/auth/it.json
new file mode 100644
index 000000000..64d8a30fb
--- /dev/null
+++ b/packages/shared-i18n/src/translations/auth/it.json
@@ -0,0 +1,59 @@
+{
+ "login": {
+ "title": "Accedi",
+ "subtitle": "Accedi con il tuo account Mana",
+ "emailPlaceholder": "Email",
+ "passwordPlaceholder": "Password",
+ "rememberMe": "Ricordami",
+ "forgotPassword": "Password dimenticata?",
+ "signInButton": "Accedi",
+ "signingIn": "Accesso in corso...",
+ "success": "Successo!",
+ "orDivider": "oppure",
+ "noAccount": "Non hai un account?",
+ "createAccount": "Creane uno",
+ "skipToForm": "Vai al modulo di accesso",
+ "showPassword": "Mostra password",
+ "hidePassword": "Nascondi password",
+ "emailRequired": "L'email è obbligatoria",
+ "emailInvalid": "Inserisci un indirizzo email valido",
+ "passwordRequired": "La password è obbligatoria",
+ "signInFailed": "Accesso fallito",
+ "googleSignInFailed": "Accesso con Google fallito",
+ "signInSuccess": "Accesso effettuato. Reindirizzamento...",
+ "googleSignInSuccess": "Accesso con Google effettuato. Reindirizzamento..."
+ },
+ "register": {
+ "title": "Crea Account",
+ "emailPlaceholder": "Email",
+ "passwordPlaceholder": "Password",
+ "confirmPasswordPlaceholder": "Conferma Password",
+ "passwordRequirements": "La password deve contenere almeno 8 caratteri con minuscole, maiuscole, numeri e caratteri speciali.",
+ "createAccountButton": "Crea Account",
+ "creatingAccount": "Creazione account...",
+ "backToLogin": "Torna al login",
+ "showPassword": "Mostra password",
+ "hidePassword": "Nascondi password",
+ "emailRequired": "L'email è obbligatoria",
+ "passwordRequired": "La password è obbligatoria",
+ "confirmPasswordRequired": "Conferma la tua password",
+ "passwordsDoNotMatch": "Le password non corrispondono",
+ "passwordTooShort": "La password deve contenere almeno 8 caratteri",
+ "passwordStrengthError": "La password deve contenere minuscole, maiuscole, numeri e caratteri speciali",
+ "registrationFailed": "Registrazione fallita",
+ "accountCreated": "Account creato! Controlla la tua email per verificare il tuo account."
+ },
+ "forgotPassword": {
+ "titleForm": "Reimposta Password",
+ "titleSuccess": "Email Inviata",
+ "description": "Inserisci il tuo indirizzo email e ti invieremo un link per reimpostare la password.",
+ "emailPlaceholder": "Email",
+ "sendResetLinkButton": "Invia Link",
+ "sending": "Invio in corso...",
+ "backToLogin": "Torna al login",
+ "resendEmail": "Invia di nuovo",
+ "successMessage": "Abbiamo inviato un link per reimpostare la password a {email}. Controlla la tua casella di posta.",
+ "emailRequired": "L'email è obbligatoria",
+ "sendFailed": "Impossibile inviare l'email"
+ }
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f4b0544f0..93b89199e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -617,7 +617,7 @@ importers:
version: 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-router:
specifier: ~6.0.15
- version: 6.0.15(xryufifz5wj5kwzsjwy243gnce)
+ version: 6.0.15(6vtqpixpsaohn2qohrl6z3hsuy)
expo-status-bar:
specifier: ~3.0.8
version: 3.0.8(react-native@0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
@@ -742,6 +742,9 @@ importers:
'@supabase/supabase-js':
specifier: ^2.81.1
version: 2.81.1
+ svelte-i18n:
+ specifier: ^4.0.0
+ version: 4.0.1(svelte@5.43.14)
devDependencies:
'@playwright/test':
specifier: ^1.51.0
@@ -877,7 +880,7 @@ importers:
version: 8.0.9(expo@54.0.13)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))(react@19.1.0)
expo-router:
specifier: ~6.0.10
- version: 6.0.15(f27ak5avlguc2jker6h5375iqq)
+ version: 6.0.15(h2kortjfz5ptrdu2vyrckew36u)
expo-secure-store:
specifier: ^15.0.7
version: 15.0.7(expo@54.0.13)
@@ -1123,7 +1126,7 @@ importers:
version: 9.39.1
'@nestjs/cli':
specifier: ^11.0.0
- version: 11.0.12(@types/node@22.19.1)
+ version: 11.0.12(@types/node@22.19.1)(esbuild@0.25.12)
'@nestjs/schematics':
specifier: ^11.0.0
version: 11.0.9(chokidar@4.0.3)(typescript@5.9.3)
@@ -1156,7 +1159,7 @@ importers:
version: 16.5.0
jest:
specifier: ^30.0.0
- version: 30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ version: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
prettier:
specifier: ^3.4.2
version: 3.6.2
@@ -1168,10 +1171,10 @@ importers:
version: 7.1.4
ts-jest:
specifier: ^29.2.5
- version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3)
+ version: 29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.25.12)(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3)
ts-loader:
specifier: ^9.5.2
- version: 9.5.4(typescript@5.9.3)(webpack@5.100.2)
+ version: 9.5.4(typescript@5.9.3)(webpack@5.100.2(esbuild@0.25.12))
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@22.19.1)(typescript@5.9.3)
@@ -1346,7 +1349,7 @@ importers:
version: 18.2.0(expo@54.0.25)(react-native@0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0))
expo-router:
specifier: ~6.0.8
- version: 6.0.15(5rdkykxvwgevjabrjzqisvsnwm)
+ version: 6.0.15(fhrhlvzxrnwl4ouzxvkehjwypa)
expo-secure-store:
specifier: ~15.0.7
version: 15.0.7(expo@54.0.25)
@@ -1581,6 +1584,34 @@ importers:
specifier: ^7.1.7
version: 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)
+ packages/manadeck-database:
+ dependencies:
+ drizzle-orm:
+ specifier: ^0.36.0
+ version: 0.36.4(@types/react@19.2.7)(postgres@3.4.7)(react@19.1.0)
+ postgres:
+ specifier: ^3.4.5
+ version: 3.4.7
+ devDependencies:
+ '@supabase/supabase-js':
+ specifier: ^2.81.1
+ version: 2.81.1
+ '@types/node':
+ specifier: ^22.10.0
+ version: 22.19.1
+ dotenv-cli:
+ specifier: ^7.4.0
+ version: 7.4.4
+ drizzle-kit:
+ specifier: ^0.28.0
+ version: 0.28.1
+ tsx:
+ specifier: ^4.19.0
+ version: 4.20.6
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+
packages/shared-auth:
dependencies:
base64-js:
@@ -2447,6 +2478,9 @@ packages:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
+ '@drizzle-team/brocli@0.10.2':
+ resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
+
'@egjs/hammerjs@2.0.17':
resolution: {integrity: sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==}
engines: {node: '>=0.8.0'}
@@ -2482,6 +2516,14 @@ packages:
'@emnapi/wasi-threads@1.1.0':
resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
+ '@esbuild-kit/core-utils@3.3.2':
+ resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==}
+ deprecated: 'Merged into tsx: https://tsx.is'
+
+ '@esbuild-kit/esm-loader@2.6.5':
+ resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==}
+ deprecated: 'Merged into tsx: https://tsx.is'
+
'@esbuild/aix-ppc64@0.19.12':
resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==}
engines: {node: '>=12'}
@@ -2500,6 +2542,12 @@ packages:
cpu: [ppc64]
os: [aix]
+ '@esbuild/android-arm64@0.18.20':
+ resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+
'@esbuild/android-arm64@0.19.12':
resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==}
engines: {node: '>=12'}
@@ -2518,6 +2566,12 @@ packages:
cpu: [arm64]
os: [android]
+ '@esbuild/android-arm@0.18.20':
+ resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+
'@esbuild/android-arm@0.19.12':
resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==}
engines: {node: '>=12'}
@@ -2536,6 +2590,12 @@ packages:
cpu: [arm]
os: [android]
+ '@esbuild/android-x64@0.18.20':
+ resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+
'@esbuild/android-x64@0.19.12':
resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==}
engines: {node: '>=12'}
@@ -2554,6 +2614,12 @@ packages:
cpu: [x64]
os: [android]
+ '@esbuild/darwin-arm64@0.18.20':
+ resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+
'@esbuild/darwin-arm64@0.19.12':
resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==}
engines: {node: '>=12'}
@@ -2572,6 +2638,12 @@ packages:
cpu: [arm64]
os: [darwin]
+ '@esbuild/darwin-x64@0.18.20':
+ resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+
'@esbuild/darwin-x64@0.19.12':
resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==}
engines: {node: '>=12'}
@@ -2590,6 +2662,12 @@ packages:
cpu: [x64]
os: [darwin]
+ '@esbuild/freebsd-arm64@0.18.20':
+ resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+
'@esbuild/freebsd-arm64@0.19.12':
resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==}
engines: {node: '>=12'}
@@ -2608,6 +2686,12 @@ packages:
cpu: [arm64]
os: [freebsd]
+ '@esbuild/freebsd-x64@0.18.20':
+ resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+
'@esbuild/freebsd-x64@0.19.12':
resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==}
engines: {node: '>=12'}
@@ -2626,6 +2710,12 @@ packages:
cpu: [x64]
os: [freebsd]
+ '@esbuild/linux-arm64@0.18.20':
+ resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+
'@esbuild/linux-arm64@0.19.12':
resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==}
engines: {node: '>=12'}
@@ -2644,6 +2734,12 @@ packages:
cpu: [arm64]
os: [linux]
+ '@esbuild/linux-arm@0.18.20':
+ resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+
'@esbuild/linux-arm@0.19.12':
resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==}
engines: {node: '>=12'}
@@ -2662,6 +2758,12 @@ packages:
cpu: [arm]
os: [linux]
+ '@esbuild/linux-ia32@0.18.20':
+ resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+
'@esbuild/linux-ia32@0.19.12':
resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==}
engines: {node: '>=12'}
@@ -2680,6 +2782,12 @@ packages:
cpu: [ia32]
os: [linux]
+ '@esbuild/linux-loong64@0.18.20':
+ resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+
'@esbuild/linux-loong64@0.19.12':
resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==}
engines: {node: '>=12'}
@@ -2698,6 +2806,12 @@ packages:
cpu: [loong64]
os: [linux]
+ '@esbuild/linux-mips64el@0.18.20':
+ resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+
'@esbuild/linux-mips64el@0.19.12':
resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==}
engines: {node: '>=12'}
@@ -2716,6 +2830,12 @@ packages:
cpu: [mips64el]
os: [linux]
+ '@esbuild/linux-ppc64@0.18.20':
+ resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+
'@esbuild/linux-ppc64@0.19.12':
resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==}
engines: {node: '>=12'}
@@ -2734,6 +2854,12 @@ packages:
cpu: [ppc64]
os: [linux]
+ '@esbuild/linux-riscv64@0.18.20':
+ resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+
'@esbuild/linux-riscv64@0.19.12':
resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==}
engines: {node: '>=12'}
@@ -2752,6 +2878,12 @@ packages:
cpu: [riscv64]
os: [linux]
+ '@esbuild/linux-s390x@0.18.20':
+ resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+
'@esbuild/linux-s390x@0.19.12':
resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==}
engines: {node: '>=12'}
@@ -2770,6 +2902,12 @@ packages:
cpu: [s390x]
os: [linux]
+ '@esbuild/linux-x64@0.18.20':
+ resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+
'@esbuild/linux-x64@0.19.12':
resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==}
engines: {node: '>=12'}
@@ -2794,6 +2932,12 @@ packages:
cpu: [arm64]
os: [netbsd]
+ '@esbuild/netbsd-x64@0.18.20':
+ resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+
'@esbuild/netbsd-x64@0.19.12':
resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==}
engines: {node: '>=12'}
@@ -2818,6 +2962,12 @@ packages:
cpu: [arm64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.18.20':
+ resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/openbsd-x64@0.19.12':
resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==}
engines: {node: '>=12'}
@@ -2842,6 +2992,12 @@ packages:
cpu: [arm64]
os: [openharmony]
+ '@esbuild/sunos-x64@0.18.20':
+ resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+
'@esbuild/sunos-x64@0.19.12':
resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==}
engines: {node: '>=12'}
@@ -2860,6 +3016,12 @@ packages:
cpu: [x64]
os: [sunos]
+ '@esbuild/win32-arm64@0.18.20':
+ resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+
'@esbuild/win32-arm64@0.19.12':
resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==}
engines: {node: '>=12'}
@@ -2878,6 +3040,12 @@ packages:
cpu: [arm64]
os: [win32]
+ '@esbuild/win32-ia32@0.18.20':
+ resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+
'@esbuild/win32-ia32@0.19.12':
resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==}
engines: {node: '>=12'}
@@ -2896,6 +3064,12 @@ packages:
cpu: [ia32]
os: [win32]
+ '@esbuild/win32-x64@0.18.20':
+ resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+
'@esbuild/win32-x64@0.19.12':
resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==}
engines: {node: '>=12'}
@@ -7062,6 +7236,14 @@ packages:
dot-case@3.0.4:
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
+ dotenv-cli@7.4.4:
+ resolution: {integrity: sha512-XkBYCG0tPIes+YZr4SpfFv76SQrV/LeCE8CI7JSEMi3VR9MvTihCGTOtbIexD6i2mXF+6px7trb1imVCXSNMDw==}
+ hasBin: true
+
+ dotenv-expand@10.0.0:
+ resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==}
+ engines: {node: '>=12'}
+
dotenv-expand@11.0.7:
resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==}
engines: {node: '>=12'}
@@ -7078,6 +7260,102 @@ packages:
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
engines: {node: '>=12'}
+ drizzle-kit@0.28.1:
+ resolution: {integrity: sha512-JimOV+ystXTWMgZkLHYHf2w3oS28hxiH1FR0dkmJLc7GHzdGJoJAQtQS5DRppnabsRZwE2U1F6CuezVBgmsBBQ==}
+ hasBin: true
+
+ drizzle-orm@0.36.4:
+ resolution: {integrity: sha512-1OZY3PXD7BR00Gl61UUOFihslDldfH4NFRH2MbP54Yxi0G/PKn4HfO65JYZ7c16DeP3SpM3Aw+VXVG9j6CRSXA==}
+ peerDependencies:
+ '@aws-sdk/client-rds-data': '>=3'
+ '@cloudflare/workers-types': '>=3'
+ '@electric-sql/pglite': '>=0.2.0'
+ '@libsql/client': '>=0.10.0'
+ '@libsql/client-wasm': '>=0.10.0'
+ '@neondatabase/serverless': '>=0.10.0'
+ '@op-engineering/op-sqlite': '>=2'
+ '@opentelemetry/api': ^1.4.1
+ '@planetscale/database': '>=1'
+ '@prisma/client': '*'
+ '@tidbcloud/serverless': '*'
+ '@types/better-sqlite3': '*'
+ '@types/pg': '*'
+ '@types/react': '>=18'
+ '@types/sql.js': '*'
+ '@vercel/postgres': '>=0.8.0'
+ '@xata.io/client': '*'
+ better-sqlite3: '>=7'
+ bun-types: '*'
+ expo-sqlite: '>=14.0.0'
+ knex: '*'
+ kysely: '*'
+ mysql2: '>=2'
+ pg: '>=8'
+ postgres: '>=3'
+ prisma: '*'
+ react: '>=18'
+ sql.js: '>=1'
+ sqlite3: '>=5'
+ peerDependenciesMeta:
+ '@aws-sdk/client-rds-data':
+ optional: true
+ '@cloudflare/workers-types':
+ optional: true
+ '@electric-sql/pglite':
+ optional: true
+ '@libsql/client':
+ optional: true
+ '@libsql/client-wasm':
+ optional: true
+ '@neondatabase/serverless':
+ optional: true
+ '@op-engineering/op-sqlite':
+ optional: true
+ '@opentelemetry/api':
+ optional: true
+ '@planetscale/database':
+ optional: true
+ '@prisma/client':
+ optional: true
+ '@tidbcloud/serverless':
+ optional: true
+ '@types/better-sqlite3':
+ optional: true
+ '@types/pg':
+ optional: true
+ '@types/react':
+ optional: true
+ '@types/sql.js':
+ optional: true
+ '@vercel/postgres':
+ optional: true
+ '@xata.io/client':
+ optional: true
+ better-sqlite3:
+ optional: true
+ bun-types:
+ optional: true
+ expo-sqlite:
+ optional: true
+ knex:
+ optional: true
+ kysely:
+ optional: true
+ mysql2:
+ optional: true
+ pg:
+ optional: true
+ postgres:
+ optional: true
+ prisma:
+ optional: true
+ react:
+ optional: true
+ sql.js:
+ optional: true
+ sqlite3:
+ optional: true
+
dset@3.1.4:
resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==}
engines: {node: '>=4'}
@@ -7211,6 +7489,16 @@ packages:
esast-util-from-js@2.0.1:
resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==}
+ esbuild-register@3.6.0:
+ resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==}
+ peerDependencies:
+ esbuild: '>=0.12 <1'
+
+ esbuild@0.18.20:
+ resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==}
+ engines: {node: '>=12'}
+ hasBin: true
+
esbuild@0.19.12:
resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==}
engines: {node: '>=12'}
@@ -10699,6 +10987,10 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
+ postgres@3.4.7:
+ resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
+ engines: {node: '>=12'}
+
posthog-js@1.297.2:
resolution: {integrity: sha512-pDtCKHpKegV1D5Yk9PBmkFwI9FMnLJm0TsBO5c5/PhPq5Om4y/t+1qqbNcLCdLajkuYl2px9UlRTzycQ6W7Vmw==}
@@ -14344,6 +14636,8 @@ snapshots:
dependencies:
'@jridgewell/trace-mapping': 0.3.9
+ '@drizzle-team/brocli@0.10.2': {}
+
'@egjs/hammerjs@2.0.17':
dependencies:
'@types/hammerjs': 2.0.46
@@ -14387,6 +14681,16 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@esbuild-kit/core-utils@3.3.2':
+ dependencies:
+ esbuild: 0.18.20
+ source-map-support: 0.5.21
+
+ '@esbuild-kit/esm-loader@2.6.5':
+ dependencies:
+ '@esbuild-kit/core-utils': 3.3.2
+ get-tsconfig: 4.13.0
+
'@esbuild/aix-ppc64@0.19.12':
optional: true
@@ -14396,6 +14700,9 @@ snapshots:
'@esbuild/aix-ppc64@0.25.12':
optional: true
+ '@esbuild/android-arm64@0.18.20':
+ optional: true
+
'@esbuild/android-arm64@0.19.12':
optional: true
@@ -14405,6 +14712,9 @@ snapshots:
'@esbuild/android-arm64@0.25.12':
optional: true
+ '@esbuild/android-arm@0.18.20':
+ optional: true
+
'@esbuild/android-arm@0.19.12':
optional: true
@@ -14414,6 +14724,9 @@ snapshots:
'@esbuild/android-arm@0.25.12':
optional: true
+ '@esbuild/android-x64@0.18.20':
+ optional: true
+
'@esbuild/android-x64@0.19.12':
optional: true
@@ -14423,6 +14736,9 @@ snapshots:
'@esbuild/android-x64@0.25.12':
optional: true
+ '@esbuild/darwin-arm64@0.18.20':
+ optional: true
+
'@esbuild/darwin-arm64@0.19.12':
optional: true
@@ -14432,6 +14748,9 @@ snapshots:
'@esbuild/darwin-arm64@0.25.12':
optional: true
+ '@esbuild/darwin-x64@0.18.20':
+ optional: true
+
'@esbuild/darwin-x64@0.19.12':
optional: true
@@ -14441,6 +14760,9 @@ snapshots:
'@esbuild/darwin-x64@0.25.12':
optional: true
+ '@esbuild/freebsd-arm64@0.18.20':
+ optional: true
+
'@esbuild/freebsd-arm64@0.19.12':
optional: true
@@ -14450,6 +14772,9 @@ snapshots:
'@esbuild/freebsd-arm64@0.25.12':
optional: true
+ '@esbuild/freebsd-x64@0.18.20':
+ optional: true
+
'@esbuild/freebsd-x64@0.19.12':
optional: true
@@ -14459,6 +14784,9 @@ snapshots:
'@esbuild/freebsd-x64@0.25.12':
optional: true
+ '@esbuild/linux-arm64@0.18.20':
+ optional: true
+
'@esbuild/linux-arm64@0.19.12':
optional: true
@@ -14468,6 +14796,9 @@ snapshots:
'@esbuild/linux-arm64@0.25.12':
optional: true
+ '@esbuild/linux-arm@0.18.20':
+ optional: true
+
'@esbuild/linux-arm@0.19.12':
optional: true
@@ -14477,6 +14808,9 @@ snapshots:
'@esbuild/linux-arm@0.25.12':
optional: true
+ '@esbuild/linux-ia32@0.18.20':
+ optional: true
+
'@esbuild/linux-ia32@0.19.12':
optional: true
@@ -14486,6 +14820,9 @@ snapshots:
'@esbuild/linux-ia32@0.25.12':
optional: true
+ '@esbuild/linux-loong64@0.18.20':
+ optional: true
+
'@esbuild/linux-loong64@0.19.12':
optional: true
@@ -14495,6 +14832,9 @@ snapshots:
'@esbuild/linux-loong64@0.25.12':
optional: true
+ '@esbuild/linux-mips64el@0.18.20':
+ optional: true
+
'@esbuild/linux-mips64el@0.19.12':
optional: true
@@ -14504,6 +14844,9 @@ snapshots:
'@esbuild/linux-mips64el@0.25.12':
optional: true
+ '@esbuild/linux-ppc64@0.18.20':
+ optional: true
+
'@esbuild/linux-ppc64@0.19.12':
optional: true
@@ -14513,6 +14856,9 @@ snapshots:
'@esbuild/linux-ppc64@0.25.12':
optional: true
+ '@esbuild/linux-riscv64@0.18.20':
+ optional: true
+
'@esbuild/linux-riscv64@0.19.12':
optional: true
@@ -14522,6 +14868,9 @@ snapshots:
'@esbuild/linux-riscv64@0.25.12':
optional: true
+ '@esbuild/linux-s390x@0.18.20':
+ optional: true
+
'@esbuild/linux-s390x@0.19.12':
optional: true
@@ -14531,6 +14880,9 @@ snapshots:
'@esbuild/linux-s390x@0.25.12':
optional: true
+ '@esbuild/linux-x64@0.18.20':
+ optional: true
+
'@esbuild/linux-x64@0.19.12':
optional: true
@@ -14543,6 +14895,9 @@ snapshots:
'@esbuild/netbsd-arm64@0.25.12':
optional: true
+ '@esbuild/netbsd-x64@0.18.20':
+ optional: true
+
'@esbuild/netbsd-x64@0.19.12':
optional: true
@@ -14555,6 +14910,9 @@ snapshots:
'@esbuild/openbsd-arm64@0.25.12':
optional: true
+ '@esbuild/openbsd-x64@0.18.20':
+ optional: true
+
'@esbuild/openbsd-x64@0.19.12':
optional: true
@@ -14567,6 +14925,9 @@ snapshots:
'@esbuild/openharmony-arm64@0.25.12':
optional: true
+ '@esbuild/sunos-x64@0.18.20':
+ optional: true
+
'@esbuild/sunos-x64@0.19.12':
optional: true
@@ -14576,6 +14937,9 @@ snapshots:
'@esbuild/sunos-x64@0.25.12':
optional: true
+ '@esbuild/win32-arm64@0.18.20':
+ optional: true
+
'@esbuild/win32-arm64@0.19.12':
optional: true
@@ -14585,6 +14949,9 @@ snapshots:
'@esbuild/win32-arm64@0.25.12':
optional: true
+ '@esbuild/win32-ia32@0.18.20':
+ optional: true
+
'@esbuild/win32-ia32@0.19.12':
optional: true
@@ -14594,6 +14961,9 @@ snapshots:
'@esbuild/win32-ia32@0.25.12':
optional: true
+ '@esbuild/win32-x64@0.18.20':
+ optional: true
+
'@esbuild/win32-x64@0.19.12':
optional: true
@@ -14742,7 +15112,7 @@ snapshots:
wrap-ansi: 7.0.0
ws: 8.18.3
optionalDependencies:
- expo-router: 6.0.15(f27ak5avlguc2jker6h5375iqq)
+ expo-router: 6.0.15(h2kortjfz5ptrdu2vyrckew36u)
react-native: 0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
transitivePeerDependencies:
- '@modelcontextprotocol/sdk'
@@ -14819,7 +15189,7 @@ snapshots:
wrap-ansi: 7.0.0
ws: 8.18.3
optionalDependencies:
- expo-router: 6.0.15(5rdkykxvwgevjabrjzqisvsnwm)
+ expo-router: 6.0.15(fhrhlvzxrnwl4ouzxvkehjwypa)
react-native: 0.81.4(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
transitivePeerDependencies:
- '@modelcontextprotocol/sdk'
@@ -14896,7 +15266,7 @@ snapshots:
wrap-ansi: 7.0.0
ws: 8.18.3
optionalDependencies:
- expo-router: 6.0.15(ezsgqtdheoeph6fqqf6q7ixwnu)
+ expo-router: 6.0.15(6vtqpixpsaohn2qohrl6z3hsuy)
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
transitivePeerDependencies:
- '@modelcontextprotocol/sdk'
@@ -15859,7 +16229,7 @@ snapshots:
- supports-color
- ts-node
- '@jest/core@30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))':
+ '@jest/core@30.2.0(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))':
dependencies:
'@jest/console': 30.2.0
'@jest/pattern': 30.0.1
@@ -15874,7 +16244,7 @@ snapshots:
exit-x: 0.2.2
graceful-fs: 4.2.11
jest-changed-files: 30.2.0
- jest-config: 30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest-config: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
jest-haste-map: 30.2.0
jest-message-util: 30.2.0
jest-regex-util: 30.0.1
@@ -16281,7 +16651,7 @@ snapshots:
- uglify-js
- webpack-cli
- '@nestjs/cli@11.0.12(@types/node@22.19.1)':
+ '@nestjs/cli@11.0.12(@types/node@22.19.1)(esbuild@0.25.12)':
dependencies:
'@angular-devkit/core': 19.2.19(chokidar@4.0.3)
'@angular-devkit/schematics': 19.2.19(chokidar@4.0.3)
@@ -16292,14 +16662,14 @@ snapshots:
chokidar: 4.0.3
cli-table3: 0.6.5
commander: 4.1.1
- fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.100.2)
+ fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.100.2(esbuild@0.25.12))
glob: 12.0.0
node-emoji: 1.11.0
ora: 5.4.1
tsconfig-paths: 4.2.0
tsconfig-paths-webpack-plugin: 4.2.0
typescript: 5.9.3
- webpack: 5.100.2
+ webpack: 5.100.2(esbuild@0.25.12)
webpack-node-externals: 3.0.0
transitivePeerDependencies:
- '@types/node'
@@ -17774,7 +18144,7 @@ snapshots:
optionalDependencies:
jest: 29.5.0(@types/node@18.15.11)(ts-node@10.9.2(@types/node@18.15.11)(typescript@5.9.3))
- '@testing-library/react-native@13.3.3(jest@30.2.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)':
+ '@testing-library/react-native@13.3.3(jest@30.2.0(esbuild-register@3.6.0(esbuild@0.25.12)))(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
@@ -17784,10 +18154,10 @@ 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)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
optional: true
- '@testing-library/react-native@13.3.3(jest@30.2.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@30.2.0(esbuild-register@3.6.0(esbuild@0.25.12)))(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
@@ -17797,7 +18167,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)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
optional: true
'@tokenizer/inflate@0.2.7':
@@ -20261,18 +20631,42 @@ snapshots:
no-case: 3.0.4
tslib: 2.8.1
+ dotenv-cli@7.4.4:
+ dependencies:
+ cross-spawn: 7.0.6
+ dotenv: 16.6.1
+ dotenv-expand: 10.0.0
+ minimist: 1.2.8
+
+ dotenv-expand@10.0.0: {}
+
dotenv-expand@11.0.7:
dependencies:
- dotenv: 16.4.7
+ dotenv: 16.6.1
dotenv-expand@12.0.1:
dependencies:
- dotenv: 16.4.7
+ dotenv: 16.6.1
dotenv@16.4.7: {}
dotenv@16.6.1: {}
+ drizzle-kit@0.28.1:
+ dependencies:
+ '@drizzle-team/brocli': 0.10.2
+ '@esbuild-kit/esm-loader': 2.6.5
+ esbuild: 0.19.12
+ esbuild-register: 3.6.0(esbuild@0.19.12)
+ transitivePeerDependencies:
+ - supports-color
+
+ drizzle-orm@0.36.4(@types/react@19.2.7)(postgres@3.4.7)(react@19.1.0):
+ optionalDependencies:
+ '@types/react': 19.2.7
+ postgres: 3.4.7
+ react: 19.1.0
+
dset@3.1.4: {}
dunder-proto@1.0.1:
@@ -20487,6 +20881,46 @@ snapshots:
esast-util-from-estree: 2.0.0
vfile-message: 4.0.3
+ esbuild-register@3.6.0(esbuild@0.19.12):
+ dependencies:
+ debug: 4.4.3
+ esbuild: 0.19.12
+ transitivePeerDependencies:
+ - supports-color
+
+ esbuild-register@3.6.0(esbuild@0.25.12):
+ dependencies:
+ debug: 4.4.3
+ esbuild: 0.25.12
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ esbuild@0.18.20:
+ optionalDependencies:
+ '@esbuild/android-arm': 0.18.20
+ '@esbuild/android-arm64': 0.18.20
+ '@esbuild/android-x64': 0.18.20
+ '@esbuild/darwin-arm64': 0.18.20
+ '@esbuild/darwin-x64': 0.18.20
+ '@esbuild/freebsd-arm64': 0.18.20
+ '@esbuild/freebsd-x64': 0.18.20
+ '@esbuild/linux-arm': 0.18.20
+ '@esbuild/linux-arm64': 0.18.20
+ '@esbuild/linux-ia32': 0.18.20
+ '@esbuild/linux-loong64': 0.18.20
+ '@esbuild/linux-mips64el': 0.18.20
+ '@esbuild/linux-ppc64': 0.18.20
+ '@esbuild/linux-riscv64': 0.18.20
+ '@esbuild/linux-s390x': 0.18.20
+ '@esbuild/linux-x64': 0.18.20
+ '@esbuild/netbsd-x64': 0.18.20
+ '@esbuild/openbsd-x64': 0.18.20
+ '@esbuild/sunos-x64': 0.18.20
+ '@esbuild/win32-arm64': 0.18.20
+ '@esbuild/win32-ia32': 0.18.20
+ '@esbuild/win32-x64': 0.18.20
+
esbuild@0.19.12:
optionalDependencies:
'@esbuild/aix-ppc64': 0.19.12
@@ -20598,7 +21032,7 @@ snapshots:
'@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.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.47.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)(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.47.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-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.47.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-react: 7.37.5(eslint@9.39.1(jiti@2.6.1))
@@ -20672,7 +21106,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(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.47.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
@@ -20697,14 +21131,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.47.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)):
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.47.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.47.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)):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.47.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)(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.47.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))
transitivePeerDependencies:
- supports-color
@@ -20776,7 +21210,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.47.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))
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.47.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.47.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))
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -21371,7 +21805,7 @@ snapshots:
expo-device@8.0.9(expo@54.0.25):
dependencies:
- 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: 54.0.25(@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)
ua-parser-js: 0.7.41
expo-document-picker@14.0.7(expo@54.0.25):
@@ -21426,7 +21860,7 @@ snapshots:
expo-image-loader@6.0.0(expo@54.0.25):
dependencies:
- 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: 54.0.25(@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)
expo-image-picker@17.0.8(expo@54.0.13):
dependencies:
@@ -21435,7 +21869,7 @@ snapshots:
expo-image-picker@17.0.8(expo@54.0.25):
dependencies:
- 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: 54.0.25(@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)
expo-image-loader: 6.0.0(expo@54.0.25)
expo-image@3.0.10(expo@54.0.25)(react-native-web@0.21.2(react-dom@19.1.0(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):
@@ -21502,7 +21936,7 @@ snapshots:
expo-localization@17.0.7(expo@54.0.25)(react@19.1.0):
dependencies:
- 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: 54.0.25(@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)
react: 19.1.0
rtl-detect: 1.1.2
@@ -21574,21 +22008,21 @@ snapshots:
react: 19.1.0
react-native: 0.81.5(@babel/core@7.28.5)(@types/react@19.2.7)(react@19.1.0)
- expo-router@6.0.15(5rdkykxvwgevjabrjzqisvsnwm):
+ expo-router@6.0.15(6vtqpixpsaohn2qohrl6z3hsuy):
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/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.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.7.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)
+ '@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.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: 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
@@ -21596,10 +22030,10 @@ snapshots:
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)
+ 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
@@ -21607,13 +22041,13 @@ snapshots:
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.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-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)(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-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.5.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@30.2.0(esbuild-register@3.6.0(esbuild@0.25.12)))(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.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.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-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.5.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)
+ 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.25.12))
transitivePeerDependencies:
- '@react-native-masked-view/masked-view'
- '@types/react'
@@ -21666,7 +22100,53 @@ snapshots:
- '@types/react-dom'
- supports-color
- expo-router@6.0.15(f27ak5avlguc2jker6h5375iqq):
+ expo-router@6.0.15(fhrhlvzxrnwl4ouzxvkehjwypa):
+ 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.7.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@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.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-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(esbuild-register@3.6.0(esbuild@0.25.12)))(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.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-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.25.12))
+ transitivePeerDependencies:
+ - '@react-native-masked-view/masked-view'
+ - '@types/react'
+ - '@types/react-dom'
+ - supports-color
+
+ expo-router@6.0.15(h2kortjfz5ptrdu2vyrckew36u):
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)
'@expo/schema-utils': 0.1.7
@@ -21700,58 +22180,12 @@ snapshots:
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.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-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)(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)
+ '@testing-library/react-native': 13.3.3(jest@30.2.0(esbuild-register@3.6.0(esbuild@0.25.12)))(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.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-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(xryufifz5wj5kwzsjwy243gnce):
- 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.5.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@30.2.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.5.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)
+ 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.25.12))
transitivePeerDependencies:
- '@react-native-masked-view/masked-view'
- '@types/react'
@@ -21764,7 +22198,7 @@ snapshots:
expo-secure-store@15.0.7(expo@54.0.25):
dependencies:
- 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: 54.0.25(@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)
expo-server@1.0.4: {}
@@ -21775,7 +22209,7 @@ snapshots:
expo-splash-screen@31.0.11(expo@54.0.25):
dependencies:
'@expo/prebuild-config': 54.0.6(expo@54.0.25)
- 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: 54.0.25(@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)
transitivePeerDependencies:
- supports-color
@@ -22309,7 +22743,7 @@ snapshots:
typescript: 5.7.2
webpack: 5.97.1
- fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.100.2):
+ fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.100.2(esbuild@0.25.12)):
dependencies:
'@babel/code-frame': 7.27.1
chalk: 4.1.2
@@ -22324,7 +22758,7 @@ snapshots:
semver: 7.7.3
tapable: 2.3.0
typescript: 5.9.3
- webpack: 5.100.2
+ webpack: 5.100.2(esbuild@0.25.12)
form-data@2.5.5:
dependencies:
@@ -23384,15 +23818,15 @@ snapshots:
- supports-color
- ts-node
- jest-cli@30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
+ jest-cli@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
dependencies:
- '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.25.12))(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)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest-config: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(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
@@ -23465,7 +23899,7 @@ snapshots:
- babel-plugin-macros
- supports-color
- jest-config@30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
+ jest-config@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
dependencies:
'@babel/core': 7.28.5
'@jest/get-type': 30.1.0
@@ -23493,6 +23927,7 @@ snapshots:
strip-json-comments: 3.1.1
optionalDependencies:
'@types/node': 22.19.1
+ esbuild-register: 3.6.0(esbuild@0.25.12)
ts-node: 10.9.2(@types/node@22.19.1)(typescript@5.9.3)
transitivePeerDependencies:
- babel-plugin-macros
@@ -24008,12 +24443,12 @@ snapshots:
- supports-color
- ts-node
- jest@30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
+ jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)):
dependencies:
- '@jest/core': 30.2.0(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ '@jest/core': 30.2.0(esbuild-register@3.6.0(esbuild@0.25.12))(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(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest-cli: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
transitivePeerDependencies:
- '@types/node'
- babel-plugin-macros
@@ -26100,6 +26535,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ postgres@3.4.7: {}
+
posthog-js@1.297.2:
dependencies:
'@posthog/core': 1.5.5
@@ -26782,6 +27219,16 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.7
+ 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.25.12)):
+ dependencies:
+ acorn-loose: 8.5.2
+ neo-async: 2.6.2
+ react: 19.1.0
+ react-dom: 19.1.0(react@19.1.0)
+ webpack: 5.100.2(esbuild@0.25.12)
+ webpack-sources: 3.3.3
+ optional: true
+
react-server-dom-webpack@19.0.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(webpack@5.100.2):
dependencies:
acorn-loose: 8.5.2
@@ -27924,6 +28371,17 @@ snapshots:
ansi-escapes: 4.3.2
supports-hyperlinks: 2.3.0
+ terser-webpack-plugin@5.3.14(esbuild@0.25.12)(webpack@5.100.2(esbuild@0.25.12)):
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.31
+ jest-worker: 27.5.1
+ schema-utils: 4.3.3
+ serialize-javascript: 6.0.2
+ terser: 5.44.1
+ webpack: 5.100.2(esbuild@0.25.12)
+ optionalDependencies:
+ esbuild: 0.25.12
+
terser-webpack-plugin@5.3.14(webpack@5.100.2):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -28071,12 +28529,12 @@ snapshots:
'@jest/types': 29.6.3
babel-jest: 29.7.0(@babel/core@7.28.5)
- ts-jest@29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3):
+ ts-jest@29.4.5(@babel/core@7.28.5)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.28.5))(esbuild@0.25.12)(jest-util@30.2.0)(jest@30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3)))(typescript@5.9.3):
dependencies:
bs-logger: 0.2.6
fast-json-stable-stringify: 2.1.0
handlebars: 4.7.8
- jest: 30.2.0(@types/node@22.19.1)(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
+ jest: 30.2.0(@types/node@22.19.1)(esbuild-register@3.6.0(esbuild@0.25.12))(ts-node@10.9.2(@types/node@22.19.1)(typescript@5.9.3))
json5: 2.2.3
lodash.memoize: 4.1.2
make-error: 1.3.6
@@ -28089,9 +28547,10 @@ snapshots:
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
babel-jest: 30.2.0(@babel/core@7.28.5)
+ esbuild: 0.25.12
jest-util: 30.2.0
- ts-loader@9.5.4(typescript@5.9.3)(webpack@5.100.2):
+ ts-loader@9.5.4(typescript@5.9.3)(webpack@5.100.2(esbuild@0.25.12)):
dependencies:
chalk: 4.1.2
enhanced-resolve: 5.18.3
@@ -28099,7 +28558,7 @@ snapshots:
semver: 7.7.3
source-map: 0.7.6
typescript: 5.9.3
- webpack: 5.100.2
+ webpack: 5.100.2(esbuild@0.25.12)
ts-loader@9.5.4(typescript@5.9.3)(webpack@5.97.1):
dependencies:
@@ -28956,6 +29415,38 @@ snapshots:
- esbuild
- uglify-js
+ webpack@5.100.2(esbuild@0.25.12):
+ dependencies:
+ '@types/eslint-scope': 3.7.7
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
+ '@webassemblyjs/ast': 1.14.1
+ '@webassemblyjs/wasm-edit': 1.14.1
+ '@webassemblyjs/wasm-parser': 1.14.1
+ acorn: 8.15.0
+ acorn-import-phases: 1.0.4(acorn@8.15.0)
+ browserslist: 4.28.0
+ chrome-trace-event: 1.0.4
+ enhanced-resolve: 5.18.3
+ es-module-lexer: 1.7.0
+ eslint-scope: 5.1.1
+ events: 3.3.0
+ glob-to-regexp: 0.4.1
+ graceful-fs: 4.2.11
+ json-parse-even-better-errors: 2.3.1
+ loader-runner: 4.3.1
+ mime-types: 2.1.35
+ neo-async: 2.6.2
+ schema-utils: 4.3.3
+ tapable: 2.3.0
+ terser-webpack-plugin: 5.3.14(esbuild@0.25.12)(webpack@5.100.2(esbuild@0.25.12))
+ watchpack: 2.4.4
+ webpack-sources: 3.3.3
+ transitivePeerDependencies:
+ - '@swc/core'
+ - esbuild
+ - uglify-js
+
webpack@5.97.1:
dependencies:
'@types/eslint-scope': 3.7.7