From c8ac1e7f473005a574845427b10a4167eb1c8cf8 Mon Sep 17 00:00:00 2001 From: Peter Joshua Brion Date: Sun, 30 Aug 2026 18:34:09 +0800 Subject: [PATCH 1/5] fix(savings): enhance savings goal schema, full CRUD endpoints, and interactive UI for Stellar/Soroban readiness --- backend/src/savings/savings-goal.schema.ts | 28 +- backend/src/savings/savings.controller.ts | 42 ++- backend/src/savings/savings.dto.ts | 100 +++++- backend/src/savings/savings.service.ts | 103 +++++- src/app/(tabs)/savings.tsx | 365 ++++++++++++++++++++- src/lib/api.ts | 25 +- 6 files changed, 619 insertions(+), 44 deletions(-) diff --git a/backend/src/savings/savings-goal.schema.ts b/backend/src/savings/savings-goal.schema.ts index 40383d5..dd07402 100644 --- a/backend/src/savings/savings-goal.schema.ts +++ b/backend/src/savings/savings-goal.schema.ts @@ -3,6 +3,8 @@ import { Document } from 'mongoose'; export type SavingsGoalDocument = SavingsGoal & Document; +export type SavingsGoalStatus = 'draft' | 'pending' | 'active' | 'completed' | 'withdrawn'; + @Schema({ timestamps: true }) export class SavingsGoal { @Prop({ required: true, trim: true }) @@ -14,20 +16,32 @@ export class SavingsGoal { @Prop({ required: true, min: 0, default: 0 }) fundedAmount: number; - @Prop() + @Prop({ trim: true }) targetDate?: string; - @Prop({ default: 'XLM' }) + @Prop({ required: true, default: 'XLM', trim: true }) asset: string; - @Prop({ enum: ['draft'], default: 'draft' }) - status: string; + @Prop({ + required: true, + enum: ['draft', 'pending', 'active', 'completed', 'withdrawn'], + default: 'draft', + }) + status: SavingsGoalStatus; - @Prop() - transactionHash?: string; + @Prop({ trim: true, default: 'testnet' }) + network: string; + + @Prop({ trim: true }) + ownerAddress?: string; - @Prop() + @Prop({ trim: true }) contractId?: string; + + @Prop({ trim: true }) + transactionHash?: string; } export const SavingsGoalSchema = SchemaFactory.createForClass(SavingsGoal); +SavingsGoalSchema.index({ status: 1, createdAt: -1 }); +SavingsGoalSchema.index({ ownerAddress: 1, status: 1 }); diff --git a/backend/src/savings/savings.controller.ts b/backend/src/savings/savings.controller.ts index 8ee6457..b85f06c 100644 --- a/backend/src/savings/savings.controller.ts +++ b/backend/src/savings/savings.controller.ts @@ -1,10 +1,42 @@ -import { Body, Controller, Get, Post } from '@nestjs/common'; -import { CreateSavingsGoalDto } from './savings.dto'; +import { + Body, + Controller, + Delete, + Get, + Param, + Patch, + Post, +} from '@nestjs/common'; + +import { CreateSavingsGoalDto, UpdateSavingsGoalDto } from './savings.dto'; import { SavingsService } from './savings.service'; @Controller('savings-goals') export class SavingsController { - constructor(private readonly savings: SavingsService) {} - @Get() findAll() { return this.savings.findAll(); } - @Post() create(@Body() dto: CreateSavingsGoalDto) { return this.savings.create(dto); } + constructor(private readonly savingsService: SavingsService) {} + + @Get() + findAll() { + return this.savingsService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.savingsService.findOne(id); + } + + @Post() + create(@Body() dto: CreateSavingsGoalDto) { + return this.savingsService.create(dto); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() dto: UpdateSavingsGoalDto) { + return this.savingsService.update(id, dto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.savingsService.remove(id); + } } diff --git a/backend/src/savings/savings.dto.ts b/backend/src/savings/savings.dto.ts index c612cb7..53ffa9d 100644 --- a/backend/src/savings/savings.dto.ts +++ b/backend/src/savings/savings.dto.ts @@ -1,8 +1,98 @@ -import { IsNumber, IsOptional, IsPositive, IsString } from 'class-validator'; +import { + IsEnum, + IsNotEmpty, + IsNumber, + IsOptional, + IsPositive, + IsString, + Min, +} from 'class-validator'; +import { SavingsGoalStatus } from './savings-goal.schema'; export class CreateSavingsGoalDto { - @IsString() name: string; - @IsNumber() @IsPositive() targetAmount: number; - @IsOptional() @IsString() targetDate?: string; - @IsOptional() @IsString() asset?: string; + @IsString() + @IsNotEmpty() + name: string; + + @IsNumber() + @IsPositive() + targetAmount: number; + + @IsOptional() + @IsNumber() + @Min(0) + fundedAmount?: number; + + @IsOptional() + @IsString() + targetDate?: string; + + @IsOptional() + @IsString() + asset?: string; + + @IsOptional() + @IsEnum(['draft', 'pending', 'active', 'completed', 'withdrawn']) + status?: SavingsGoalStatus; + + @IsOptional() + @IsString() + network?: string; + + @IsOptional() + @IsString() + ownerAddress?: string; + + @IsOptional() + @IsString() + contractId?: string; + + @IsOptional() + @IsString() + transactionHash?: string; +} + +export class UpdateSavingsGoalDto { + @IsOptional() + @IsString() + @IsNotEmpty() + name?: string; + + @IsOptional() + @IsNumber() + @IsPositive() + targetAmount?: number; + + @IsOptional() + @IsNumber() + @Min(0) + fundedAmount?: number; + + @IsOptional() + @IsString() + targetDate?: string; + + @IsOptional() + @IsString() + asset?: string; + + @IsOptional() + @IsEnum(['draft', 'pending', 'active', 'completed', 'withdrawn']) + status?: SavingsGoalStatus; + + @IsOptional() + @IsString() + network?: string; + + @IsOptional() + @IsString() + ownerAddress?: string; + + @IsOptional() + @IsString() + contractId?: string; + + @IsOptional() + @IsString() + transactionHash?: string; } diff --git a/backend/src/savings/savings.service.ts b/backend/src/savings/savings.service.ts index df9c7ad..a8d37fe 100644 --- a/backend/src/savings/savings.service.ts +++ b/backend/src/savings/savings.service.ts @@ -1,9 +1,9 @@ -import { Injectable, OnModuleInit } from '@nestjs/common'; +import { Injectable, NotFoundException, OnModuleInit } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; -import { Model } from 'mongoose'; +import { Model, Types } from 'mongoose'; -import { CreateSavingsGoalDto } from './savings.dto'; -import { SavingsGoal, SavingsGoalDocument } from './savings-goal.schema'; +import { CreateSavingsGoalDto, UpdateSavingsGoalDto } from './savings.dto'; +import { SavingsGoal, SavingsGoalDocument, SavingsGoalStatus } from './savings-goal.schema'; import { DEMO_SAVINGS_GOALS } from '../seed/demo-data'; export type SavingsGoalResponse = { @@ -13,9 +13,11 @@ export type SavingsGoalResponse = { fundedAmount: number; targetDate?: string; asset: string; - status: 'draft'; - transactionHash?: string; + status: SavingsGoalStatus; + network?: string; + ownerAddress?: string; contractId?: string; + transactionHash?: string; }; function toSavingsGoalResponse(doc: any): SavingsGoalResponse { @@ -27,14 +29,19 @@ function toSavingsGoalResponse(doc: any): SavingsGoalResponse { targetDate: doc.targetDate, asset: doc.asset ?? 'XLM', status: doc.status ?? 'draft', - transactionHash: doc.transactionHash, + network: doc.network ?? 'testnet', + ownerAddress: doc.ownerAddress, contractId: doc.contractId, + transactionHash: doc.transactionHash, }; } @Injectable() export class SavingsService implements OnModuleInit { - private inMemoryGoals: SavingsGoalResponse[] = DEMO_SAVINGS_GOALS.map(toSavingsGoalResponse); + private inMemoryGoals: SavingsGoalResponse[] = DEMO_SAVINGS_GOALS.map((g) => ({ + ...g, + network: 'testnet', + })); constructor(@InjectModel(SavingsGoal.name) private readonly savingsGoalModel: Model) {} @@ -50,6 +57,7 @@ export class SavingsService implements OnModuleInit { targetDate, asset, status, + network: 'testnet', })), ); } @@ -68,15 +76,35 @@ export class SavingsService implements OnModuleInit { return this.inMemoryGoals; } + async findOne(id: string): Promise { + try { + if (Types.ObjectId.isValid(id)) { + const goal = await this.savingsGoalModel.findById(id).lean(); + if (goal) return toSavingsGoalResponse(goal); + } + } catch { + // Fallback + } + + const fallback = this.inMemoryGoals.find((g) => g.id === id); + if (fallback) return fallback; + + throw new NotFoundException(`Savings goal with id ${id} not found`); + } + async create(dto: CreateSavingsGoalDto): Promise { try { const goal = new this.savingsGoalModel({ name: dto.name, targetAmount: dto.targetAmount, - fundedAmount: 0, + fundedAmount: dto.fundedAmount ?? 0, targetDate: dto.targetDate, asset: dto.asset ?? 'XLM', - status: 'draft', + status: dto.status ?? 'draft', + network: dto.network ?? 'testnet', + ownerAddress: dto.ownerAddress, + contractId: dto.contractId, + transactionHash: dto.transactionHash, }); const saved = await goal.save(); return toSavingsGoalResponse(saved.toObject()); @@ -85,13 +113,64 @@ export class SavingsService implements OnModuleInit { id: `goal_${Date.now()}`, name: dto.name, targetAmount: dto.targetAmount, - fundedAmount: 0, + fundedAmount: dto.fundedAmount ?? 0, targetDate: dto.targetDate, asset: dto.asset ?? 'XLM', - status: 'draft', + status: dto.status ?? 'draft', + network: dto.network ?? 'testnet', + ownerAddress: dto.ownerAddress, + contractId: dto.contractId, + transactionHash: dto.transactionHash, }; this.inMemoryGoals.unshift(fallback); return fallback; } } + + async update(id: string, dto: UpdateSavingsGoalDto): Promise { + try { + if (Types.ObjectId.isValid(id)) { + const updated = await this.savingsGoalModel + .findByIdAndUpdate( + id, + { $set: Object.fromEntries(Object.entries(dto).filter(([, value]) => value !== undefined)) }, + { new: true }, + ) + .lean(); + if (updated) return toSavingsGoalResponse(updated); + } + } catch { + // Fallback + } + + const index = this.inMemoryGoals.findIndex((g) => g.id === id); + if (index !== -1) { + this.inMemoryGoals[index] = { + ...this.inMemoryGoals[index], + ...Object.fromEntries(Object.entries(dto).filter(([, value]) => value !== undefined)), + }; + return this.inMemoryGoals[index]; + } + + throw new NotFoundException(`Savings goal with id ${id} not found`); + } + + async remove(id: string): Promise<{ deleted: boolean }> { + try { + if (Types.ObjectId.isValid(id)) { + const deleted = await this.savingsGoalModel.findByIdAndDelete(id).lean(); + if (deleted) return { deleted: true }; + } + } catch { + // Fallback + } + + const index = this.inMemoryGoals.findIndex((g) => g.id === id); + if (index !== -1) { + this.inMemoryGoals.splice(index, 1); + return { deleted: true }; + } + + throw new NotFoundException(`Savings goal with id ${id} not found`); + } } diff --git a/src/app/(tabs)/savings.tsx b/src/app/(tabs)/savings.tsx index a8c2cd8..06fcfbd 100644 --- a/src/app/(tabs)/savings.tsx +++ b/src/app/(tabs)/savings.tsx @@ -1,22 +1,363 @@ -import { useEffect, useState } from 'react'; -import { Pressable, Text, TextInput, View } from 'react-native'; +import { useCallback, useEffect, useState } from 'react'; +import { Alert, Pressable, StyleSheet, Text, TextInput, View } from 'react-native'; import { FinancePage, financePageStyles as styles } from '@/components/layout/finance-page'; -import { createSavingsGoal, fetchSavingsGoals, type ApiSavingsGoal } from '@/lib/api'; +import { + createSavingsGoal, + deleteSavingsGoal, + fetchSavingsGoals, + type ApiSavingsGoal, +} from '@/lib/api'; export default function SavingsScreen() { const [goals, setGoals] = useState([]); - const [form, setForm] = useState({ name: '', targetAmount: '', targetDate: '' }); + const [loading, setLoading] = useState(true); + const [form, setForm] = useState({ + name: '', + targetAmount: '', + targetDate: '', + asset: 'XLM', + }); const [message, setMessage] = useState(null); - useEffect(() => { void fetchSavingsGoals().then(setGoals).catch(() => setMessage('Savings API unavailable.')); }, []); + + const loadGoals = useCallback(async () => { + try { + setLoading(true); + const items = await fetchSavingsGoals(); + setGoals(items); + setMessage(null); + } catch { + setMessage('Savings API unavailable.'); + } finally { + setLoading(false); + } + }, []); + + useEffect(() => { + void loadGoals(); + }, [loadGoals]); + const create = async () => { const targetAmount = Number(form.targetAmount); - if (!form.name.trim() || !Number.isFinite(targetAmount) || targetAmount <= 0) return setMessage('Enter a goal name and valid target.'); - try { const goal = await createSavingsGoal({ name: form.name.trim(), targetAmount, targetDate: form.targetDate || undefined, asset: 'XLM' }); setGoals((items) => [goal, ...items]); setForm({ name: '', targetAmount: '', targetDate: '' }); setMessage(null); } - catch { setMessage('Savings API unavailable.'); } + if (!form.name.trim() || !Number.isFinite(targetAmount) || targetAmount <= 0) { + return setMessage('Enter a valid goal name and positive target amount.'); + } + + try { + const goal = await createSavingsGoal({ + name: form.name.trim(), + targetAmount, + targetDate: form.targetDate || undefined, + asset: form.asset, + status: 'draft', + network: 'testnet', + }); + setGoals((items) => [goal, ...items]); + setForm({ name: '', targetAmount: '', targetDate: '', asset: 'XLM' }); + setMessage(null); + } catch { + setMessage('Failed to create savings goal. API unavailable.'); + } + }; + + const removeGoal = (id: string, name: string) => { + Alert.alert('Delete savings goal?', `Are you sure you want to delete "${name}"?`, [ + { text: 'Cancel', style: 'cancel' }, + { + text: 'Delete', + style: 'destructive', + onPress: async () => { + try { + await deleteSavingsGoal(id); + setGoals((prev) => prev.filter((g) => g.id !== id)); + } catch { + Alert.alert('Error', 'Failed to delete goal.'); + } + }, + }, + ]); }; - return - {goals.map((goal) => {goal.name}{goal.fundedAmount} / {goal.targetAmount} {goal.asset}{goal.status} · {goal.targetDate || 'No target date'} · awaiting Soroban deployment)}{!goals.length ? <>No savings goals yetCreate an off-chain draft below. Funding remains unavailable until the verified Soroban integration is complete. : null} - Create goal draft{[['Goal name', 'name'], ['Target amount in XLM', 'targetAmount'], ['Target date (YYYY-MM-DD)', 'targetDate']].map(([placeholder, key]) => setForm((current) => ({ ...current, [key]: value }))} />)}{message ? {message} : null}Save goal draft - ; + + return ( + + + + Active Goals ({goals.length}) + + {loading ? 'Refreshing…' : '↻ Refresh'} + + + + {goals.map((goal) => { + const percent = Math.min( + Math.round(((goal.fundedAmount || 0) / Math.max(goal.targetAmount, 1)) * 100), + 100, + ); + + return ( + + + + {goal.name} + + + {goal.status.toUpperCase()} + + + {goal.asset} + + + + removeGoal(goal.id, goal.name)} + hitSlop={8} + style={localStyles.deleteButton}> + + + + + + + {goal.fundedAmount.toLocaleString('en-US')} / {goal.targetAmount.toLocaleString('en-US')} {goal.asset} + + {percent}% funded + + + + + + + + + {goal.targetDate ? `Target: ${goal.targetDate}` : 'No deadline'} · Stellar {goal.network ?? 'testnet'} + + {goal.contractId ? ( + + Vault: {goal.contractId.slice(0, 8)}... + + ) : ( + Off-chain draft + )} + + + ); + })} + + {!goals.length && !loading ? ( + + No savings goals yet + + Create your first savings goal below to track target funds on the Stellar network. + + + ) : null} + + + + Create New Goal + setForm((c) => ({ ...c, name: value }))} + /> + + + setForm((c) => ({ ...c, targetAmount: value }))} + /> + + {['XLM', 'USDC'].map((asset) => ( + setForm((c) => ({ ...c, asset }))} + style={[ + localStyles.assetChoice, + form.asset === asset && localStyles.assetChoiceActive, + ]}> + + {asset} + + + ))} + + + + setForm((c) => ({ ...c, targetDate: value }))} + /> + + {message ? {message} : null} + + + Save Goal Draft + + + + ); } + +const localStyles = StyleSheet.create({ + headerRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 8, + }, + refreshButton: { + paddingHorizontal: 8, + paddingVertical: 4, + borderRadius: 6, + backgroundColor: '#17243b', + }, + refreshText: { + color: '#55a6ff', + fontSize: 11, + fontWeight: '600', + }, + goalCard: { + paddingVertical: 12, + borderBottomWidth: 1, + borderBottomColor: '#17243b', + gap: 6, + }, + goalTitleWrap: { + gap: 4, + flex: 1, + }, + badgeRow: { + flexDirection: 'row', + gap: 6, + alignItems: 'center', + }, + statusBadge: { + backgroundColor: '#1b2a44', + borderRadius: 4, + paddingHorizontal: 6, + paddingVertical: 2, + }, + statusBadgeText: { + color: '#8bb9f8', + fontSize: 9, + fontWeight: '700', + }, + assetBadge: { + backgroundColor: '#16312a', + borderRadius: 4, + paddingHorizontal: 6, + paddingVertical: 2, + }, + assetBadgeText: { + color: '#34d399', + fontSize: 9, + fontWeight: '700', + }, + deleteButton: { + width: 28, + height: 28, + borderRadius: 14, + backgroundColor: '#261924', + alignItems: 'center', + justifyContent: 'center', + }, + deleteButtonText: { + color: '#ff6b81', + fontSize: 12, + fontWeight: '700', + }, + amountRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + fundedText: { + color: '#f4f7fb', + fontSize: 13, + fontWeight: '700', + }, + percentText: { + color: '#7d8ba6', + fontSize: 11, + fontWeight: '600', + }, + progressTrack: { + height: 6, + borderRadius: 3, + backgroundColor: '#17243b', + overflow: 'hidden', + }, + progressFill: { + height: '100%', + backgroundColor: '#55a6ff', + borderRadius: 3, + }, + metaRow: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + }, + contractText: { + color: '#a78bfa', + fontSize: 10, + fontWeight: '600', + }, + draftNote: { + color: '#65738c', + fontSize: 10, + fontStyle: 'italic', + }, + input: { + backgroundColor: '#081120', + color: '#f4f7fb', + borderRadius: 9, + padding: 12, + borderWidth: 1, + borderColor: '#17243b', + }, + formRow: { + flexDirection: 'row', + gap: 8, + alignItems: 'center', + }, + assetPicker: { + flexDirection: 'row', + backgroundColor: '#081120', + borderRadius: 9, + borderWidth: 1, + borderColor: '#17243b', + padding: 3, + gap: 4, + }, + assetChoice: { + paddingHorizontal: 12, + paddingVertical: 9, + borderRadius: 6, + }, + assetChoiceActive: { + backgroundColor: '#1c3458', + }, + assetChoiceText: { + color: '#65738c', + fontSize: 12, + fontWeight: '700', + }, + assetChoiceTextActive: { + color: '#55a6ff', + }, +}); diff --git a/src/lib/api.ts b/src/lib/api.ts index 9076890..f2cd889 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -33,6 +33,8 @@ export type ApiCategory = { color: string; }; +export type ApiSavingsGoalStatus = 'draft' | 'pending' | 'active' | 'completed' | 'withdrawn'; + export type ApiSavingsGoal = { id: string; name: string; @@ -40,9 +42,11 @@ export type ApiSavingsGoal = { fundedAmount: number; targetDate?: string; asset: string; - status: 'draft'; - transactionHash?: string; + status: ApiSavingsGoalStatus; + network?: string; + ownerAddress?: string; contractId?: string; + transactionHash?: string; }; export function getApiBaseUrl(): string { @@ -156,10 +160,25 @@ export async function fetchSavingsGoals(): Promise { return response.json() as Promise; } -export function createSavingsGoal(payload: Pick) { +export async function fetchSavingsGoal(id: string): Promise { + const url = `${getApiBaseUrl()}/savings-goals/${id}`; + const response = await fetch(url); + if (!response.ok) throw new Error(`Unable to load savings goal ${id} from ${url}`); + return response.json() as Promise; +} + +export function createSavingsGoal(payload: Partial> & Pick) { return postJson('/savings-goals', payload); } +export function updateSavingsGoal(id: string, payload: Partial>) { + return mutateJson(`/savings-goals/${id}`, 'PATCH', payload); +} + +export function deleteSavingsGoal(id: string) { + return mutateJson<{ deleted: boolean }>(`/savings-goals/${id}`, 'DELETE'); +} + export async function createTransaction(payload: Omit): Promise { const url = `${getApiBaseUrl()}/transactions`; const response = await fetch(url, { From 30af57c3a97d696f55e5ed18a8869066cb84c47d Mon Sep 17 00:00:00 2001 From: Peter Joshua Brion Date: Sun, 30 Aug 2026 18:41:07 +0800 Subject: [PATCH 2/5] fix(app): dynamic budget calculations, persistent custom fields, receipt workflow, and navigation alignment --- src/app/(tabs)/budgets.tsx | 105 ++++- src/app/custom-fields.tsx | 129 +++++- src/app/explore.tsx | 180 --------- src/app/receipt.tsx | 265 ++++++++---- src/app/reports.tsx | 422 ++++++++++++++++++-- src/components/dashboard/save-dashboard.tsx | 44 +- src/components/navigation/app-sidebar.tsx | 4 +- 7 files changed, 819 insertions(+), 330 deletions(-) delete mode 100644 src/app/explore.tsx diff --git a/src/app/(tabs)/budgets.tsx b/src/app/(tabs)/budgets.tsx index b965267..405095f 100644 --- a/src/app/(tabs)/budgets.tsx +++ b/src/app/(tabs)/budgets.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useMemo, useState } from 'react'; import { Pressable, Text, TextInput, View } from 'react-native'; import { FinancePage, financePageStyles as styles } from '@/components/layout/finance-page'; @@ -6,49 +6,124 @@ import { useFinanceStore } from '@/store/finance-store'; import { createBudget } from '@/lib/api'; import { saveBudgets } from '@/lib/sqlite'; -const peso = new Intl.NumberFormat('en-PH', { style: 'currency', currency: 'PHP', maximumFractionDigits: 0 }); +const peso = new Intl.NumberFormat('en-PH', { + style: 'currency', + currency: 'PHP', + maximumFractionDigits: 0, +}); export default function BudgetsScreen() { - const { budgets, setBudgets } = useFinanceStore(); + const { budgets, setBudgets, transactions } = useFinanceStore(); const [form, setForm] = useState({ category: '', limit: '' }); const [message, setMessage] = useState(null); + const currentMonthPrefix = useMemo(() => new Date().toISOString().slice(0, 7), []); + + const dynamicSpentMap = useMemo(() => { + const map = new Map(); + for (const t of transactions) { + if (t.type === 'expense' && t.date.startsWith(currentMonthPrefix)) { + map.set(t.category, (map.get(t.category) ?? 0) + t.amount); + } + } + return map; + }, [currentMonthPrefix, transactions]); + const addBudget = async () => { const limit = Number(form.limit); - if (!form.category.trim() || !Number.isFinite(limit) || limit <= 0) return setMessage('Enter a category and valid limit.'); + if (!form.category.trim() || !Number.isFinite(limit) || limit <= 0) { + return setMessage('Enter a category and valid limit.'); + } try { - const created = await createBudget({ userId: 'usr_2', category: form.category.trim(), limit, period: 'monthly' }); - const next = [...budgets, created]; setBudgets(next); saveBudgets(next); setForm({ category: '', limit: '' }); setMessage(null); - } catch { setMessage('The budgets API is unavailable.'); } + const created = await createBudget({ + userId: 'usr_2', + category: form.category.trim(), + limit, + period: 'monthly', + }); + const next = [...budgets, created]; + setBudgets(next); + saveBudgets(next); + setForm({ category: '', limit: '' }); + setMessage(null); + } catch { + setMessage('The budgets API is unavailable.'); + } }; return ( - + Budget progress {budgets.map((budget) => { - const percent = Math.min((budget.spent / Math.max(budget.limit, 1)) * 100, 100); + const used = dynamicSpentMap.has(budget.category) + ? (dynamicSpentMap.get(budget.category) ?? 0) + : budget.spent; + const percent = Math.min((used / Math.max(budget.limit, 1)) * 100, 100); + return ( {budget.category} {Math.round(percent)}% - {peso.format(budget.spent)} of {peso.format(budget.limit)} · {budget.period} - - + + {peso.format(used)} of {peso.format(budget.limit)} · {budget.period} + + + = 100 ? '#ff4f6d' : '#55a6ff', + }} + /> ); })} {!budgets.length ? No budgets have synced yet. : null} + Add monthly budget - setForm((value) => ({ ...value, category }))} /> - setForm((value) => ({ ...value, limit }))} /> + setForm((value) => ({ ...value, category }))} + /> + setForm((value) => ({ ...value, limit }))} + /> {message ? {message} : null} - Save budget + + Save budget + ); diff --git a/src/app/custom-fields.tsx b/src/app/custom-fields.tsx index a60ab32..b5679f5 100644 --- a/src/app/custom-fields.tsx +++ b/src/app/custom-fields.tsx @@ -1,8 +1,129 @@ -import { useState } from 'react'; -import { Pressable, Text, TextInput, View } from 'react-native'; +import { useEffect, useState } from 'react'; +import { Alert, Platform, Pressable, StyleSheet, Text, TextInput, View } from 'react-native'; import { FinancePage, financePageStyles as styles } from '@/components/layout/finance-page'; +const STORAGE_KEY = 'save_custom_fields_v1'; +const DEFAULT_FIELDS = ['Project', 'Client', 'Tax ID', 'Invoice #']; + +async function loadSavedFields(): Promise { + try { + if (Platform.OS === 'web') { + const raw = window.localStorage.getItem(STORAGE_KEY); + return raw ? JSON.parse(raw) : DEFAULT_FIELDS; + } + const { getItemAsync } = await import('expo-secure-store'); + const raw = await getItemAsync(STORAGE_KEY); + return raw ? JSON.parse(raw) : DEFAULT_FIELDS; + } catch { + return DEFAULT_FIELDS; + } +} + +async function saveFields(fields: string[]) { + try { + const raw = JSON.stringify(fields); + if (Platform.OS === 'web') { + window.localStorage.setItem(STORAGE_KEY, raw); + return; + } + const { setItemAsync } = await import('expo-secure-store'); + await setItemAsync(STORAGE_KEY, raw); + } catch { + // Ignore write errors + } +} + export default function CustomFieldsScreen() { - const [fields, setFields] = useState([]); const [name, setName] = useState(''); - return {fields.map((field) => {field})}{!fields.length ? No custom fields on this device yet. : null}Add local test field { if (name.trim() && !fields.includes(name.trim())) { setFields((value) => [...value, name.trim()]); setName(''); } }}>Add fieldThis page is locally testable; server persistence will be added with the durable data phase.; + const [fields, setFields] = useState([]); + const [name, setName] = useState(''); + + useEffect(() => { + void loadSavedFields().then(setFields); + }, []); + + const addField = (fieldName: string) => { + const trimmed = fieldName.trim(); + if (!trimmed || fields.includes(trimmed)) return; + const next = [...fields, trimmed]; + setFields(next); + void saveFields(next); + setName(''); + }; + + const removeField = (fieldName: string) => { + Alert.alert('Remove custom field?', `Remove "${fieldName}" from custom fields list?`, [ + { text: 'Cancel', style: 'cancel' }, + { + text: 'Remove', + style: 'destructive', + onPress: () => { + const next = fields.filter((f) => f !== fieldName); + setFields(next); + void saveFields(next); + }, + }, + ]); + }; + + return ( + + + Active Fields ({fields.length}) + {fields.map((field) => ( + + {field} + removeField(field)} + hitSlop={8} + style={localStyles.removeButton}> + + + + ))} + {!fields.length ? ( + No custom fields configured yet. + ) : null} + + + + Add Custom Field + + addField(name)}> + Add Custom Field + + + Custom fields appear as optional metadata inputs when creating expenses and income. + + + + ); } + +const localStyles = StyleSheet.create({ + removeButton: { + width: 28, + height: 28, + borderRadius: 14, + backgroundColor: '#261924', + alignItems: 'center', + justifyContent: 'center', + }, + removeButtonText: { + color: '#ff6b81', + fontSize: 12, + fontWeight: '700', + }, +}); diff --git a/src/app/explore.tsx b/src/app/explore.tsx deleted file mode 100644 index 2934085..0000000 --- a/src/app/explore.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import { Image } from 'expo-image'; -import { SymbolView } from 'expo-symbols'; -import { Platform, Pressable, ScrollView, StyleSheet } from 'react-native'; -import { useSafeAreaInsets } from 'react-native-safe-area-context'; - -import { ExternalLink } from '@/components/external-link'; -import { ThemedText } from '@/components/themed-text'; -import { ThemedView } from '@/components/themed-view'; -import { Collapsible } from '@/components/ui/collapsible'; -import { WebBadge } from '@/components/web-badge'; -import { BottomTabInset, MaxContentWidth, Spacing } from '@/constants/theme'; -import { useTheme } from '@/hooks/use-theme'; - -export default function TabTwoScreen() { - const safeAreaInsets = useSafeAreaInsets(); - const insets = { - ...safeAreaInsets, - bottom: safeAreaInsets.bottom + BottomTabInset + Spacing.three, - }; - const theme = useTheme(); - - const contentPlatformStyle = Platform.select({ - android: { - paddingTop: insets.top, - paddingLeft: insets.left, - paddingRight: insets.right, - paddingBottom: insets.bottom, - }, - web: { - paddingTop: Spacing.six, - paddingBottom: Spacing.four, - }, - }); - - return ( - - - - Explore - - This starter app includes example{'\n'}code to help you get started. - - - - pressed && styles.pressed}> - - Expo documentation - - - - - - - - - - This app has two screens: src/app/index.tsx and{' '} - src/app/explore.tsx - - - The layout file in src/app/_layout.tsx sets up - the tab navigator. - - - Learn more - - - - - - - You can open this project on Android, iOS, and the web. To open the web version, - press w in the terminal running this - project. - - - - - - - - For static images, you can use the @2x and{' '} - @3x suffixes to provide files for different - screen densities. - - - - Learn more - - - - - - This template has light and dark mode support. The{' '} - useColorScheme() hook lets you inspect what the - user's current color scheme is, and so you can adjust UI colors accordingly. - - - Learn more - - - - - - This template includes an example of an animated component. The{' '} - src/components/ui/collapsible.tsx component uses - the powerful react-native-reanimated library to - animate opening this hint. - - - - {Platform.OS === 'web' && } - - - ); -} - -const styles = StyleSheet.create({ - scrollView: { - flex: 1, - }, - contentContainer: { - flexDirection: 'row', - justifyContent: 'center', - }, - container: { - maxWidth: MaxContentWidth, - flexGrow: 1, - }, - titleContainer: { - gap: Spacing.three, - alignItems: 'center', - paddingHorizontal: Spacing.four, - paddingVertical: Spacing.six, - }, - centerText: { - textAlign: 'center', - }, - pressed: { - opacity: 0.7, - }, - linkButton: { - flexDirection: 'row', - paddingHorizontal: Spacing.four, - paddingVertical: Spacing.two, - borderRadius: Spacing.five, - justifyContent: 'center', - gap: Spacing.one, - alignItems: 'center', - }, - sectionsWrapper: { - gap: Spacing.five, - paddingHorizontal: Spacing.four, - paddingTop: Spacing.three, - }, - collapsibleContent: { - alignItems: 'center', - }, - imageTutorial: { - width: '100%', - aspectRatio: 296 / 171, - borderRadius: Spacing.three, - marginTop: Spacing.two, - }, - imageReact: { - width: 100, - height: 100, - alignSelf: 'center', - }, -}); diff --git a/src/app/receipt.tsx b/src/app/receipt.tsx index 7e99489..20dd27d 100644 --- a/src/app/receipt.tsx +++ b/src/app/receipt.tsx @@ -1,86 +1,149 @@ import { useRouter } from 'expo-router'; import { useState } from 'react'; -import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native'; +import { Pressable, ScrollView, StyleSheet, Text, TextInput, View } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { createTransaction, type ApiTransaction } from '@/lib/api'; import { saveTransactions } from '@/lib/sqlite'; +import { useExpenseDraftStore } from '@/store/expense-draft-store'; import { useFinanceStore } from '@/store/finance-store'; +const peso = new Intl.NumberFormat('en-PH', { + style: 'currency', + currency: 'PHP', + minimumFractionDigits: 2, + maximumFractionDigits: 2, +}); + export default function ReceiptScreen() { const router = useRouter(); - const { transactions, setTransactions } = useFinanceStore(); - const [status, setStatus] = useState('Ready to scan'); - - const demoReceipt = { - merchant: 'Fresh Mart', - category: 'Food & Dining', - amount: 142.85, - date: new Date().toISOString().slice(0, 10), - }; + const { transactions, setTransactions, categories } = useFinanceStore(); + const { draft, patchDraft, resetDraft } = useExpenseDraftStore(); + + const [merchant, setMerchant] = useState(draft.merchant || 'SM Supermarket'); + const [category, setCategory] = useState(draft.category || (categories[0]?.name ?? 'Groceries')); + const [amount, setAmount] = useState(draft.amount || '1428.50'); + const [date, setDate] = useState(draft.date || new Date().toISOString().slice(0, 10)); + const [status, setStatus] = useState('Scanned receipt values ready for review'); + const [saving, setSaving] = useState(false); const handleSaveReceipt = async () => { - const transaction: ApiTransaction = { - id: `txn_receipt_${Date.now()}`, + const numAmount = Number(amount); + if (!merchant.trim() || !Number.isFinite(numAmount) || numAmount <= 0) { + setStatus('Please ensure merchant and positive amount are provided.'); + return; + } + + setSaving(true); + const transactionPayload = { userId: 'usr_2', - type: 'expense', - amount: demoReceipt.amount, - category: demoReceipt.category, - description: `${demoReceipt.merchant} receipt`, - date: demoReceipt.date, - status: 'approved', + type: 'expense' as const, + amount: numAmount, + category, + description: `${merchant} receipt`, + merchant: merchant.trim(), + date, + status: 'approved' as const, + receiptUri: draft.receiptUri, }; try { - const created = await createTransaction({ - userId: transaction.userId, - type: transaction.type, - amount: transaction.amount, - category: transaction.category, - description: transaction.description, - date: transaction.date, - status: transaction.status, - }); + const created = await createTransaction(transactionPayload); const next = [created, ...transactions]; setTransactions(next); saveTransactions(next); - setStatus('Receipt processed and saved'); + resetDraft(); + router.replace('/expenses'); } catch { - const next = [transaction, ...transactions]; + const fallback: ApiTransaction = { + id: `txn_receipt_${Date.now()}`, + ...transactionPayload, + }; + const next = [fallback, ...transactions]; setTransactions(next); saveTransactions(next); - setStatus('Saved offline. Sync will retry later.'); + resetDraft(); + router.replace('/expenses'); + } finally { + setSaving(false); } + }; - router.back(); + const handleEditInFullForm = () => { + patchDraft({ + merchant, + category, + amount, + date, + description: `${merchant} receipt`, + type: 'expense', + }); + router.push('/expense-add'); }; return ( - Receipt scan - OCR review + Receipt Scanner + Review Scanned Details - Detected values + Detected Values + Merchant - {demoReceipt.merchant} + + Category - {demoReceipt.category} + + - Amount - ${demoReceipt.amount.toFixed(2)} + Amount (PHP) + + Date - {demoReceipt.date} + + + {draft.receiptUri ? ( + + + ✓ Image attached: {draft.receiptUri.split('/').pop()} + + + ) : null} @@ -88,12 +151,19 @@ export default function ReceiptScreen() { {status} - - Save receipt + + {saving ? 'Saving…' : 'Quick Save Receipt'} - router.back()} style={styles.secondaryButton}> - Back to dashboard + + Edit in Full Expense Form + + + router.back()} style={styles.linkButton}> + Cancel @@ -103,96 +173,117 @@ export default function ReceiptScreen() { const styles = StyleSheet.create({ safeArea: { flex: 1, - backgroundColor: '#0b1220', + backgroundColor: '#070d1a', }, container: { flexGrow: 1, - padding: 24, + padding: 20, + gap: 12, }, header: { - marginBottom: 20, + marginBottom: 8, }, eyebrow: { - color: '#7dd3fc', - fontSize: 12, + color: '#55a6ff', + fontSize: 11, textTransform: 'uppercase', - marginBottom: 8, + marginBottom: 4, letterSpacing: 1.2, + fontWeight: '700', }, title: { - color: '#f8fafc', - fontSize: 30, - fontWeight: '700', + color: '#f4f7fb', + fontSize: 26, + fontWeight: '800', }, card: { - backgroundColor: '#121d2e', - borderRadius: 22, + backgroundColor: '#0d1629', + borderRadius: 14, borderWidth: 1, - borderColor: '#1d2940', - padding: 18, + borderColor: '#17243b', + padding: 16, gap: 12, }, cardTitle: { - color: '#f8fafc', - fontSize: 18, + color: '#f4f7fb', + fontSize: 16, fontWeight: '700', - marginBottom: 8, + marginBottom: 4, }, row: { - flexDirection: 'row', - justifyContent: 'space-between', - alignItems: 'center', - borderBottomWidth: 1, - borderBottomColor: '#1d2940', - paddingBottom: 10, + gap: 4, }, label: { - color: '#8aa3bf', + color: '#7d8ba6', + fontSize: 12, + fontWeight: '600', + }, + input: { + backgroundColor: '#081120', + borderWidth: 1, + borderColor: '#17243b', + borderRadius: 8, + paddingHorizontal: 12, + paddingVertical: 10, + color: '#f4f7fb', fontSize: 14, }, - value: { - color: '#f8fafc', + attachmentRow: { + paddingTop: 6, + }, + attachmentText: { + color: '#19c983', + fontSize: 12, fontWeight: '600', }, notice: { - backgroundColor: '#0f172a', - borderRadius: 16, - padding: 16, - marginTop: 20, + backgroundColor: '#0d1629', + borderRadius: 10, + padding: 14, borderWidth: 1, - borderColor: '#1d2940', + borderColor: '#17243b', }, noticeTitle: { - color: '#93c5fd', + color: '#55a6ff', fontWeight: '700', - marginBottom: 6, + fontSize: 12, + marginBottom: 4, }, noticeText: { - color: '#e2e8f0', + color: '#7d8ba6', + fontSize: 12, }, primaryButton: { - marginTop: 24, - backgroundColor: '#8b5cf6', - borderRadius: 12, + backgroundColor: '#55a6ff', + borderRadius: 10, paddingVertical: 14, alignItems: 'center', + marginTop: 6, }, primaryButtonText: { - color: '#fff', - fontSize: 16, - fontWeight: '700', + color: '#07111f', + fontSize: 15, + fontWeight: '800', }, secondaryButton: { - marginTop: 12, borderWidth: 1, - borderColor: '#1d2940', - borderRadius: 12, + borderColor: '#263956', + backgroundColor: '#111c31', + borderRadius: 10, paddingVertical: 14, alignItems: 'center', }, secondaryButtonText: { - color: '#cbd5e1', - fontSize: 15, + color: '#f4f7fb', + fontSize: 14, fontWeight: '600', }, + linkButton: { + alignItems: 'center', + paddingVertical: 10, + }, + linkButtonText: { + color: '#7d8ba6', + fontSize: 14, + }, }); diff --git a/src/app/reports.tsx b/src/app/reports.tsx index a4baa0b..e7495bb 100644 --- a/src/app/reports.tsx +++ b/src/app/reports.tsx @@ -6,49 +6,403 @@ import type { ApiTransaction } from '@/lib/api'; import { useFinanceStore } from '@/store/finance-store'; type PeriodKey = 'month' | 'lastMonth' | 'threeMonths' | 'sixMonths' | 'year'; -const PERIODS: { key: PeriodKey; label: string }[] = [{ key: 'month', label: 'This month' }, { key: 'lastMonth', label: 'Last month' }, { key: 'threeMonths', label: 'Last 3 months' }, { key: 'sixMonths', label: 'Last 6 months' }, { key: 'year', label: 'Year to date' }]; -const money = (value: number) => `₱${value.toLocaleString('en-PH', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; +const PERIODS: { key: PeriodKey; label: string }[] = [ + { key: 'month', label: 'This month' }, + { key: 'lastMonth', label: 'Last month' }, + { key: 'threeMonths', label: 'Last 3 months' }, + { key: 'sixMonths', label: 'Last 6 months' }, + { key: 'year', label: 'Year to date' }, +]; + +const money = (value: number) => + `₱${value.toLocaleString('en-PH', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`; function rangeFor(key: PeriodKey) { - const now = new Date(); const end = new Date(now.getFullYear(), now.getMonth() + 1, 0); - if (key === 'lastMonth') return { start: new Date(now.getFullYear(), now.getMonth() - 1, 1), end: new Date(now.getFullYear(), now.getMonth(), 0) }; - if (key === 'threeMonths') return { start: new Date(now.getFullYear(), now.getMonth() - 2, 1), end }; - if (key === 'sixMonths') return { start: new Date(now.getFullYear(), now.getMonth() - 5, 1), end }; - if (key === 'year') return { start: new Date(now.getFullYear(), 0, 1), end }; - return { start: new Date(now.getFullYear(), now.getMonth(), 1), end }; -} -function inPeriod(item: ApiTransaction, key: PeriodKey) { const date = new Date(`${item.date}T00:00:00`); const range = rangeFor(key); return date >= range.start && date <= range.end; } + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + + if (key === 'lastMonth') { + const start = new Date(Date.UTC(year, month - 1, 1)).toISOString().slice(0, 10); + const end = new Date(Date.UTC(year, month, 0)).toISOString().slice(0, 10); + return { start, end }; + } + if (key === 'threeMonths') { + const start = new Date(Date.UTC(year, month - 2, 1)).toISOString().slice(0, 10); + const end = new Date(Date.UTC(year, month + 1, 0)).toISOString().slice(0, 10); + return { start, end }; + } + if (key === 'sixMonths') { + const start = new Date(Date.UTC(year, month - 5, 1)).toISOString().slice(0, 10); + const end = new Date(Date.UTC(year, month + 1, 0)).toISOString().slice(0, 10); + return { start, end }; + } + if (key === 'year') { + const start = new Date(Date.UTC(year, 0, 1)).toISOString().slice(0, 10); + const end = new Date(Date.UTC(year, month + 1, 0)).toISOString().slice(0, 10); + return { start, end }; + } + const start = new Date(Date.UTC(year, month, 1)).toISOString().slice(0, 10); + const end = new Date(Date.UTC(year, month + 1, 0)).toISOString().slice(0, 10); + return { start, end }; +} + +function inPeriod(item: ApiTransaction, key: PeriodKey) { + const { start, end } = rangeFor(key); + return item.date >= start && item.date <= end; +} + function stats(items: ApiTransaction[]) { - const expenses = items.filter((item) => item.type === 'expense'); const total = expenses.reduce((sum, item) => sum + item.amount, 0); - const categories = Object.entries(expenses.reduce>((all, item) => ({ ...all, [item.category]: (all[item.category] ?? 0) + item.amount }), {})).sort((a, b) => b[1] - a[1]); - const merchants = Object.entries(expenses.reduce>((all, item) => { const name = item.merchant?.trim() || item.description; const previous = all[name] ?? { count: 0, total: 0 }; return { ...all, [name]: { count: previous.count + 1, total: previous.total + item.amount } }; }, {})).sort((a, b) => b[1].total - a[1].total).slice(0, 5); - return { total, count: expenses.length, average: expenses.length ? total / expenses.length : 0, largest: Math.max(0, ...expenses.map((item) => item.amount)), categories, merchants }; + const expenses = items.filter((item) => item.type === 'expense'); + const total = expenses.reduce((sum, item) => sum + item.amount, 0); + const categories = Object.entries( + expenses.reduce>( + (all, item) => ({ ...all, [item.category]: (all[item.category] ?? 0) + item.amount }), + {}, + ), + ).sort((a, b) => b[1] - a[1]); + + const merchants = Object.entries( + expenses.reduce>((all, item) => { + const name = item.merchant?.trim() || item.description; + const previous = all[name] ?? { count: 0, total: 0 }; + return { ...all, [name]: { count: previous.count + 1, total: previous.total + item.amount } }; + }, {}), + ) + .sort((a, b) => b[1].total - a[1].total) + .slice(0, 5); + + return { + total, + count: expenses.length, + average: expenses.length ? total / expenses.length : 0, + largest: Math.max(0, ...expenses.map((item) => item.amount)), + categories, + merchants, + }; } export default function ReportsScreen() { const transactions = useFinanceStore((state) => state.transactions); - const [mode, setMode] = useState<'single' | 'compare'>('single'); const [periodA, setPeriodA] = useState('month'); const [periodB, setPeriodB] = useState('lastMonth'); - const a = useMemo(() => stats(transactions.filter((item) => inPeriod(item, periodA))), [periodA, transactions]); const b = useMemo(() => stats(transactions.filter((item) => inPeriod(item, periodB))), [periodB, transactions]); - const maxCategory = Math.max(1, ...a.categories.map((entry) => entry[1]), ...b.categories.map((entry) => entry[1])); + const [mode, setMode] = useState<'single' | 'compare'>('single'); + const [periodA, setPeriodA] = useState('month'); + const [periodB, setPeriodB] = useState('lastMonth'); + + const a = useMemo( + () => stats(transactions.filter((item) => inPeriod(item, periodA))), + [periodA, transactions], + ); + const b = useMemo( + () => stats(transactions.filter((item) => inPeriod(item, periodB))), + [periodB, transactions], + ); + + const maxCategory = Math.max( + 1, + ...a.categories.map((entry) => entry[1]), + ...b.categories.map((entry) => entry[1]), + ); + const exportCsv = async () => { - const escape = (value: unknown) => `"${String(value ?? '').replaceAll('"', '""')}"`; const csv = ['date,type,amount,category,description,merchant,tags', ...transactions.map((item) => [item.date, item.type, item.amount, item.category, item.description, item.merchant, item.tags?.join('|')].map(escape).join(','))].join('\n'); - try { await Share.share({ title: `SAVE report ${new Date().toISOString().slice(0, 10)}`, message: csv }); } catch { Alert.alert('Export failed', 'The CSV could not be shared on this device.'); } + const escape = (value: unknown) => `"${String(value ?? '').replaceAll('"', '""')}"`; + const csv = [ + 'date,type,amount,category,description,merchant,tags', + ...transactions.map((item) => + [ + item.date, + item.type, + item.amount, + item.category, + item.description, + item.merchant, + item.tags?.join('|'), + ] + .map(escape) + .join(','), + ), + ].join('\n'); + + try { + await Share.share({ + title: `SAVE report ${new Date().toISOString().slice(0, 10)}`, + message: csv, + }); + } catch { + Alert.alert('Export failed', 'The CSV could not be shared on this device.'); + } }; - return - setMode('single')}>Single setMode('compare')}>Compare⇩ Export CSV - {mode === 'single' ? : PERIOD APERIOD B} - {mode === 'compare' ? : null} - {mode === 'single' ? `Spending by Category — ${PERIODS.find((item) => item.key === periodA)?.label}` : 'Category Breakdown'}{Array.from(new Set([...a.categories.map(([name]) => name), ...(mode === 'compare' ? b.categories.map(([name]) => name) : [])])).map((name) => { const av = a.categories.find(([key]) => key === name)?.[1] ?? 0; const bv = b.categories.find(([key]) => key === name)?.[1] ?? 0; return {name}{mode === 'compare' ? : null}})}{!a.categories.length && (mode === 'single' || !b.categories.length) ? No expenses in the selected period. : null}{mode === 'compare' ? ■ Period A■ Period B : null} - {mode === 'single' ? <>SummaryTop Merchants{a.merchants.map(([name, value]) => {name}{value.count}×{money(value.total)})}{!a.merchants.length ? No merchant data in this period. : null} : null} - ; -} -function SinglePeriod({ value, onChange }: { value: PeriodKey; onChange: (value: PeriodKey) => void }) { return PERIOD; } -function PeriodButtons({ value, onChange }: { value: PeriodKey; onChange: (value: PeriodKey) => void }) { return {PERIODS.map((period) => onChange(period.key)}>{period.label})}; } -function Metric({ label, value }: { label: string; value: string }) { return {label}{value}; } -function CompareSummary({ a, b }: { a: ReturnType; b: ReturnType }) { const rows: [string, number, number, (n: number) => string][] = [['Total Spent', a.total, b.total, money], ['Transactions', a.count, b.count, String], ['Avg / Transaction', a.average, b.average, money], ['Largest Expense', a.largest, b.largest, money]]; return Summary ComparisonMetricPeriod APeriod BChange{rows.map(([label, av, bv, format]) => { const delta = bv ? (av - bv) / bv : av ? 1 : 0; return {label}{format(av)}{format(bv)} 0 ? styles.negative : styles.positive]}>{delta > 0 ? '↑' : '↓'} {Math.abs(delta * 100).toFixed(1)}%; })}; } + + return ( + + + + setMode('single')}> + Single + + setMode('compare')}> + Compare + + + + ⇩ Export CSV + + + + {mode === 'single' ? ( + + ) : ( + + PERIOD A + + + PERIOD B + + + )} + + {mode === 'compare' ? : null} + + + + {mode === 'single' + ? `Spending by Category — ${PERIODS.find((item) => item.key === periodA)?.label}` + : 'Category Breakdown'} + + {Array.from( + new Set([ + ...a.categories.map(([name]) => name), + ...(mode === 'compare' ? b.categories.map(([name]) => name) : []), + ]), + ).map((name) => { + const av = a.categories.find(([key]) => key === name)?.[1] ?? 0; + const bv = b.categories.find(([key]) => key === name)?.[1] ?? 0; + return ( + + + {name} + + + + {mode === 'compare' ? ( + + ) : null} + + + ); + })} + {!a.categories.length && (mode === 'single' || !b.categories.length) ? ( + No expenses in the selected period. + ) : null} + {mode === 'compare' ? ( + + ■ Period A + ■ Period B + + ) : null} + + + {mode === 'single' ? ( + <> + + Summary + + + + + + + Top Merchants + {a.merchants.map(([name, value]) => ( + + + {name} + + {value.count}× + {money(value.total)} + + ))} + {!a.merchants.length ? ( + No merchant data in this period. + ) : null} + + + ) : null} + + ); +} + +function SinglePeriod({ + value, + onChange, +}: { + value: PeriodKey; + onChange: (value: PeriodKey) => void; +}) { + return ( + + PERIOD + + + ); +} + +function PeriodButtons({ + value, + onChange, +}: { + value: PeriodKey; + onChange: (value: PeriodKey) => void; +}) { + return ( + + {PERIODS.map((period) => ( + onChange(period.key)}> + {period.label} + + ))} + + ); +} + +function Metric({ label, value }: { label: string; value: string }) { + return ( + + {label} + {value} + + ); +} + +function CompareSummary({ + a, + b, +}: { + a: ReturnType; + b: ReturnType; +}) { + const rows: [string, number, number, (n: number) => string][] = [ + ['Total Spent', a.total, b.total, money], + ['Transactions', a.count, b.count, String], + ['Avg / Transaction', a.average, b.average, money], + ['Largest Expense', a.largest, b.largest, money], + ]; + + return ( + + Summary Comparison + + Metric + Period A + Period B + Change + + {rows.map(([label, av, bv, format]) => { + const delta = bv ? (av - bv) / bv : av ? 1 : 0; + return ( + + {label} + {format(av)} + {format(bv)} + 0 ? styles.negative : styles.positive]}> + {delta > 0 ? '↑' : '↓'} {Math.abs(delta * 100).toFixed(1)}% + + + ); + })} + + ); +} const styles = StyleSheet.create({ - toolbar: { flexDirection: 'row', gap: 9 }, segment: { flex: 1, flexDirection: 'row', borderWidth: 1, borderColor: '#1e2b43', borderRadius: 9, overflow: 'hidden' }, tab: { flex: 1, alignItems: 'center', paddingVertical: 12 }, tabActive: { backgroundColor: '#5ca9ff' }, tabText: { color: '#e6edf7', fontWeight: '700' }, export: { borderWidth: 1, borderColor: '#263650', borderRadius: 9, paddingHorizontal: 15, justifyContent: 'center' }, exportText: { color: '#e6edf7', fontWeight: '700' }, card: { backgroundColor: '#0d1629', borderWidth: 1, borderColor: '#1c2941', borderRadius: 12, padding: 15, gap: 12 }, cardTitle: { color: '#f3f6fb', fontWeight: '800', fontSize: 14 }, periodLabel: { color: '#8e9bb0', fontSize: 11, fontWeight: '800' }, periods: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 }, pill: { borderWidth: 1, borderColor: '#26344d', borderRadius: 18, paddingHorizontal: 14, paddingVertical: 8 }, pillActive: { backgroundColor: '#5ca9ff', borderColor: '#5ca9ff' }, pillText: { color: '#e7edf7', fontSize: 11, fontWeight: '700' }, divider: { height: 1, backgroundColor: '#223049', marginVertical: 7 }, - metric: { flexDirection: 'row', alignItems: 'center', minHeight: 34 }, metricLabel: { color: '#a1aec2', flex: 1 }, metricValue: { color: '#f2f6fb', fontWeight: '800' }, count: { color: '#8996aa', marginRight: 10 }, barRow: { flexDirection: 'row', alignItems: 'center', minHeight: 50 }, barLabel: { width: 112, textAlign: 'right', paddingRight: 12, color: '#dce4ef', fontSize: 11 }, barArea: { flex: 1, gap: 4 }, bar: { height: 15, borderRadius: 4, backgroundColor: '#559be8' }, barB: { backgroundColor: '#dc9410' }, legend: { flexDirection: 'row', justifyContent: 'center', gap: 16 }, legendA: { color: '#5ca9ff', fontSize: 11 }, legendB: { color: '#e9a113', fontSize: 11 }, empty: { color: '#7d8ba6', textAlign: 'center', padding: 15 }, - compareHead: { flexDirection: 'row', borderBottomWidth: 1, borderBottomColor: '#243149', paddingVertical: 9 }, compareRow: { flexDirection: 'row', alignItems: 'center', borderBottomWidth: 1, borderBottomColor: '#19263d', paddingVertical: 12 }, compareMetric: { flex: 1.4, color: '#9aa7bc', fontSize: 10 }, compareA: { flex: 1, textAlign: 'right', color: '#69afff', fontSize: 10, fontWeight: '700' }, compareB: { flex: 1, textAlign: 'right', color: '#e7a522', fontSize: 10 }, change: { flex: 0.9, textAlign: 'right', color: '#8c99ad', fontSize: 9 }, positive: { color: '#28ca83' }, negative: { color: '#f05c70' }, + toolbar: { flexDirection: 'row', gap: 9 }, + segment: { + flex: 1, + flexDirection: 'row', + borderWidth: 1, + borderColor: '#1e2b43', + borderRadius: 9, + overflow: 'hidden', + }, + tab: { flex: 1, alignItems: 'center', paddingVertical: 12 }, + tabActive: { backgroundColor: '#5ca9ff' }, + tabText: { color: '#e6edf7', fontWeight: '700' }, + export: { + borderWidth: 1, + borderColor: '#263650', + borderRadius: 9, + paddingHorizontal: 15, + justifyContent: 'center', + }, + exportText: { color: '#e6edf7', fontWeight: '700' }, + card: { + backgroundColor: '#0d1629', + borderWidth: 1, + borderColor: '#1c2941', + borderRadius: 12, + padding: 15, + gap: 12, + }, + cardTitle: { color: '#f3f6fb', fontWeight: '800', fontSize: 14 }, + periodLabel: { color: '#8e9bb0', fontSize: 11, fontWeight: '800' }, + periods: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 }, + pill: { + borderWidth: 1, + borderColor: '#26344d', + borderRadius: 18, + paddingHorizontal: 14, + paddingVertical: 8, + }, + pillActive: { backgroundColor: '#5ca9ff', borderColor: '#5ca9ff' }, + pillText: { color: '#e7edf7', fontSize: 11, fontWeight: '700' }, + divider: { height: 1, backgroundColor: '#223049', marginVertical: 7 }, + metric: { flexDirection: 'row', alignItems: 'center', minHeight: 34 }, + metricLabel: { color: '#a1aec2', flex: 1 }, + metricValue: { color: '#f2f6fb', fontWeight: '800' }, + count: { color: '#8996aa', marginRight: 10 }, + barRow: { flexDirection: 'row', alignItems: 'center', minHeight: 50 }, + barLabel: { width: 112, textAlign: 'right', paddingRight: 12, color: '#dce4ef', fontSize: 11 }, + barArea: { flex: 1, gap: 4 }, + bar: { height: 15, borderRadius: 4, backgroundColor: '#559be8' }, + barB: { backgroundColor: '#dc9410' }, + legend: { flexDirection: 'row', justifyContent: 'center', gap: 16 }, + legendA: { color: '#5ca9ff', fontSize: 11 }, + legendB: { color: '#e9a113', fontSize: 11 }, + empty: { color: '#7d8ba6', textAlign: 'center', padding: 15 }, + compareHead: { + flexDirection: 'row', + borderBottomWidth: 1, + borderBottomColor: '#243149', + paddingVertical: 9, + }, + compareRow: { + flexDirection: 'row', + alignItems: 'center', + borderBottomWidth: 1, + borderBottomColor: '#19263d', + paddingVertical: 12, + }, + compareMetric: { flex: 1.4, color: '#9aa7bc', fontSize: 10 }, + compareA: { flex: 1, textAlign: 'right', color: '#69afff', fontSize: 10, fontWeight: '700' }, + compareB: { flex: 1, textAlign: 'right', color: '#e7a522', fontSize: 10 }, + change: { flex: 0.9, textAlign: 'right', color: '#8c99ad', fontSize: 9 }, + positive: { color: '#28ca83' }, + negative: { color: '#f05c70' }, }); diff --git a/src/components/dashboard/save-dashboard.tsx b/src/components/dashboard/save-dashboard.tsx index 3ecb676..1ff65a8 100644 --- a/src/components/dashboard/save-dashboard.tsx +++ b/src/components/dashboard/save-dashboard.tsx @@ -101,6 +101,7 @@ export function SaveDashboard({ budgets, transactions, totals, loading, syncMess const isWide = width >= 760; const month = useMemo(() => getDashboardMonth(transactions), [transactions]); const monthLabel = month.toLocaleDateString('en-US', { month: 'long', year: 'numeric' }); + const currentMonthStr = month.toISOString().slice(0, 7); const expenses = useMemo( () => transactions.filter((transaction) => transaction.type === 'expense'), @@ -110,27 +111,50 @@ export function SaveDashboard({ budgets, transactions, totals, loading, syncMess const spendingByCategory = useMemo(() => { const values = new Map(); for (const transaction of expenses) { - values.set(transaction.category, (values.get(transaction.category) ?? 0) + transaction.amount); + if (transaction.date.startsWith(currentMonthStr)) { + values.set(transaction.category, (values.get(transaction.category) ?? 0) + transaction.amount); + } } return [...values.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5); - }, [expenses]); + }, [currentMonthStr, expenses]); + + const categorySpentMap = useMemo(() => { + const map = new Map(); + for (const transaction of expenses) { + if (transaction.date.startsWith(currentMonthStr)) { + map.set(transaction.category, (map.get(transaction.category) ?? 0) + transaction.amount); + } + } + return map; + }, [currentMonthStr, expenses]); const dailySpending = useMemo(() => { const values = new Map(); for (const transaction of expenses) { - values.set(transaction.date, (values.get(transaction.date) ?? 0) + transaction.amount); + if (transaction.date.startsWith(currentMonthStr)) { + values.set(transaction.date, (values.get(transaction.date) ?? 0) + transaction.amount); + } } return [...values.entries()].sort(([a], [b]) => a.localeCompare(b)).slice(-7); - }, [expenses]); + }, [currentMonthStr, expenses]); const topMerchants = useMemo( - () => [...expenses].sort((a, b) => b.amount - a.amount).slice(0, 5), - [expenses], + () => + [...expenses] + .filter((t) => t.date.startsWith(currentMonthStr)) + .sort((a, b) => b.amount - a.amount) + .slice(0, 5), + [currentMonthStr, expenses], ); const spentDates = useMemo( - () => new Set(expenses.map((transaction) => Number(transaction.date.slice(-2)))), - [expenses], + () => + new Set( + expenses + .filter((t) => t.date.startsWith(currentMonthStr)) + .map((transaction) => Number(transaction.date.slice(-2))), + ), + [currentMonthStr, expenses], ); const daysInMonth = new Date(month.getFullYear(), month.getMonth() + 1, 0).getDate(); @@ -270,7 +294,9 @@ export function SaveDashboard({ budgets, transactions, totals, loading, syncMess {budgets.map((budget, index) => { - const used = budget.spent; + const used = categorySpentMap.has(budget.category) + ? (categorySpentMap.get(budget.category) ?? 0) + : budget.spent; const percent = Math.min((used / budget.limit) * 100, 100); const color = categoryColors[index % categoryColors.length]; return ( diff --git a/src/components/navigation/app-sidebar.tsx b/src/components/navigation/app-sidebar.tsx index 44cfa3b..9b28058 100644 --- a/src/components/navigation/app-sidebar.tsx +++ b/src/components/navigation/app-sidebar.tsx @@ -9,6 +9,8 @@ type AppSidebarProps = { const menuItems: Array<{ label: string; href: Href; icon: string }> = [ { label: 'Dashboard', href: '/', icon: '⌘' }, { label: 'Expenses', href: '/expenses', icon: '▧' }, + { label: 'Budgets', href: '/budgets', icon: '◔' }, + { label: 'Savings', href: '/savings', icon: '◈' }, { label: 'Categories', href: '/categories', icon: '◇' }, { label: 'Custom Fields', href: '/custom-fields', icon: '☷' }, { label: 'Reports', href: '/reports', icon: '↗' }, @@ -33,7 +35,7 @@ export function AppSidebar({ visible, onClose }: AppSidebarProps) { - Expense Tracker + SAVE Finance × From 8264a7aac41bf80376240cb890d5f406b372bdac Mon Sep 17 00:00:00 2001 From: Peter Joshua Brion Date: Mon, 31 Aug 2026 08:58:49 +0800 Subject: [PATCH 3/5] Implement Stellar savings and wallet integration --- .env.example | 9 + .github/workflows/soroban-contract.yml | 30 + .gitignore | 4 + README.md | 51 +- STELLAR_SOROBAN_INTEGRATIONS.md | 292 - backend/.env.example | 15 + backend/nest-cli.json | 8 + backend/package-lock.json | 305 +- backend/package.json | 3 +- backend/src/app.module.ts | 2 + backend/src/stellar/stellar.controller.ts | 57 + backend/src/stellar/stellar.dto.ts | 109 + backend/src/stellar/stellar.module.ts | 18 + backend/src/stellar/stellar.schema.ts | 41 + backend/src/stellar/stellar.sep7.ts | 67 + backend/src/stellar/stellar.service.ts | 459 + backend/test/stellar.sep7.test.cjs | 73 + backend/tsconfig.build.json | 7 + contract/.gitignore | 1 + contract/Cargo.lock | 2121 ++++ contract/Cargo.toml | 21 + contract/rust-toolchain.toml | 4 + contract/savings-vault/Cargo.toml | 15 + contract/savings-vault/src/lib.rs | 325 + contract/savings-vault/src/test.rs | 133 + .../test/cancellation_refunds_balance.1.json | 705 ++ ...transfers_tokens_and_reaches_target.1.json | 616 ++ .../test/create_and_list_goal.1.json | 500 + ...can_complete_and_owner_can_withdraw.1.json | 712 ++ .../new_owner_has_an_empty_goal_list.1.json | 319 + .../rejects_invalid_lifecycle_actions.1.json | 537 ++ ...COMBINED_SOROBAN_STELLAR_IMPLEMENTATION.md | 335 + docs/CONTRACT.md | 79 + docs/DELIVERABLES_1_2_TEST_REPORT.md | 75 + docs/STELLAR_ARCHITECTURE.md | 47 + eslint.config.js | 7 + metro.config.js | 11 + package-lock.json | 8493 ++++++++++++++--- package.json | 14 +- src/app/(tabs)/more.tsx | 2 +- src/app/(tabs)/savings.tsx | 127 +- src/app/receipt.tsx | 7 - src/app/stellar.tsx | 353 + src/components/navigation/app-sidebar.tsx | 2 +- src/hooks/use-color-scheme.web.ts | 10 +- src/lib/api.ts | 160 +- src/lib/wallet-connect.native.ts | 161 + src/lib/wallet-connect.ts | 37 + src/lib/wallet-connect.web.ts | 33 + 49 files changed, 15677 insertions(+), 1835 deletions(-) create mode 100644 .env.example create mode 100644 .github/workflows/soroban-contract.yml delete mode 100644 STELLAR_SOROBAN_INTEGRATIONS.md create mode 100644 backend/nest-cli.json create mode 100644 backend/src/stellar/stellar.controller.ts create mode 100644 backend/src/stellar/stellar.dto.ts create mode 100644 backend/src/stellar/stellar.module.ts create mode 100644 backend/src/stellar/stellar.schema.ts create mode 100644 backend/src/stellar/stellar.sep7.ts create mode 100644 backend/src/stellar/stellar.service.ts create mode 100644 backend/test/stellar.sep7.test.cjs create mode 100644 backend/tsconfig.build.json create mode 100644 contract/.gitignore create mode 100644 contract/Cargo.lock create mode 100644 contract/Cargo.toml create mode 100644 contract/rust-toolchain.toml create mode 100644 contract/savings-vault/Cargo.toml create mode 100644 contract/savings-vault/src/lib.rs create mode 100644 contract/savings-vault/src/test.rs create mode 100644 contract/savings-vault/test_snapshots/test/cancellation_refunds_balance.1.json create mode 100644 contract/savings-vault/test_snapshots/test/contribution_transfers_tokens_and_reaches_target.1.json create mode 100644 contract/savings-vault/test_snapshots/test/create_and_list_goal.1.json create mode 100644 contract/savings-vault/test_snapshots/test/deadline_can_complete_and_owner_can_withdraw.1.json create mode 100644 contract/savings-vault/test_snapshots/test/new_owner_has_an_empty_goal_list.1.json create mode 100644 contract/savings-vault/test_snapshots/test/rejects_invalid_lifecycle_actions.1.json create mode 100644 docs/COMBINED_SOROBAN_STELLAR_IMPLEMENTATION.md create mode 100644 docs/CONTRACT.md create mode 100644 docs/DELIVERABLES_1_2_TEST_REPORT.md create mode 100644 docs/STELLAR_ARCHITECTURE.md create mode 100644 eslint.config.js create mode 100644 metro.config.js create mode 100644 src/app/stellar.tsx create mode 100644 src/lib/wallet-connect.native.ts create mode 100644 src/lib/wallet-connect.ts create mode 100644 src/lib/wallet-connect.web.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..11f7510 --- /dev/null +++ b/.env.example @@ -0,0 +1,9 @@ +# Backend URL reachable by the phone, for example http://192.168.1.25:3000. +EXPO_PUBLIC_API_URL= + +# Public WalletConnect application identifier. Create one at https://dashboard.walletconnect.com/. +EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID= + +# Optional public HTTPS page that identifies SAVE Finance in Freighter. +# Until one is provided, the app uses https://github.com/FWDP/save-project. +EXPO_PUBLIC_WALLETCONNECT_METADATA_URL= diff --git a/.github/workflows/soroban-contract.yml b/.github/workflows/soroban-contract.yml new file mode 100644 index 0000000..cae6993 --- /dev/null +++ b/.github/workflows/soroban-contract.yml @@ -0,0 +1,30 @@ +name: Soroban contract + +on: + pull_request: + paths: ['contract/**', '.github/workflows/soroban-contract.yml'] + push: + branches: [main] + paths: ['contract/**', '.github/workflows/soroban-contract.yml'] + +jobs: + contract: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + targets: wasm32v1-none + components: rustfmt, clippy + - uses: Swatinem/rust-cache@v2 + with: + workspaces: contract + - name: Format + run: cargo fmt --manifest-path contract/Cargo.toml --all -- --check + - name: Unit tests + run: cargo test --manifest-path contract/Cargo.toml --locked + - name: Clippy + run: cargo clippy --manifest-path contract/Cargo.toml --all-targets --locked -- -D warnings + - name: Build Wasm + run: cargo build --manifest-path contract/Cargo.toml --package save-savings-vault --target wasm32v1-none --release --locked + diff --git a/.gitignore b/.gitignore index 221e1f1..0b69b2a 100644 --- a/.gitignore +++ b/.gitignore @@ -33,10 +33,14 @@ yarn-error.* # local env files .env*.local *.env +/backend/.stellar_integrity_signer_secret # typescript *.tsbuildinfo +# Rust / Soroban +/contract/target/ + example # generated native folders diff --git a/README.md b/README.md index d596770..a622610 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ This project includes: ## Environment files - Copy `backend/.env.example` to `backend/.env` and update values as needed. -- The Expo app can use environment variables as needed later for secure config. +- Copy `.env.example` to `.env` for the Expo app. WalletConnect values prefixed + with `EXPO_PUBLIC_` are public app configuration, not wallet secrets. - The admin app can use its own local `.env.local` file for API URLs and secrets. ## Stack summary @@ -70,3 +71,51 @@ This project includes: - Backend: NestJS + MongoDB + Redis + BullMQ - Object storage: MinIO / S3-compatible storage - Web/admin: Next.js dashboard for operations and analytics + +## Stellar Testnet and Soroban + +SAVE uses a non-custodial architecture: the mobile app links a public Testnet address, the backend reads Horizon/RPC data and prepares unsigned XDR, and a compatible external wallet approves signatures. Secret seeds are never accepted by the API. + +- Mobile route: `/stellar` +- Backend endpoints: `/stellar/network`, `/stellar/accounts`, `/stellar/payments`, `/stellar/vault`, `/stellar/transactions` +- Contract source: `contract/savings-vault` +- Contract specification and deployment: `docs/CONTRACT.md` + +Run `npm run contract:test` and `npm run contract:build` before deployment. Actual Testnet deployment requires an operator-owned funded Stellar CLI identity and setting `STELLAR_VAULT_CONTRACT_ID` in `backend/.env`. + +### Freighter Mobile signing + +The app uses WalletConnect v2 to request `stellar_signXDR` approval from +Freighter Mobile. SEP-7 and copied unsigned XDR remain available as manual +fallbacks. + +1. Create a dApp project at the [WalletConnect dashboard](https://dashboard.walletconnect.com/). +2. Copy `.env.example` to `.env` and set: + + ```dotenv + EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID=your_public_project_id + # Optional until SAVE has a public website: + EXPO_PUBLIC_WALLETCONNECT_METADATA_URL= + ``` + + When omitted, the app uses the SAVE GitHub repository as temporary metadata. + For production, set this to a public HTTPS page identifying the app and add + the same origin to the WalletConnect project allowlist when enabled. + +3. Install Freighter Mobile, import or create a dedicated **Testnet-only** + account, and switch Freighter to Testnet. Never enter its secret seed in + SAVE or the backend. +4. Fully restart Metro after changing `.env`: + + ```bash + npx expo start -c + ``` + +5. Open **More → Stellar Testnet → Connect Freighter Mobile**. Approve the + WalletConnect session, create a savings goal, then fund it. Freighter shows + the XDR approval; SAVE submits the signed XDR and displays the ledger + confirmation and updated goal balance. + +For native testing, use an Expo development build (`npm run android` or an EAS +development build). Keep the backend reachable from the phone and point the +app's API URL at the computer's LAN address rather than `localhost`. diff --git a/STELLAR_SOROBAN_INTEGRATIONS.md b/STELLAR_SOROBAN_INTEGRATIONS.md deleted file mode 100644 index 9b6e35a..0000000 --- a/STELLAR_SOROBAN_INTEGRATIONS.md +++ /dev/null @@ -1,292 +0,0 @@ -# Stellar and Soroban Integration Options for SAVE - -Assessment date: 2026-08-27 - -## Purpose and scope - -This document catalogs the meaningful Stellar and Soroban integrations that fit the current SAVE project. It is a product and technical options map, not a claim that every option should be built. - -The current repository contains: - -- an Expo 57 / React Native client for Android, iOS, and web; -- a NestJS API; -- a Next.js admin application; -- transaction, category, and budget features; -- offline SQLite caching and Zustand state; -- SecureStore, local authentication, linking, and web-browser capabilities; and -- planned MongoDB, Redis/BullMQ, and object storage infrastructure. - -This is a strong base for a non-custodial savings and payments application. The recommended first product is a Stellar account/wallet plus stablecoin payments, followed by a Soroban savings-vault contract. Running an issuer, exchange, lending product, or custodial wallet is possible but changes the legal, operational, and security scope substantially. - -## Recommended product direction - -| Priority | Integration | Why it fits SAVE | -| --- | --- | --- | -| P0 | Read-only Stellar portfolio and transaction import | Adds real financial data without custody or signing risk. | -| P0 | Connect or create a non-custodial account | Establishes the user's on-chain identity and balance source. | -| P0 | Send/receive XLM and selected stablecoins | Maps directly to the existing income/expense and receipt flows. | -| P0 | Sponsored account reserves and fee-bump transactions | Removes most XLM onboarding friction. | -| P1 | Anchor deposit/withdrawal and KYC flows | Lets users move between fiat and Stellar assets. | -| P1 | Soroban goal vault | Turns the current budgets/savings concept into enforceable on-chain savings rules. | -| P1 | RPC event ingestion and reconciliation | Keeps mobile, backend, and admin views consistent with final ledger state. | -| P2 | Cross-asset path payments and quotes | Allows “pay in one asset, receive another.” | -| P2 | Shared savings, allowances, and recovery policies | Adds differentiated programmable-finance features. | -| P3 | Rewards asset, DeFi, remittance operator, or custody | Valuable only after product demand and regulatory review are established. | - -## Integration catalog - -### 1. Accounts, wallets, and signing - -| Option | User experience | SAVE implementation | Notes | -| --- | --- | --- | --- | -| Watch-only account | Paste/scan a `G...` or `C...` address and view balances/activity. | Client validates the address; backend indexes it through Stellar RPC. | Safest first integration; no signing or custody. | -| External wallet connection | User approves each transaction in a compatible wallet. | Build unsigned XDR or a SEP-7 request, deep-link to the wallet, then reconcile the submitted hash. | Best default when mobile wallet compatibility meets requirements. No secret key enters SAVE. | -| App-managed non-custodial classic account | SAVE generates/imports an Ed25519 account and signs locally. | Encrypt the secret locally, gate signing with device authentication, and never send the secret to NestJS. | Requires backup/recovery, threat modeling, device-change flows, and a security audit. SecureStore alone is not a recovery strategy. | -| Soroban smart wallet / contract account | Seedless passkey-style signing with programmable controls. | A Rust contract implements `__check_auth`; the app supplies passkey/device signatures and a relayer can submit transactions. | Strong future fit for spend limits, allowlists, recovery, session keys, and multi-factor policies. Passkey tooling must be proven on native Expo builds, not assumed from browser examples. | -| Classic multisig account | Multiple people/devices approve sensitive actions. | Configure account signers, weights, and thresholds; collect signatures before submission. | Useful for joint savings, treasury, issuer, sponsor, and admin accounts. | -| Custodial/omnibus wallet | SAVE controls funds and exposes internal user balances. | HSM/KMS signing, pooled account with muxed IDs or memos, withdrawals, reconciliation, risk controls, and compliance operations. | Not recommended for the first release. This is a materially different regulated and security-sensitive business. | -| Account recovery | User recovers after losing a key/device. | SEP-30 recovery servers for classic accounts, or contract-account recovery policies. | Design before allowing material balances; never treat email login alone as sufficient authorization to move funds. | - -Relevant standards and guides: [wallet overview](https://developers.stellar.org/docs/build/apps/overview), [Wallet SDK](https://developers.stellar.org/docs/build/apps/wallet), [smart wallets](https://developers.stellar.org/docs/build/guides/contract-accounts/smart-wallets), [multisig](https://developers.stellar.org/docs/learn/fundamentals/transactions/signatures-multisig), and [active SEPs, including SEP-30](https://developers.stellar.org/docs/learn/fundamentals/stellar-ecosystem-proposals). - -### 2. Network data and portfolio features - -SAVE can add: - -- XLM, issued-asset, and contract-token balances; -- trustlines and authorization status; -- pending, successful, and failed on-chain transactions; -- payment, transfer, mint, burn, clawback, and contract events; -- claimable balances; -- active offers and liquidity-pool positions; -- account signers, thresholds, sponsorships, and reserve requirements; -- Soroban contract state and savings-vault positions; -- transaction explorer links and human-readable operation details; and -- cost-basis or fiat-value reporting when paired with a separate trusted price source. - -Use Stellar RPC for live state, contract simulation/submission, recent transactions, and filtered events. RPC's recent transaction retention is limited, so the backend should persist normalized events and cursors. Use Hubble or Galexie for historical analytics rather than treating a public endpoint as the permanent accounting database. Horizon should be limited to integrations that still require its parsed resources, because Stellar marks it as nearing end-of-life. See the official [API comparison](https://developers.stellar.org/docs/data/apis) and [unified payment-event guide](https://developers.stellar.org/docs/build/guides/transactions/send-and-receive-payments). - -### 3. Payments and money movement - -| Integration | Application to SAVE | -| --- | --- | -| Native XLM payments | Send, receive, request, and record XLM. | -| Issued-asset payments | Support selected stablecoins or other assets after validating code and issuer together. | -| Contract-account payments | Transfer Stellar assets between classic `G...` and contract `C...` addresses through the Stellar Asset Contract (SAC). | -| Payment requests | Produce QR codes and deep links for a prefilled destination, asset, amount, memo, or callback. SEP-7 supports delegated signing and payment requests. | -| Contacts and aliases | Save verified addresses locally/server-side; optionally resolve human-readable addresses through SEP-2 federation. | -| Pooled account routing | Use muxed accounts or memos to associate inbound funds with a user when operating a shared account. Enforce memo requirements where an exchange/anchor requires them. | -| Claimable balances | Send an asset before a recipient has a trustline, add time predicates, or create time-bounded gifts/rewards. Include a reclaim path to avoid permanent unclaimed entries. | -| Batched payments | Bundle up to the protocol's allowed operation count in a classic transaction for reimbursements or distributions. Smart-contract transactions have different one-operation constraints. | -| Fee sponsorship | Pay users' network fees using fee-bump transactions without taking control of their funds. | -| Reserve sponsorship | Sponsor account creation, trustlines, signers, offers, and other reserve-bearing entries. | -| Merchant/receipt matching | Attach a stable internal reference using a memo where appropriate, then reconcile the chain event with the scanned receipt. Never place private receipt details on-chain. | - -References: [send and receive payments](https://developers.stellar.org/docs/build/guides/transactions/send-and-receive-payments), [SEP-7](https://developers.stellar.org/docs/build/apps/wallet/sep7), [claimable balances](https://developers.stellar.org/docs/build/guides/transactions/claimable-balances), [sponsored reserves](https://developers.stellar.org/docs/build/guides/transactions/sponsored-reserves), and [fee-bump transactions](https://developers.stellar.org/docs/build/guides/transactions/fee-bump-transactions). - -### 4. Fiat on/off-ramps, KYC, and remittances - -SAVE can consume an existing anchor rather than becoming one: - -- SEP-1: discover an anchor and its supported assets from `stellar.toml`; -- SEP-10: authenticate a classic Stellar account to the anchor; -- SEP-45: authenticate a contract account to an anchor; -- SEP-12/SEP-9: collect and update required KYC fields; -- SEP-24: open a hosted interactive deposit or withdrawal flow; -- SEP-6: implement programmatic deposits and withdrawals; -- SEP-38: show indicative or firm conversion quotes; and -- SEP-31: participate in cross-border payment flows where the provider relationships and compliance model support it. - -The current `expo-web-browser`, `expo-linking`, and `saveproject` custom scheme can handle hosted-flow callbacks. Production should also configure HTTPS universal/app links and use development builds for realistic callback tests. The [Expo 57 Linking API](https://docs.expo.dev/versions/v57.0.0/sdk/linking/) warns that Expo Go URLs are not stable for authorization callbacks. Anchor support is described by the [Wallet SDK guide](https://developers.stellar.org/docs/build/apps/wallet/intro) and [Anchor Platform](https://developers.stellar.org/docs/platforms/anchor-platform). - -Becoming an anchor is also technically possible: the existing Docker/NestJS stack could run a business server beside Stellar Anchor Platform and implement KYC, quote, transaction-status, settlement, and callback endpoints. That option requires banking/payment partners, liquidity, sanctions and AML controls, data-retention policies, incident response, and jurisdiction-specific legal review. It should be treated as a separate program, not an ordinary app feature. - -### 5. Asset conversion and liquidity - -| Integration | What SAVE could expose | Risk/constraint | -| --- | --- | --- | -| Path payment | User spends XLM while the recipient receives a stablecoin, or vice versa. | Quote expiration, slippage bounds, trustlines, and route availability must be shown before signing. | -| SDEX order | Buy/sell assets with limit offers and show open-order status. | Asset verification, thin liquidity, price impact, and user education. | -| Liquidity-pool deposit/withdrawal | Track or manage LP positions. | Impermanent loss, reserve requirements, and financial-product disclosures. | -| Soroban DEX/DeFi adapter | Route swaps or deposits to reviewed third-party contracts. | Contract, oracle, liquidity, upgrade, and governance risk; use allowlisted contract IDs by network. | - -Classic path payments can route through the Stellar decentralized exchange and protocol liquidity pools. See [path payments](https://developers.stellar.org/docs/build/guides/transactions/path-payments) and [Stellar liquidity](https://developers.stellar.org/docs/learn/fundamentals/liquidity-on-stellar-sdex-liquidity-pools). - -### 6. Soroban savings and finance contracts - -These are the most relevant custom-contract opportunities for SAVE: - -| Contract feature | Core behavior | Suggested priority | -| --- | --- | --- | -| Goal vault | Deposit XLM or an approved SAC asset toward a named goal; withdraw under defined owner and deadline rules. | P1 | -| Time-locked savings | Prevent ordinary withdrawal until a timestamp/ledger deadline, with a clearly defined emergency path. | P1 | -| Shared savings pot | Multiple members contribute; withdrawal requires threshold or role-based approval. | P2 | -| Envelope vaults | Keep auditable balances for categories or goals while assets remain in contract custody. | P2 | -| Allowance/spending policy | Permit a capped amount per period, recipient allowlist, or dual approval. | P2; often best as a smart-wallet policy. | -| Milestone escrow | Release funds after payer/payee approval, deadline, or an authorized arbiter decision. | P2 | -| Matching contribution | Sponsor matches eligible deposits up to a cap. | P2 | -| Rewards distribution | Distribute an existing Stellar asset for savings streaks or program participation. | P2/P3 | -| Round-up aggregation | Accumulate computed round-ups and periodically deposit them into a goal. | P2; computation and triggering remain off-chain. | -| Recurring contribution | Store a schedule/allowance and let an authorized keeper submit due contributions. | P2; contracts do not initiate transactions by themselves. | -| Conditional disbursement | Release funds based on approved attestations or oracle data. | P3; oracle trust must be explicit. | -| Group lending / rotating savings | Contributions and scheduled payouts for a savings circle. | P3; high contract, default, identity, and regulatory risk. | -| DeFi yield adapter | Deposit eligible assets into a reviewed lending/liquidity protocol and account for shares/yield. | P3; do not advertise principal safety or fixed yield. | -| Governance | Member voting over shared treasury rules or upgrades. | P3. | -| Proof/attestation | Publish a hash or minimal event proving a milestone or approved record. | Optional; never publish personal finance data. | - -Soroban contracts are Rust programs compiled to Wasm. They can authorize both account and contract addresses and can interact with Stellar assets through the SAC, but they cannot directly invoke the SDEX, claimable-balance, or sponsorship operations. Those classic operations must be composed outside the contract in separately authorized transactions. See the [Soroban overview](https://developers.stellar.org/docs/build/smart-contracts/overview), [contract authorization](https://developers.stellar.org/docs/build/guides/auth/contract-authorization), and [SAC documentation](https://developers.stellar.org/docs/tokens/stellar-asset-contract). - -### 7. Assets and tokens - -SAVE has four possible levels of token integration: - -1. **Display and transfer existing assets.** This is the recommended baseline. Maintain a reviewed allowlist keyed by `(network, asset code, issuer)` or contract ID. -2. **Use existing assets in a vault.** Deploy/use their built-in SAC and accept only configured token contract IDs. -3. **Issue a SAVE rewards asset.** A classic Stellar asset is normally preferable for a transferable loyalty/reward unit because it gains wallet, exchange, anchor, and SAC compatibility. Publish complete metadata in `/.well-known/stellar.toml`, separate issuer and distribution accounts, and protect issuer authority with cold/multisig controls. -4. **Build a SEP-41 contract token or regulated token.** Do this only when protocol assets cannot express the required behavior. Custom tokens add contract and interoperability work; regulated/RWA tokens add identity, transfer restriction, clawback, disclosure, reserve, and legal obligations. - -Stellar explicitly recommends a protocol-issued asset plus SAC when it is sufficient. See [asset and contract-token comparison](https://developers.stellar.org/docs/tokens), [issuing an asset](https://developers.stellar.org/docs/tokens/how-to-issue-an-asset), [publishing asset information](https://developers.stellar.org/docs/tokens/publishing-asset-info), and the [token interface](https://developers.stellar.org/docs/tokens/token-interface). - -### 8. Authentication and identity protocols - -Possible additions include: - -- wallet ownership login using SEP-10 for classic accounts or SEP-45 for contract accounts; -- an app session linked to one or more Stellar addresses; -- KYC state and anchor customer IDs without putting PII on-chain; -- federation names for easier addressing; -- verified domain and asset/service discovery through SEP-1; -- regulated-asset approval flows (SEP-8) where required; and -- account/address identicons (SEP-33) to reduce address-selection mistakes. - -Wallet authentication proves control of an address; it does not prove a legal identity. Keep the current app user ID distinct from account address, KYC customer ID, and device credential. - -### 9. Admin, reconciliation, and operations - -The Next.js admin and NestJS backend can support: - -- per-network contract and asset allowlists; -- sponsor account balance/reserve/fee monitoring; -- transaction submission queue and idempotent retries; -- RPC cursor checkpoints and reprocessing; -- ledger-confirmation and failed-transaction reconciliation; -- unmatched deposit, memo, receipt, and internal-record review; -- vault totals and contract-event dashboards; -- anchor transaction and KYC status support tools; -- signer/threshold and issuer/distribution-account monitoring; -- suspicious activity and velocity alerts; -- contract Wasm hash, deployment, upgrade, and TTL tracking; and -- audit exports that distinguish on-chain facts from editable app metadata. - -Redis/BullMQ is suitable for polling, retry, and reconciliation work, but MongoDB should contain durable idempotency records and the last processed ledger/cursor. A queue acknowledgement is not evidence of ledger finality. - -## Proposed architecture - -| Layer | Responsibility | -| --- | --- | -| Expo app | Address management, balance views, transaction review, local signing or wallet handoff, biometric confirmation, QR/deep links, anchor browser flows, and offline read cache. | -| NestJS API | User/address associations, policies, unsigned transaction preparation, fee sponsorship, RPC access, event normalization, idempotency, anchor callbacks, and notifications. | -| Soroban contracts | Minimal enforceable vault, escrow, shared-control, or smart-wallet rules; token custody only where the product requires it. | -| MongoDB | Users, linked accounts, app metadata, normalized operations/events, reconciliation state, anchor references, and audit records. | -| Redis/BullMQ | Event polling, retryable submissions, reconciliation, quote expiry, notification, and TTL-maintenance jobs. | -| Next.js admin | Contract/asset configuration, exception handling, sponsor health, reconciliation, compliance status, and audit views. | -| Stellar RPC | Current ledger state, simulation, submission, recent transaction lookup, and events. | -| Hubble/Galexie or managed indexer | Long-range historical and analytical data when required. | - -## Required data-model changes - -The existing `ApiTransaction` is an app finance record and is not sufficient as a blockchain transaction. Preserve it, but add separate entities such as: - -- `StellarAccount`: user ID, network, address, account kind, label, custody mode, and verification status; -- `Asset`: network, type, code, issuer or contract ID, decimals, home domain, and allowlist status; -- `LedgerTransaction`: hash, envelope/result XDR references, source, ledger, timestamps, fee, status, and paging cursor; -- `LedgerOperation` / `ContractEvent`: operation/event type, source, destination, asset, exact decimal amount, contract ID, topics, and raw reference; -- `SigningRequest`: unsigned XDR, network passphrase, summary, expiration, nonce/idempotency key, signer set, and status; -- `VaultPosition`: contract ID, owner, asset contract ID, deposited/withdrawn amounts, goal, deadline, and state; -- `AnchorTransaction`: SEP type, anchor domain, external ID, status, quote ID, KYC customer ID, and sanitized callback data; and -- `ChainLink`: relationship between a user-entered income/expense record and one or more ledger operations/events. - -Never store Stellar amounts in JavaScript `number` or MongoDB floating-point fields. Preserve the network's exact decimal string/integer representation and format only at the UI boundary. A ledger transaction may contain multiple operations, while one finance record may match multiple ledger events, so do not overload the current single `id/type/amount` record. - -## Expo 57 integration notes - -- The installed `expo-secure-store` is appropriate for small encrypted values, tokens, or a wrapped-key reference, but secrets need an explicit backup/recovery design. Review the exact [Expo 57 SecureStore API](https://docs.expo.dev/versions/v57.0.0/sdk/securestore/). -- The installed `expo-local-authentication` can gate signing; Face ID requires a development build and its iOS permission configuration. See [Expo 57 LocalAuthentication](https://docs.expo.dev/versions/v57.0.0/sdk/local-authentication/). -- The existing custom scheme supports callbacks, but production wallet/anchor flows should add verified universal/app links and strict route/parameter validation. See [Expo 57 Linking](https://docs.expo.dev/versions/v57.0.0/sdk/linking/). -- `expo-web-browser` can host SEP-24/KYC flows, returning through the configured link. Never assume browser success means an on-chain transfer succeeded; reconcile with the anchor and ledger. -- `@stellar/stellar-sdk` officially targets browser and Node.js environments. React Native compatibility and any required crypto/Buffer polyfills must be validated in an Expo development build before choosing client-side signing. A backend-only SDK integration avoids native bundling issues but cannot provide non-custodial signing by itself. See [Stellar client SDKs](https://developers.stellar.org/docs/tools/sdks/client-sdks). -- The TypeScript Wallet SDK covers common wallet and anchor flows; use lower-level SDK/RPC calls for advanced operations and Soroban. Validate its native runtime behavior in this exact Expo/React Native version before adopting it. - -## Security, privacy, and correctness requirements - -- Default to Testnet until end-to-end reconciliation, recovery, and failure handling are proven. -- Make the selected network unmistakable and bind every signature to the expected network passphrase. -- Never send a user secret seed, decrypted key, passkey private material, or recovery secret to the backend or logs in a non-custodial design. -- Show a decoded transaction summary—asset and issuer/contract, amount, destination, memo, contract, function, arguments, and maximum fee—before signing. -- Simulate Soroban transactions immediately before signing and enforce resource-fee and expiration bounds. -- Treat all deep links, wallet callbacks, anchor responses, RPC responses, and contract events as untrusted input. -- Use destination, asset, issuer/contract, and network allowlists where a feature does not require arbitrary values. -- Use idempotency keys and reconcile by transaction hash, ledger, operation/event identity, and cursor. Never mark a payment final from a client callback alone. -- Keep PII, receipt images, budget names, notes, categories, and KYC documents off-chain. Store only minimal public identifiers or commitments when essential. -- Separate sponsor, relayer, issuer, distribution, admin, and operational keys. Protect privileged keys with HSM/KMS or cold multisig; never place them in the mobile bundle or ordinary environment files. -- Audit any contract that can custody or control value. Use property/fuzz tests, invariant tests, Testnet deployments, reproducible Wasm builds, verified source, upgrade controls, and an incident/pausing strategy appropriate to the custody model. -- Plan contract storage TTL and restoration. TTL expiry is not a safe deadline mechanism, and extending/restoring state costs fees. See [Soroban storage guidance](https://developers.stellar.org/docs/build/guides/storage/storage-strategies). -- Obtain legal review before custody, fiat ramps, rewards with monetary value, swaps, yield, lending, pooled funds, remittances, securities/RWAs, or operation in regulated jurisdictions. - -## Known limitations and non-goals - -- Soroban contracts do not execute on a timer and cannot initiate a transaction. Recurring deposits require a user, relayer, or keeper to submit an authorized invocation. -- A Soroban contract cannot directly operate the classic SDEX, claimable balances, or sponsorships. The client/backend must build the relevant classic transactions. -- Blockchain data is public; encryption elsewhere does not make an on-chain amount, address, or event private. -- A Stellar address is not a verified person, and a confirmed transaction is not automatically a correctly categorized income/expense record. -- On-chain balances do not provide historical fiat prices, tax lots, merchant identity, or exchange-rate truth. Those require separate data and accounting policies. -- Offline mode can display cached data and queue intent, but it cannot truthfully confirm sequence numbers, simulation results, quotes, fees, or finality until reconnected. -- “Stablecoin” does not guarantee redemption, price stability, liquidity, or regulatory availability. SAVE must verify issuers and communicate asset-specific risks. -- Smart-contract programmability does not remove custody, consumer-protection, tax, sanctions, AML, or securities obligations. - -## Delivery roadmap - -### Phase 0 — Decisions and proof of compatibility - -1. Choose non-custodial external wallet, app-managed key, smart wallet, or watch-only scope. -2. Choose Testnet asset allowlist and a managed/public RPC provider. -3. Prove `@stellar/stellar-sdk`, Wallet SDK, required polyfills, deep links, SecureStore, and biometric confirmation in Android/iOS development builds and web. -4. Define exact amount, network, account, ledger-event, and idempotency models. -5. Write threat, custody, recovery, compliance, and privacy decisions before handling value. - -### Phase 1 — Read-only vertical slice - -1. Link a Testnet address. -2. Import balances and payment events through RPC. -3. Store cursors and normalized ledger data in the backend. -4. Display explorer-verifiable activity and link it to optional SAVE categories. -5. Add admin reconciliation and RPC-health views. - -### Phase 2 — Payments - -1. Build, decode, review, sign, submit, and reconcile Testnet payments. -2. Add receive/request QR and deep-link flows. -3. Add fee-bump and reserve sponsorship with strict quotas. -4. Add trustline and claimable-balance handling for one reviewed stablecoin. -5. Test timeout, duplicate submission, sequence conflict, fee surge, bad memo, wrong network, and callback spoofing cases. - -### Phase 3 — Fiat access - -1. Integrate one reviewed test anchor using SEP-1/10/12/24/38. -2. Handle browser callbacks, anchor status, ledger status, and cancellation independently. -3. Add production KYC/privacy/legal controls before any Mainnet launch. - -### Phase 4 — Goal vault - -1. Specify owner, asset, deposit, withdrawal, deadline, emergency, upgrade, fee, and TTL invariants. -2. Implement and test the minimal Rust contract. -3. Generate typed client bindings, simulate every invocation, and index contract events. -4. Audit, deploy to Testnet, verify Wasm/source, and complete failure/recovery drills before Mainnet. - -### Phase 5 — Optional expansion - -Add shared savings, smart-wallet policies, path payments, recovery, rewards, remittances, or reviewed DeFi adapters only in response to a validated product need. Each should receive its own threat model and go/no-go review. - -## Final recommendation - -Build the first release as a non-custodial, Testnet-first wallet companion: watch/link an account, import balances and payments via RPC, send and request a reviewed asset with external or locally protected signing, sponsor fees/reserves, and reconcile every action through the backend. Then add one deliberately small Soroban goal-vault contract. This path reuses nearly every existing part of SAVE while keeping custody, contract, and regulatory risk bounded. diff --git a/backend/.env.example b/backend/.env.example index 79bed9c..2e49c92 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -10,3 +10,18 @@ S3_ACCESS_KEY=save-access-key S3_SECRET_KEY=save-secret-key JWT_SECRET=replace_with_secure_secret + +# Stellar Testnet only. Do not put secret seeds in this file. +STELLAR_NETWORK=TESTNET +STELLAR_NETWORK_PASSPHRASE=Test SDF Network ; September 2015 +STELLAR_HORIZON_URL=https://horizon-testnet.stellar.org +STELLAR_RPC_URL=https://soroban-testnet.stellar.org +STELLAR_FRIENDBOT_URL=https://friendbot.stellar.org +STELLAR_VAULT_CONTRACT_ID=CALFEOYNTNJYB5HTUPYHHFHMNNYLYEBOCV43Z73J54G3CQNSH5VCNP7H +STELLAR_XLM_SAC_ID=CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC +STELLAR_MAX_SOROBAN_FEE=2000000 +STELLAR_EVENT_POLL_MS=15000 +STELLAR_CALLBACK_BASE_URL=http://localhost:3000 +STELLAR_ORIGIN_DOMAIN= +STELLAR_INTEGRITY_SIGNER_SECRET_FILE= +EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID=219c5a0dcc9ced2856f12d0df4a2d484 \ No newline at end of file diff --git a/backend/nest-cli.json b/backend/nest-cli.json new file mode 100644 index 0000000..f9aa683 --- /dev/null +++ b/backend/nest-cli.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/nest-cli", + "collection": "@nestjs/schematics", + "sourceRoot": "src", + "compilerOptions": { + "deleteOutDir": true + } +} diff --git a/backend/package-lock.json b/backend/package-lock.json index d06c0a0..6c3e59a 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -14,6 +14,7 @@ "@nestjs/mongoose": "^11.0.0", "@nestjs/platform-express": "^11.0.0", "@nestjs/swagger": "^11.0.0", + "@stellar/stellar-sdk": "^17.0.1", "bullmq": "^5.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", @@ -212,6 +213,23 @@ "node": ">=12" } }, + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, "node_modules/@inquirer/ansi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", @@ -1038,6 +1056,27 @@ } } }, + "node_modules/@noble/ed25519": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-3.2.0.tgz", + "integrity": "sha512-criDgRlnUA09hchYrTy/JUWPIEap5rZxQe6wDWzRx51oWWpDRcUpuNzlgPxDJaOK6AsW9c0wKcj3rKRv6t+bPQ==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz", + "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@redis/bloom": { "version": "5.12.1", "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.12.1.tgz", @@ -1126,6 +1165,51 @@ "hasInstallScript": true, "license": "Apache-2.0" }, + "node_modules/@stellar/js-xdr": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-5.0.0.tgz", + "integrity": "sha512-HBDNKnxr+ecdaEmbZ0mcKkirOF8tXXEbWSw34P3wT40Tn3g+u+cCH17xAWZymzscq8cojHB8340pR8QNVaD32w==", + "license": "Apache-2.0", + "engines": { + "node": ">=22.0.0", + "pnpm": ">=10.0.0" + } + }, + "node_modules/@stellar/stellar-sdk": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-17.0.1.tgz", + "integrity": "sha512-fsHHbzJ14N5Ttq5Qpz4AX0ytmPSLCzcy4XC3uIgSQz0cBkEgv0Zb4KE6tWEd3nDQUk/1qP8ZX9cRonIaUXO3Sw==", + "license": "Apache-2.0", + "dependencies": { + "@exodus/bytes": "^1.15.1", + "@noble/ed25519": "^3.1.0", + "@noble/hashes": "^2.2.0", + "@stellar/js-xdr": "^5.0.0", + "@types/json-schema": "^7.0.15", + "axios": "1.18.0", + "bignumber.js": "^11.1.4", + "commander": "^14.0.3", + "eventsource": "^4.1.0", + "feaxios": "^0.0.23", + "smol-toml": "^1.6.1", + "uint8array-extras": "^1.5.0" + }, + "bin": { + "stellar-js": "bin/stellar-js" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@stellar/stellar-sdk/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/@tokenizer/inflate": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", @@ -1263,7 +1347,6 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, "license": "MIT" }, "node_modules/@types/node": { @@ -1559,6 +1642,18 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", @@ -1679,6 +1774,24 @@ "dev": true, "license": "MIT" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz", + "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1720,6 +1833,12 @@ "node": ">=6.0.0" } }, + "node_modules/bignumber.js": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-11.1.5.tgz", + "integrity": "sha512-6WmzCNtUnfKpbozq+hOgWaZMMzORmYBwF1xZScyoIX3QRYWeKTtxxwDOW5tIz7C9BdjkIYHGTcelCLkXg0mndw==", + "license": "MIT" + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -2117,6 +2236,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -2330,6 +2461,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -2511,6 +2651,21 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2607,6 +2762,27 @@ "node": ">=0.8.x" } }, + "node_modules/eventsource": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-4.1.1.tgz", + "integrity": "sha512-D6bTRWh6KahHTK/m4WnjPQyEinNPf9eFLEZSEoj7d6fTibspnAVYfzHvirL7u/aoX5d9YYfIkBVAhmigUELk9w==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.1.tgz", + "integrity": "sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/express": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", @@ -2687,6 +2863,15 @@ ], "license": "BSD-3-Clause" }, + "node_modules/feaxios": { + "version": "0.0.23", + "resolved": "https://registry.npmjs.org/feaxios/-/feaxios-0.0.23.tgz", + "integrity": "sha512-eghR0A21fvbkcQBgZuMfQhrXxJzC0GNUGC9fXhBge33D+mFDTwl0aJ35zoQQn575BhyjQitRc5N4f+L4cP708g==", + "license": "MIT", + "dependencies": { + "is-retry-allowed": "^3.0.0" + } + }, "node_modules/file-type": { "version": "21.3.4", "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.4.tgz", @@ -2726,6 +2911,26 @@ "url": "https://opencollective.com/express" } }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz", @@ -2754,6 +2959,43 @@ "webpack": "^5.11.0" } }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2945,6 +3187,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", @@ -2977,6 +3234,19 @@ "url": "https://opencollective.com/express" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/iconv-lite": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", @@ -3100,6 +3370,18 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/is-retry-allowed": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-3.0.0.tgz", + "integrity": "sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -3939,6 +4221,15 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -4362,6 +4653,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/smol-toml": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz", + "integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", diff --git a/backend/package.json b/backend/package.json index f233470..5404167 100644 --- a/backend/package.json +++ b/backend/package.json @@ -9,7 +9,7 @@ "start:debug": "nest start --debug --watch", "seed": "ts-node src/seed/seed.ts", "lint": "eslint . --ext .ts", - "test": "jest" + "test": "npm run build && node --test test/*.test.cjs" }, "dependencies": { "@nestjs/common": "^11.0.0", @@ -18,6 +18,7 @@ "@nestjs/mongoose": "^11.0.0", "@nestjs/platform-express": "^11.0.0", "@nestjs/swagger": "^11.0.0", + "@stellar/stellar-sdk": "^17.0.1", "bullmq": "^5.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 4efe8d2..4fce6e9 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -7,6 +7,7 @@ import { CategoriesModule } from './categories/categories.module'; import { TransactionsModule } from './transactions/transactions.module'; import { UsersModule } from './users/users.module'; import { SavingsModule } from './savings/savings.module'; +import { StellarModule } from './stellar/stellar.module'; @Module({ imports: [ @@ -26,6 +27,7 @@ import { SavingsModule } from './savings/savings.module'; CategoriesModule, BudgetsModule, SavingsModule, + StellarModule, ], controllers: [], providers: [], diff --git a/backend/src/stellar/stellar.controller.ts b/backend/src/stellar/stellar.controller.ts new file mode 100644 index 0000000..290fbac --- /dev/null +++ b/backend/src/stellar/stellar.controller.ts @@ -0,0 +1,57 @@ +import { Body, Controller, Get, Header, HttpCode, Param, ParseIntPipe, Post, Query } from '@nestjs/common'; + +import { LinkStellarAccountDto, PreparePaymentDto, PrepareVaultInvocationDto, Sep7CallbackDto, StellarEventsQueryDto, SubmitStellarTransactionDto } from './stellar.dto'; +import { StellarService } from './stellar.service'; + +@Controller('stellar') +export class StellarController { + constructor(private readonly stellar: StellarService) {} + + @Get('network') + network() { return this.stellar.networkHealth(); } + + @Post('accounts/link') + linkAccount(@Body() dto: LinkStellarAccountDto) { return this.stellar.linkAccount(dto); } + + @Get('accounts/:address') + portfolio(@Param('address') address: string) { return this.stellar.getPortfolio(address); } + + @Get('accounts/:address/payments') + payments(@Param('address') address: string, @Query('limit', new ParseIntPipe({ optional: true })) limit?: number) { return this.stellar.getPayments(address, limit); } + + @Post('payments/prepare') + preparePayment(@Body() dto: PreparePaymentDto) { return this.stellar.preparePayment(dto); } + + @Post('vault/prepare') + prepareVault(@Body() dto: PrepareVaultInvocationDto) { return this.stellar.prepareVaultInvocation(dto); } + + @Get('vault/goals/:owner') + vaultGoals(@Param('owner') owner: string) { return this.stellar.listVaultGoals(owner); } + + @Get('vault/events') + vaultEvents(@Query() query: StellarEventsQueryDto) { return this.stellar.getVaultEvents(query); } + + @Post('transactions/submit') + submit(@Body() dto: SubmitStellarTransactionDto) { return this.stellar.submitTransaction(dto); } + + @Get('signing-requests/:idempotencyKey') + signingRequest(@Param('idempotencyKey') idempotencyKey: string) { return this.stellar.getSigningRequest(idempotencyKey); } + + @Post('signing-requests/:idempotencyKey/callback') + @HttpCode(200) + signingCallback(@Param('idempotencyKey') idempotencyKey: string, @Body() dto: Sep7CallbackDto) { + return this.stellar.receiveSep7Callback(idempotencyKey, dto.xdr); + } + + @Get('transactions/:hash') + transaction(@Param('hash') hash: string, @Query('kind') kind: 'classic' | 'soroban' = 'soroban') { return this.stellar.getTransaction(hash, kind); } +} + +@Controller('.well-known') +export class StellarTomlController { + constructor(private readonly stellar: StellarService) {} + + @Get('stellar.toml') + @Header('Content-Type', 'text/plain; charset=utf-8') + stellarToml() { return this.stellar.stellarToml(); } +} diff --git a/backend/src/stellar/stellar.dto.ts b/backend/src/stellar/stellar.dto.ts new file mode 100644 index 0000000..c7b5550 --- /dev/null +++ b/backend/src/stellar/stellar.dto.ts @@ -0,0 +1,109 @@ +import { IsEnum, IsInt, IsNotEmpty, IsOptional, IsString, Matches, Max, Min } from 'class-validator'; + +const AMOUNT_PATTERN = /^(0|[1-9]\d*)(\.\d{1,7})?$/; + +export class LinkStellarAccountDto { + @IsString() + @IsNotEmpty() + address: string; +} + +export class PreparePaymentDto { + @IsString() + source: string; + + @IsString() + destination: string; + + @IsString() + @Matches(AMOUNT_PATTERN) + amount: string; + + @IsOptional() + @IsString() + memo?: string; + + @IsString() + @IsNotEmpty() + idempotencyKey: string; +} + +export class PrepareVaultInvocationDto { + @IsString() + source: string; + + @IsEnum(['create_goal', 'contribute', 'complete_goal', 'withdraw', 'cancel_goal']) + action: 'create_goal' | 'contribute' | 'complete_goal' | 'withdraw' | 'cancel_goal'; + + @IsString() + @IsNotEmpty() + idempotencyKey: string; + + @IsOptional() + @IsString() + owner?: string; + + @IsOptional() + @IsString() + contributor?: string; + + @IsOptional() + @IsString() + assetContractId?: string; + + @IsOptional() + @IsString() + @Matches(/^\d+$/) + goalId?: string; + + @IsOptional() + @IsString() + @Matches(/^\d+$/) + targetAmount?: string; + + @IsOptional() + @IsString() + @Matches(/^\d+$/) + targetDate?: string; + + @IsOptional() + @IsString() + @Matches(/^\d+$/) + amount?: string; +} + +export class SubmitStellarTransactionDto { + @IsString() + @IsNotEmpty() + signedXdr: string; + + @IsEnum(['classic', 'soroban']) + kind: 'classic' | 'soroban'; + + @IsOptional() + @IsString() + idempotencyKey?: string; +} + +export class Sep7CallbackDto { + @IsString() + @IsNotEmpty() + xdr: string; +} + +export class StellarEventsQueryDto { + @IsOptional() + @IsString() + cursor?: string; + + @IsOptional() + @IsInt() + @Min(1) + startLedger?: number; + + @IsOptional() + @IsInt() + @Min(1) + @Max(100) + limit?: number; +} diff --git a/backend/src/stellar/stellar.module.ts b/backend/src/stellar/stellar.module.ts new file mode 100644 index 0000000..f63d983 --- /dev/null +++ b/backend/src/stellar/stellar.module.ts @@ -0,0 +1,18 @@ +import { Module } from '@nestjs/common'; +import { MongooseModule } from '@nestjs/mongoose'; + +import { StellarController, StellarTomlController } from './stellar.controller'; +import { StellarService } from './stellar.service'; +import { StellarAccount, StellarAccountSchema, StellarContractEvent, StellarContractEventSchema, StellarSigningRequest, StellarSigningRequestSchema } from './stellar.schema'; + +@Module({ + imports: [MongooseModule.forFeature([ + { name: StellarAccount.name, schema: StellarAccountSchema }, + { name: StellarSigningRequest.name, schema: StellarSigningRequestSchema }, + { name: StellarContractEvent.name, schema: StellarContractEventSchema }, + ])], + controllers: [StellarController, StellarTomlController], + providers: [StellarService], + exports: [StellarService], +}) +export class StellarModule {} diff --git a/backend/src/stellar/stellar.schema.ts b/backend/src/stellar/stellar.schema.ts new file mode 100644 index 0000000..db105d0 --- /dev/null +++ b/backend/src/stellar/stellar.schema.ts @@ -0,0 +1,41 @@ +import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; +import { HydratedDocument, SchemaTypes } from 'mongoose'; + +@Schema({ timestamps: true }) +export class StellarAccount { + @Prop({ required: true, unique: true, index: true }) address: string; + @Prop({ required: true, default: 'testnet', index: true }) network: string; + @Prop({ required: true, default: 'watch-only' }) signingMode: string; + @Prop() lastSyncedAt?: Date; +} +export type StellarAccountDocument = HydratedDocument; +export const StellarAccountSchema = SchemaFactory.createForClass(StellarAccount); + +@Schema({ timestamps: true }) +export class StellarSigningRequest { + @Prop({ required: true, unique: true, index: true }) idempotencyKey: string; + @Prop({ required: true, enum: ['classic', 'soroban'] }) kind: string; + @Prop({ required: true }) action: string; + @Prop({ required: true, index: true }) source: string; + @Prop({ required: true }) unsignedXdr: string; + @Prop({ required: true, enum: ['prepared', 'submitted', 'pending', 'success', 'failed'], index: true }) status: string; + @Prop({ index: true }) hash?: string; + @Prop() fee?: string; + @Prop() error?: string; +} +export type StellarSigningRequestDocument = HydratedDocument; +export const StellarSigningRequestSchema = SchemaFactory.createForClass(StellarSigningRequest); + +@Schema({ timestamps: true }) +export class StellarContractEvent { + @Prop({ required: true, unique: true, index: true }) eventId: string; + @Prop({ required: true, index: true }) contractId: string; + @Prop({ required: true, index: true }) ledger: number; + @Prop({ required: true, index: true }) transactionHash: string; + @Prop() ledgerClosedAt?: string; + @Prop({ type: [SchemaTypes.Mixed], default: [] }) topics: unknown[]; + @Prop({ type: SchemaTypes.Mixed }) value: unknown; + @Prop({ required: true, default: true }) successful: boolean; +} +export type StellarContractEventDocument = HydratedDocument; +export const StellarContractEventSchema = SchemaFactory.createForClass(StellarContractEvent); diff --git a/backend/src/stellar/stellar.sep7.ts b/backend/src/stellar/stellar.sep7.ts new file mode 100644 index 0000000..b362f3a --- /dev/null +++ b/backend/src/stellar/stellar.sep7.ts @@ -0,0 +1,67 @@ +import { readFileSync, statSync } from 'node:fs'; + +import { Keypair, TransactionBuilder } from '@stellar/stellar-sdk'; + +const SEP7_PREFIX = 'stellar.sep.7 - URI Scheme'; + +export function loadIntegritySigner(secretFile?: string): Keypair | undefined { + if (!secretFile) return undefined; + + const stats = statSync(secretFile); + if (!stats.isFile()) throw new Error('STELLAR_INTEGRITY_SIGNER_SECRET_FILE must reference a regular file'); + if (process.platform !== 'win32' && (stats.mode & 0o077) !== 0) { + throw new Error('Stellar integrity signer secret file must not be accessible by group or other users'); + } + + return Keypair.fromSecret(readFileSync(secretFile, 'utf8').trim()); +} + +export function transactionHash(xdr: string, networkPassphrase: string): string { + const transaction = TransactionBuilder.fromXDR(xdr, networkPassphrase); + return Buffer.from(transaction.hash()).toString('hex'); +} + +export function assertMatchingSignedTransaction( + unsignedXdr: string, + signedXdr: string, + networkPassphrase: string, +): void { + const unsigned = TransactionBuilder.fromXDR(unsignedXdr, networkPassphrase); + const signed = TransactionBuilder.fromXDR(signedXdr, networkPassphrase); + if (!('signatures' in signed) || signed.signatures.length === 0) { + throw new Error('Transaction has no signatures'); + } + if (Buffer.from(unsigned.hash()).compare(Buffer.from(signed.hash())) !== 0) { + throw new Error('Signed transaction does not match the prepared request'); + } +} + +export function signSep7Uri(uri: string, signer: Keypair): string { + const envelopeType = Buffer.alloc(36); + envelopeType[35] = 4; + const payload = Buffer.concat([envelopeType, Buffer.from(`${SEP7_PREFIX}${uri}`, 'utf8')]); + return Buffer.from(signer.sign(payload)).toString('base64'); +} + +export function buildSep7SigningUrl(options: { + xdr: string; + source: string; + action: string; + callbackUrl?: string; + originDomain?: string; + signer?: Keypair; +}): string { + const parameters = [ + `xdr=${encodeURIComponent(options.xdr)}`, + `pubkey=${encodeURIComponent(options.source)}`, + `msg=${encodeURIComponent(`SAVE Testnet: ${options.action.replaceAll('_', ' ')}`)}`, + ]; + if (options.callbackUrl) parameters.push(`callback=${encodeURIComponent(`url:${options.callbackUrl}`)}`); + if (options.originDomain && options.signer) { + parameters.push(`origin_domain=${encodeURIComponent(options.originDomain)}`); + } + + const unsignedUri = `web+stellar:tx?${parameters.join('&')}`; + if (!options.originDomain || !options.signer) return unsignedUri; + return `${unsignedUri}&signature=${encodeURIComponent(signSep7Uri(unsignedUri, options.signer))}`; +} diff --git a/backend/src/stellar/stellar.service.ts b/backend/src/stellar/stellar.service.ts new file mode 100644 index 0000000..f142b09 --- /dev/null +++ b/backend/src/stellar/stellar.service.ts @@ -0,0 +1,459 @@ +import { BadRequestException, ConflictException, Injectable, OnModuleDestroy, OnModuleInit, ServiceUnavailableException } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import { InjectModel } from '@nestjs/mongoose'; +import { Model } from 'mongoose'; +import { + Address, + Asset, + BASE_FEE, + Contract, + Horizon, + Keypair, + Memo, + Networks, + Operation, + StrKey, + TransactionBuilder, + nativeToScVal, + rpc, + scValToNative, +} from '@stellar/stellar-sdk'; + +import { LinkStellarAccountDto, PreparePaymentDto, PrepareVaultInvocationDto, StellarEventsQueryDto, SubmitStellarTransactionDto } from './stellar.dto'; +import { assertMatchingSignedTransaction, buildSep7SigningUrl, loadIntegritySigner, transactionHash } from './stellar.sep7'; +import { StellarAccount, StellarAccountDocument, StellarContractEvent, StellarContractEventDocument, StellarSigningRequest, StellarSigningRequestDocument } from './stellar.schema'; + +type SigningRequest = { + idempotencyKey: string; + kind: 'classic' | 'soroban'; + action: string; + source: string; + unsignedXdr: string; + status: 'prepared' | 'submitted' | 'pending' | 'success' | 'failed'; + hash: string; + fee?: string; + error?: string; + createdAt: string; +}; + +function jsonSafe(value: unknown): unknown { + if (typeof value === 'bigint') return value.toString(); + if (Array.isArray(value)) return value.map(jsonSafe); + if (value instanceof Map) return Object.fromEntries([...value.entries()].map(([key, item]) => [String(key), jsonSafe(item)])); + if (value && typeof value === 'object') { + return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, jsonSafe(item)])); + } + return value; +} + +@Injectable() +export class StellarService implements OnModuleInit, OnModuleDestroy { + private readonly horizonUrl: string; + private readonly rpcUrl: string; + private readonly networkPassphrase: string; + private readonly vaultContractId?: string; + private readonly xlmSacId: string; + private readonly maxSorobanFee: number; + private readonly callbackBaseUrl?: string; + private readonly originDomain?: string; + private readonly integritySigner?: Keypair; + private readonly horizon: Horizon.Server; + private readonly rpc: rpc.Server; + private readonly signingRequests = new Map(); + private readonly linkedAccounts = new Set(); + private eventCursor?: string; + private eventTimer?: NodeJS.Timeout; + private readonly eventPollMs: number; + + constructor( + config: ConfigService, + @InjectModel(StellarAccount.name) private readonly accountModel: Model, + @InjectModel(StellarSigningRequest.name) private readonly signingRequestModel: Model, + @InjectModel(StellarContractEvent.name) private readonly eventModel: Model, + ) { + this.horizonUrl = config.get('STELLAR_HORIZON_URL') ?? 'https://horizon-testnet.stellar.org'; + this.rpcUrl = config.get('STELLAR_RPC_URL') ?? 'https://soroban-testnet.stellar.org'; + this.networkPassphrase = config.get('STELLAR_NETWORK_PASSPHRASE') ?? Networks.TESTNET; + this.vaultContractId = config.get('STELLAR_VAULT_CONTRACT_ID'); + this.xlmSacId = config.get('STELLAR_XLM_SAC_ID') ?? Asset.native().contractId(this.networkPassphrase); + this.maxSorobanFee = Number(config.get('STELLAR_MAX_SOROBAN_FEE') ?? 2_000_000); + this.eventPollMs = Math.max(Number(config.get('STELLAR_EVENT_POLL_MS') ?? 15_000), 5_000); + this.callbackBaseUrl = config.get('STELLAR_CALLBACK_BASE_URL')?.replace(/\/+$/, ''); + this.originDomain = config.get('STELLAR_ORIGIN_DOMAIN')?.trim() || undefined; + this.integritySigner = loadIntegritySigner(config.get('STELLAR_INTEGRITY_SIGNER_SECRET_FILE')); + if (this.originDomain && !this.integritySigner) { + throw new Error('STELLAR_ORIGIN_DOMAIN requires STELLAR_INTEGRITY_SIGNER_SECRET_FILE'); + } + this.horizon = new Horizon.Server(this.horizonUrl, { allowHttp: this.horizonUrl.startsWith('http://') }); + this.rpc = new rpc.Server(this.rpcUrl, { allowHttp: this.rpcUrl.startsWith('http://') }); + } + + onModuleInit() { + if (!this.vaultContractId) return; + const poll = async () => { + try { + const page = await this.getVaultEvents(this.eventCursor ? { cursor: this.eventCursor, limit: 100 } : { limit: 100 }); + this.eventCursor = page.cursor; + } catch { + // RPC outages are retried on the next interval; no signing or state mutation occurs here. + } + }; + void poll(); + this.eventTimer = setInterval(() => void poll(), this.eventPollMs); + } + + onModuleDestroy() { + if (this.eventTimer) clearInterval(this.eventTimer); + } + + async networkHealth() { + try { + const [network, ledger] = await Promise.all([this.rpc.getNetwork(), this.rpc.getLatestLedger()]); + return { + network: 'testnet', + passphrase: network.passphrase, + protocolVersion: network.protocolVersion, + latestLedger: ledger.sequence, + horizonUrl: this.horizonUrl, + rpcUrl: this.rpcUrl, + vaultContractId: this.vaultContractId ?? null, + xlmSacId: this.xlmSacId, + sep7: { + callbackEnabled: Boolean(this.callbackBaseUrl), + requestSigningEnabled: Boolean(this.originDomain && this.integritySigner), + requestSigningPublicKey: this.integritySigner?.publicKey() ?? null, + originDomain: this.originDomain ?? null, + }, + }; + } catch (error) { + throw new ServiceUnavailableException(`Stellar Testnet is unavailable: ${error instanceof Error ? error.message : 'unknown RPC error'}`); + } + } + + stellarToml() { + const lines = [ + 'NETWORK_PASSPHRASE="Test SDF Network ; September 2015"', + 'VERSION="2.0.0"', + ]; + if (this.integritySigner) lines.push(`URI_REQUEST_SIGNING_KEY="${this.integritySigner.publicKey()}"`); + return `${lines.join('\n')}\n`; + } + + async linkAccount(dto: LinkStellarAccountDto) { + this.assertAccount(dto.address); + const portfolio = await this.getPortfolio(dto.address); + this.linkedAccounts.add(dto.address); + void this.accountModel.updateOne({ address: dto.address }, { $set: { network: 'testnet', signingMode: 'watch-only', lastSyncedAt: new Date() } }, { upsert: true }).catch(() => undefined); + return { ...portfolio, linked: true, signingMode: 'external-wallet', secretsStored: false }; + } + + async getPortfolio(address: string) { + this.assertAccount(address); + try { + const account = await this.horizon.loadAccount(address); + return { + address, + sequence: account.sequence, + balances: account.balances.map((balance) => ({ + asset: balance.asset_type === 'native' ? 'XLM' : `${'asset_code' in balance ? balance.asset_code : 'POOL'}`, + issuer: 'asset_issuer' in balance ? balance.asset_issuer : undefined, + balance: balance.balance, + assetType: balance.asset_type, + })), + subentryCount: account.subentry_count, + lastModifiedLedger: account.last_modified_ledger, + explorerUrl: `https://stellar.expert/explorer/testnet/account/${address}`, + }; + } catch (error) { + throw new ServiceUnavailableException(`Unable to load Testnet account: ${error instanceof Error ? error.message : 'Horizon error'}`); + } + } + + async getPayments(address: string, limit = 20) { + this.assertAccount(address); + try { + const page = await this.horizon.payments().forAccount(address).order('desc').limit(Math.min(Math.max(limit, 1), 100)).call(); + return page.records.map((record: any) => ({ id: record.id, type: record.type, from: record.from, to: record.to, amount: record.amount, asset: record.asset_type === 'native' ? 'XLM' : record.asset_code, transactionHash: record.transaction_hash, createdAt: record.created_at, explorerUrl: `https://stellar.expert/explorer/testnet/tx/${record.transaction_hash}` })); + } catch (error) { + throw new ServiceUnavailableException(`Unable to load Testnet payments: ${error instanceof Error ? error.message : 'Horizon error'}`); + } + } + + async preparePayment(dto: PreparePaymentDto) { + this.assertAccount(dto.source); this.assertAccount(dto.destination); + const existing = await this.findSigningRequest(dto.idempotencyKey); + if (existing) { + if (existing.action !== 'payment' || existing.source !== dto.source) throw new ConflictException('Idempotency key is already assigned to a different request'); + return this.presentSigningRequest(existing); + } + try { + const source = await this.horizon.loadAccount(dto.source); + let builder = new TransactionBuilder(source, { fee: BASE_FEE, networkPassphrase: this.networkPassphrase }) + .addOperation(Operation.payment({ destination: dto.destination, asset: Asset.native(), amount: dto.amount })); + if (dto.memo) builder = builder.addMemo(Memo.text(dto.memo.slice(0, 28))); + const transaction = builder.setTimeout(180).build(); + return this.recordSigningRequest(dto.idempotencyKey, 'classic', 'payment', dto.source, transaction.toXDR()); + } catch (error) { + throw new ServiceUnavailableException(`Unable to prepare payment: ${error instanceof Error ? error.message : 'Horizon error'}`); + } + } + + async prepareVaultInvocation(dto: PrepareVaultInvocationDto) { + this.assertAccount(dto.source); + const contractId = this.requireVaultContract(); + const existing = await this.findSigningRequest(dto.idempotencyKey); + if (existing) { + if (existing.action !== dto.action || existing.source !== dto.source) throw new ConflictException('Idempotency key is already assigned to a different request'); + return this.presentSigningRequest(existing); + } + try { + const source = await this.rpc.getAccount(dto.source); + const contract = new Contract(contractId); + const operation = contract.call(dto.action, ...this.vaultArguments(dto)); + const raw = new TransactionBuilder(source, { fee: BASE_FEE, networkPassphrase: this.networkPassphrase }).addOperation(operation).setTimeout(180).build(); + const prepared = await this.rpc.prepareTransaction(raw); + if (Number(prepared.fee) > this.maxSorobanFee) throw new BadRequestException(`Simulated fee ${prepared.fee} exceeds configured bound ${this.maxSorobanFee}`); + return this.recordSigningRequest(dto.idempotencyKey, 'soroban', dto.action, dto.source, prepared.toXDR(), prepared.fee); + } catch (error) { + if (error instanceof BadRequestException) throw error; + throw new ServiceUnavailableException(`Unable to simulate vault invocation: ${error instanceof Error ? error.message : 'RPC error'}`); + } + } + + async submitTransaction(dto: SubmitStellarTransactionDto) { + let transaction: ReturnType; + try { transaction = TransactionBuilder.fromXDR(dto.signedXdr, this.networkPassphrase); } catch { throw new BadRequestException('Invalid signed transaction XDR'); } + if (!('signatures' in transaction) || transaction.signatures.length === 0) throw new BadRequestException('Transaction has no signatures'); + const request = dto.idempotencyKey ? await this.findSigningRequest(dto.idempotencyKey) : undefined; + if (request) { + try { assertMatchingSignedTransaction(request.unsignedXdr, dto.signedXdr, this.networkPassphrase); } + catch (error) { throw new BadRequestException(error instanceof Error ? error.message : 'Signed transaction mismatch'); } + if (['submitted', 'pending', 'success'].includes(request.status)) return this.presentSigningRequest(request); + } + try { + if (dto.kind === 'classic') { + const result = await this.horizon.submitTransaction(transaction as any); + if (request) Object.assign(request, { status: 'success', hash: result.hash, error: undefined }); + if (dto.idempotencyKey) await this.persistRequestUpdate(dto.idempotencyKey, 'success', result.hash); + return { kind: dto.kind, status: 'success', hash: result.hash, ledger: result.ledger, explorerUrl: `https://stellar.expert/explorer/testnet/tx/${result.hash}` }; + } + const result = await this.rpc.sendTransaction(transaction as any); + if (request) Object.assign(request, { status: result.status === 'PENDING' ? 'pending' : 'submitted', hash: result.hash, error: undefined }); + if (dto.idempotencyKey) await this.persistRequestUpdate(dto.idempotencyKey, result.status === 'PENDING' ? 'pending' : 'submitted', result.hash); + return { kind: dto.kind, status: result.status.toLowerCase(), hash: result.hash, latestLedger: result.latestLedger, explorerUrl: `https://stellar.expert/explorer/testnet/tx/${result.hash}` }; + } catch (error) { + if (request) { + request.status = 'failed'; + request.error = error instanceof Error ? error.message : 'network error'; + await this.persistRequestUpdate(request.idempotencyKey, 'failed', request.hash, request.error); + } + throw new ServiceUnavailableException(`Transaction submission failed: ${error instanceof Error ? error.message : 'network error'}`); + } + } + + async receiveSep7Callback(idempotencyKey: string, signedXdr: string) { + const request = await this.findSigningRequest(idempotencyKey); + if (!request) throw new BadRequestException('Unknown or expired signing request'); + try { assertMatchingSignedTransaction(request.unsignedXdr, signedXdr, this.networkPassphrase); } + catch (error) { throw new BadRequestException(error instanceof Error ? error.message : 'Signed transaction mismatch'); } + return this.submitTransaction({ signedXdr, kind: request.kind, idempotencyKey }); + } + + async getSigningRequest(idempotencyKey: string) { + const request = await this.findSigningRequest(idempotencyKey); + if (!request) throw new BadRequestException('Signing request not found'); + await this.reconcileSigningRequest(request); + return this.presentSigningRequest(request); + } + + async getTransaction(hash: string, kind: 'classic' | 'soroban') { + try { + if (kind === 'classic') { + const result = await this.horizon.transactions().transaction(hash).call(); + return { kind, hash, status: result.successful ? 'success' : 'failed', ledger: result.ledger, explorerUrl: `https://stellar.expert/explorer/testnet/tx/${hash}` }; + } + const result = await this.rpc.getTransaction(hash); + return { kind, hash, status: result.status.toLowerCase(), latestLedger: result.latestLedger, explorerUrl: `https://stellar.expert/explorer/testnet/tx/${hash}` }; + } catch (error) { + throw new ServiceUnavailableException(`Unable to reconcile transaction: ${error instanceof Error ? error.message : 'network error'}`); + } + } + + async listVaultGoals(owner: string) { + this.assertAccount(owner); + try { + const response = await this.rpc.queryContract(this.requireVaultContract(), 'list_goals', { owner }, this.networkPassphrase); + const goals = (response.result ?? []).map((raw) => this.presentGoal(raw)); + const eventPage = await this.getVaultEvents({ limit: 100 }); + const goalIds = new Set(goals.map((goal) => goal.id)); + const events = eventPage.events + .map((event) => ({ + ...event, + type: String(event.topics[0] ?? 'contract_event'), + goalId: event.topics.length > 1 ? String(event.topics[1]) : null, + explorerUrl: `https://stellar.expert/explorer/testnet/tx/${event.txHash}`, + })) + .filter((event) => event.goalId && goalIds.has(event.goalId)); + return { owner, goals, events, ledgerVerified: response.isReadCall, contractId: this.vaultContractId }; + } catch (error) { + throw new ServiceUnavailableException(`Unable to query vault goals: ${error instanceof Error ? error.message : 'RPC error'}`); + } + } + + private presentGoal(raw: unknown) { + const goal = raw as Record; + const stringValue = (value: unknown) => { + if (value === null || value === undefined) return null; + if (typeof value === 'string') return value; + const rendered = String(value); + return rendered === '[object Object]' ? JSON.stringify(jsonSafe(value)) : rendered; + }; + const rawStatus = goal.status as { tag?: unknown } | string | undefined; + const status = typeof rawStatus === 'string' ? rawStatus : stringValue(rawStatus?.tag) ?? 'Unknown'; + return { + id: stringValue(goal.id) ?? '0', + owner: stringValue(goal.owner) ?? '', + asset: stringValue(goal.asset) ?? '', + targetAmount: stringValue(goal.target_amount ?? goal.targetAmount) ?? '0', + targetDate: stringValue(goal.target_date ?? goal.targetDate), + balance: stringValue(goal.balance) ?? '0', + status, + }; + } + + async getVaultEvents(query: StellarEventsQueryDto) { + const contractId = this.requireVaultContract(); + try { + const request: rpc.Api.GetEventsRequest = query.cursor + ? { filters: [{ type: 'contract', contractIds: [contractId] }], cursor: query.cursor, limit: query.limit ?? 50 } + : { filters: [{ type: 'contract', contractIds: [contractId] }], startLedger: query.startLedger ?? Math.max((await this.rpc.getLatestLedger()).sequence - 10_000, 1), limit: query.limit ?? 50 }; + const response = await this.rpc.getEvents(request); + const events = response.events.map((event) => ({ id: event.id, ledger: event.ledger, ledgerClosedAt: event.ledgerClosedAt, txHash: event.txHash, contractId: event.contractId?.toString() ?? contractId, topics: event.topic.map((topic) => jsonSafe(scValToNative(topic))), value: jsonSafe(scValToNative(event.value)), successful: event.inSuccessfulContractCall })); + if (events.length) void this.eventModel.bulkWrite(events.map((event) => ({ updateOne: { filter: { eventId: event.id }, update: { $set: { eventId: event.id, contractId: event.contractId, ledger: event.ledger, transactionHash: event.txHash, ledgerClosedAt: event.ledgerClosedAt, topics: event.topics, value: event.value, successful: event.successful } }, upsert: true } }))).catch(() => undefined); + return { cursor: response.cursor, events }; + } catch (error) { + throw new ServiceUnavailableException(`Unable to fetch vault events: ${error instanceof Error ? error.message : 'RPC error'}`); + } + } + + private vaultArguments(dto: PrepareVaultInvocationDto) { + const id = () => { if (!dto.goalId) throw new BadRequestException('goalId is required'); return nativeToScVal(BigInt(dto.goalId), { type: 'u128' }); }; + const amount = (value = dto.amount) => { if (!value || BigInt(value) <= 0n) throw new BadRequestException('A positive amount is required'); return nativeToScVal(BigInt(value), { type: 'i128' }); }; + if (dto.action === 'create_goal') { + const owner = dto.owner ?? dto.source; this.assertAccount(owner); + const assetContractId = dto.assetContractId || this.xlmSacId; + if (!StrKey.isValidContract(assetContractId)) throw new BadRequestException('A valid SAC assetContractId is required'); + return [new Address(owner).toScVal(), new Address(assetContractId).toScVal(), amount(dto.targetAmount), dto.targetDate ? nativeToScVal(BigInt(dto.targetDate), { type: 'u64' }) : nativeToScVal(null)]; + } + if (dto.action === 'contribute') { const contributor = dto.contributor ?? dto.source; this.assertAccount(contributor); return [id(), new Address(contributor).toScVal(), amount()]; } + if (dto.action === 'withdraw') return [id(), amount()]; + return [id()]; + } + + private async recordSigningRequest( + idempotencyKey: string, + kind: SigningRequest['kind'], + action: string, + source: string, + unsignedXdr: string, + fee = BASE_FEE, + ) { + const request: SigningRequest = { + idempotencyKey, + kind, + action, + source, + unsignedXdr, + status: 'prepared', + hash: transactionHash(unsignedXdr, this.networkPassphrase), + fee: String(fee), + createdAt: new Date().toISOString(), + }; + this.signingRequests.set(idempotencyKey, request); + await this.signingRequestModel.updateOne({ idempotencyKey }, { $set: request }, { upsert: true }); + return this.presentSigningRequest(request); + } + + private presentSigningRequest(request: SigningRequest) { + const callbackUrl = this.callbackBaseUrl + ? `${this.callbackBaseUrl}/stellar/signing-requests/${encodeURIComponent(request.idempotencyKey)}/callback` + : undefined; + return { + ...request, + network: 'testnet', + networkPassphrase: this.networkPassphrase, + callbackUrl: callbackUrl ?? null, + explorerUrl: `https://stellar.expert/explorer/testnet/tx/${request.hash}`, + signingUrl: buildSep7SigningUrl({ + xdr: request.unsignedXdr, + source: request.source, + action: request.action, + callbackUrl, + originDomain: this.originDomain, + signer: this.integritySigner, + }), + }; + } + + private async findSigningRequest(idempotencyKey: string): Promise { + const cached = this.signingRequests.get(idempotencyKey); + if (cached) return cached; + const persisted = await this.signingRequestModel.findOne({ idempotencyKey }).lean().exec(); + if (!persisted?.hash || !persisted.source) return undefined; + const request: SigningRequest = { + idempotencyKey: persisted.idempotencyKey, + kind: persisted.kind as SigningRequest['kind'], + action: persisted.action, + source: persisted.source, + unsignedXdr: persisted.unsignedXdr, + status: persisted.status as SigningRequest['status'], + hash: persisted.hash, + fee: persisted.fee, + error: persisted.error, + createdAt: ((persisted as unknown as { createdAt?: Date }).createdAt ?? new Date()).toISOString(), + }; + this.signingRequests.set(idempotencyKey, request); + return request; + } + + private async reconcileSigningRequest(request: SigningRequest): Promise { + if (request.status === 'success') return; + try { + if (request.kind === 'classic') { + const result = await this.horizon.transactions().transaction(request.hash).call(); + request.status = result.successful ? 'success' : 'failed'; + request.error = result.successful ? undefined : 'Transaction failed on Stellar Testnet'; + } else { + const result = await this.rpc.getTransaction(request.hash); + if (result.status === 'SUCCESS') { request.status = 'success'; request.error = undefined; } + else if (result.status === 'FAILED') { request.status = 'failed'; request.error = 'Soroban transaction failed on Stellar Testnet'; } + else if (result.status === 'NOT_FOUND' && Date.now() - Date.parse(request.createdAt) > 180_000) { + request.status = 'failed'; request.error = 'Wallet approval expired. Prepare a fresh request and retry.'; + } + } + } catch (error) { + const status = (error as { response?: { status?: number } }).response?.status; + if (status !== 404) return; + if (Date.now() - Date.parse(request.createdAt) > 180_000) { + request.status = 'failed'; request.error = 'Wallet approval expired. Prepare a fresh request and retry.'; + } + } + await this.persistRequestUpdate(request.idempotencyKey, request.status, request.hash, request.error); + } + + private assertAccount(address: string) { + if (!StrKey.isValidEd25519PublicKey(address)) throw new BadRequestException('Invalid Stellar G-address'); + } + + private requireVaultContract() { + if (!this.vaultContractId || !StrKey.isValidContract(this.vaultContractId)) throw new ConflictException('STELLAR_VAULT_CONTRACT_ID is not configured'); + return this.vaultContractId; + } + + private async persistRequestUpdate(idempotencyKey: string, status: SigningRequest['status'], hash: string, error?: string) { + await this.signingRequestModel.updateOne( + { idempotencyKey }, + { $set: { status, hash, error: error ?? null } }, + ).catch(() => undefined); + } +} diff --git a/backend/test/stellar.sep7.test.cjs b/backend/test/stellar.sep7.test.cjs new file mode 100644 index 0000000..ea5bb27 --- /dev/null +++ b/backend/test/stellar.sep7.test.cjs @@ -0,0 +1,73 @@ +const assert = require('node:assert/strict'); +const test = require('node:test'); + +const { Account, Keypair, Networks, Operation, TransactionBuilder } = require('@stellar/stellar-sdk'); +const { + assertMatchingSignedTransaction, + buildSep7SigningUrl, + signSep7Uri, + transactionHash, +} = require('../dist/stellar/stellar.sep7'); + +function transaction(keypair, sequence, value) { + return new TransactionBuilder(new Account(keypair.publicKey(), sequence), { + fee: '100', + networkPassphrase: Networks.TESTNET, + }) + .addOperation(Operation.manageData({ name: 'save-test', value })) + .setTimeout(60) + .build(); +} + +test('accepts signatures only for the prepared transaction body', () => { + const signer = Keypair.random(); + const prepared = transaction(signer, '1', 'expected'); + const signed = TransactionBuilder.fromXDR(prepared.toXDR(), Networks.TESTNET); + signed.sign(signer); + + assert.doesNotThrow(() => assertMatchingSignedTransaction(prepared.toXDR(), signed.toXDR(), Networks.TESTNET)); + assert.equal(transactionHash(prepared.toXDR(), Networks.TESTNET), transactionHash(signed.toXDR(), Networks.TESTNET)); + + const substituted = transaction(signer, '2', 'different'); + substituted.sign(signer); + assert.throws( + () => assertMatchingSignedTransaction(prepared.toXDR(), substituted.toXDR(), Networks.TESTNET), + /does not match/, + ); +}); + +test('builds a callback-enabled SEP-7 request for the intended signer', () => { + const source = Keypair.random(); + const prepared = transaction(source, '1', 'callback'); + const url = buildSep7SigningUrl({ + xdr: prepared.toXDR(), + source: source.publicKey(), + action: 'contribute', + callbackUrl: 'https://save.example/stellar/callback/request-1', + }); + + assert.match(url, /^web\+stellar:tx\?/); + assert.match(url, new RegExp(`pubkey=${source.publicKey()}`)); + assert.match(url, /callback=url%3Ahttps%3A%2F%2Fsave\.example/); + assert.doesNotMatch(url, /signature=/); +}); + +test('signs SEP-7 origin requests with the dedicated integrity key', () => { + const user = Keypair.random(); + const integritySigner = Keypair.random(); + const prepared = transaction(user, '1', 'signed-request'); + const url = buildSep7SigningUrl({ + xdr: prepared.toXDR(), + source: user.publicKey(), + action: 'create_goal', + originDomain: 'save.example', + signer: integritySigner, + }); + const [unsignedUri, encodedSignature] = url.split('&signature='); + const signature = Buffer.from(decodeURIComponent(encodedSignature), 'base64'); + const envelopeType = Buffer.alloc(36); envelopeType[35] = 4; + const payload = Buffer.concat([envelopeType, Buffer.from(`stellar.sep.7 - URI Scheme${unsignedUri}`)]); + + assert.equal(signSep7Uri(unsignedUri, integritySigner), signature.toString('base64')); + assert.equal(integritySigner.verify(payload, signature), true); +}); diff --git a/backend/tsconfig.build.json b/backend/tsconfig.build.json new file mode 100644 index 0000000..038209f --- /dev/null +++ b/backend/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "incremental": false + }, + "exclude": ["node_modules", "dist", "test", "**/*.spec.ts"] +} diff --git a/contract/.gitignore b/contract/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/contract/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/contract/Cargo.lock b/contract/Cargo.lock new file mode 100644 index 0000000..ea2e04e --- /dev/null +++ b/contract/Cargo.lock @@ -0,0 +1,2121 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "ark-bls12-381" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df4dcc01ff89867cd86b0da835f23c3f02738353aaee7dde7495af71363b8d5" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools", + "num-bigint", + "num-integer", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools", + "num-bigint", + "num-traits", + "paste", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "arrayvec", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes-lit" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b04f2b1d34cb428043f14aa4c853d14294532e8bbde3b6a3bc2faaaae31a1dd" +dependencies = [ + "num-bigint", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "cc" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_eval" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + +[[package]] +name = "crate-git-revision" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c521bf1f43d31ed2f73441775ed31935d77901cb3451e44b38a1c1612fcbaf98" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "crate-git-revision" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54851b5b3f24621804b1cded2820975623c205e3055d2d44031cdb1237339ac8" +dependencies = [ + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "ctor" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2" + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto 0.2.9", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eed333089e2e1c1ac8c6c0398e5e2497b4c9926ca6d0365ed1e099afa5bc23" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "curve25519-dalek-derive", + "digest 0.11.3", + "fiat-crypto 0.3.0", + "rustc_version", + "subtle", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.119", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.119", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "darling_macro" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" +dependencies = [ + "darling_core 0.23.0", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "data-encoding" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" + +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.20", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "serde_core", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common 0.1.6", + "subtle", +] + +[[package]] +name = "digest" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +dependencies = [ + "block-buffer 0.12.1", + "crypto-common 0.2.2", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dtor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek 4.1.3", + "ed25519", + "rand_core", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "either" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "enum-ordinalize" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89dd01549b09589510cf0647475075d12071456586d70f5c75c98ae2a5537677" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65863d15a4ce2888bd2f0f543cc963d3879c3a022c8ee43f6141d479a3ac815" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "escape-bytes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bfcf67fea2815c2fc3b90873fae90957be12ff417335dfadc7f52927feb03b2" + +[[package]] +name = "ethnum" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40404c3f5f511ec4da6fe866ddf6a717c309fdbb69fbbad7b0f3edab8f2e835f" + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "fiat-crypto" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" + +[[package]] +name = "find-msvc-tools" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hybrid-array" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +dependencies = [ + "typenum", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "indexmap-nostd" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jiff" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668b7183bd07af9a4885f5c35b0cc5c83c4607a913c16b7e17291832910d2dcc" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "windows-link", +] + +[[package]] +name = "jiff-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7feca88439efe53da3754500c1851dedf3cb36c524dd5cf8225cc0794de95d09" +dependencies = [ + "defmt", +] + +[[package]] +name = "jiff-static" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a69dcb3a21cfb32ce1cd056169337ca284af0766dd766e7878819b251a49204" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + +[[package]] +name = "js-sys" +version = "0.3.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "sha2", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures 0.2.17", +] + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.119", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ref-cast" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "save-savings-vault" +version = "0.1.0" +dependencies = [ + "soroban-sdk", +] + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687274d293b6cdc6e73e0fee520bf2049650090d7164f87672d212a3c530cf4a" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_with" +version = "3.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee78f1fbe43ac4a0e47aadb3dbd357b69eb0d3793e948624cd03dd2750ab1c0a" +dependencies = [ + "base64", + "bs58", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.14.1", + "jiff", + "schemars 0.8.22", + "schemars 0.9.0", + "schemars 1.2.2", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8705578779c2b6bd90d84d66eb2e206b708b1a4d7b9f17641b293545bf1c7e46" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77fd7028345d415a4034cf8777cd4f8ab1851274233b45f84e3d955502d93874" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "soroban-builtin-sdk-macros" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b77bc93d930032c487cb1506b6ed166b2af49db76d52678ec4887ac621ecce01" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "soroban-env-common" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b22e9981cdd444f3aa6734bc58d76195bf7eca3ccf1dd432b875af5d02da068" +dependencies = [ + "arbitrary", + "crate-git-revision 0.0.6", + "ethnum", + "num-derive", + "num-traits", + "serde", + "soroban-env-macros", + "soroban-wasmi", + "static_assertions", + "stellar-xdr", + "wasmparser", +] + +[[package]] +name = "soroban-env-guest" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b6072f99ca6bf8e8d5b04e05d083dac785e5357d9c0f36a6658f819c2fd7d67" +dependencies = [ + "soroban-env-common", + "static_assertions", +] + +[[package]] +name = "soroban-env-host" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c06afd7c75ce150ce53e4d77a77645b18e3fb61856a0ddc42bfcecdc39fa3b9" +dependencies = [ + "ark-bls12-381", + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "curve25519-dalek 5.0.0", + "ecdsa", + "ed25519-dalek", + "elliptic-curve", + "generic-array", + "getrandom", + "hex-literal", + "hmac", + "k256", + "num-derive", + "num-integer", + "num-traits", + "p256", + "rand", + "rand_chacha", + "sec1", + "sha2", + "sha3", + "soroban-builtin-sdk-macros", + "soroban-env-common", + "soroban-wasmi", + "static_assertions", + "stellar-strkey 0.0.13", + "wasmparser", +] + +[[package]] +name = "soroban-env-macros" +version = "27.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647811bdd28a3ec40296987f6635781e5e1141c8f5affbbd53ba12b6295b7bb6" +dependencies = [ + "itertools", + "proc-macro2", + "quote", + "serde", + "serde_json", + "stellar-xdr", + "syn 2.0.119", +] + +[[package]] +name = "soroban-ledger-snapshot" +version = "27.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b59883d8bd0d1aed8d57579a9974ab88eaf787dd0a1af104f6881b5707450558" +dependencies = [ + "serde", + "serde_json", + "serde_with", + "soroban-env-common", + "soroban-env-host", + "thiserror 1.0.69", +] + +[[package]] +name = "soroban-sdk" +version = "27.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c3f21971c84fcfb08957e3e8f5a9a70f134cb07ad9ee053ac7e6d7a887a82af" +dependencies = [ + "arbitrary", + "bytes-lit", + "crate-git-revision 0.0.9", + "ctor", + "derive_arbitrary", + "ed25519-dalek", + "rand", + "rustc_version", + "serde", + "serde_json", + "soroban-env-guest", + "soroban-env-host", + "soroban-ledger-snapshot", + "soroban-sdk-macros", + "stellar-strkey 0.0.16", + "visibility", +] + +[[package]] +name = "soroban-sdk-macros" +version = "27.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bd4a847273d749807fe2eb52e2b9c1917ee482cd6a39465cad5c389548996ad" +dependencies = [ + "darling 0.20.11", + "heck", + "itertools", + "macro-string", + "proc-macro2", + "quote", + "sha2", + "soroban-env-common", + "soroban-spec", + "soroban-spec-rust", + "stellar-xdr", + "syn 2.0.119", +] + +[[package]] +name = "soroban-spec" +version = "27.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473404322827b285cbcd87517f365986bd63af7842c78b2a86ee061715fda61e" +dependencies = [ + "base64", + "sha2", + "stellar-xdr", + "thiserror 1.0.69", + "wasmparser", +] + +[[package]] +name = "soroban-spec-rust" +version = "27.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f25698b6ce2125850a9ef075cf9ba1e8d25b4cfa0c46aca42dadd80cc29d881" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "sha2", + "soroban-spec", + "stellar-xdr", + "syn 2.0.119", + "thiserror 1.0.69", +] + +[[package]] +name = "soroban-wasmi" +version = "0.31.1-soroban.20.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710403de32d0e0c35375518cb995d4fc056d0d48966f2e56ea471b8cb8fc9719" +dependencies = [ + "smallvec", + "spin", + "wasmi_arena", + "wasmi_core", + "wasmparser-nostd", +] + +[[package]] +name = "spin" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stellar-strkey" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee1832fb50c651ad10f734aaf5d31ca5acdfb197a6ecda64d93fcdb8885af913" +dependencies = [ + "crate-git-revision 0.0.6", + "data-encoding", +] + +[[package]] +name = "stellar-strkey" +version = "0.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084afcb0d458c3d5d5baa2d294b18f881e62cc258ef539d8fdf68be7dbe45520" +dependencies = [ + "crate-git-revision 0.0.6", + "data-encoding", + "heapless", +] + +[[package]] +name = "stellar-xdr" +version = "27.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ff843326969bdf1ef673dcdba94c08f4a3c8f1e58d6e6ef39b1bd4f749179a" +dependencies = [ + "arbitrary", + "base64", + "cfg_eval", + "crate-git-revision 0.0.6", + "escape-bytes", + "ethnum", + "hex", + "serde", + "serde_with", + "sha2", + "stellar-strkey 0.0.13", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6275cddf4610d1775e6d1fe9469b2e77d0f39fd98fb7450901b821e0c53649f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl 2.0.20", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.4", +] + +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "time-macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "visibility" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d674d135b4a8c1d7e813e2f8d1c9a58308aee4a680323066025e53132218bd91" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.119", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasmi_arena" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" + +[[package]] +name = "wasmi_core" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf1a7db34bff95b85c261002720c00c3a6168256dcb93041d3fa2054d19856a" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + +[[package]] +name = "wasmparser" +version = "0.116.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50" +dependencies = [ + "indexmap 2.14.1", + "semver", +] + +[[package]] +name = "wasmparser-nostd" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a015fe95f3504a94bb1462c717aae75253e39b9dd6c3fb1062c934535c64aa" +dependencies = [ + "indexmap-nostd", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "zerocopy" +version = "0.8.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/contract/Cargo.toml b/contract/Cargo.toml new file mode 100644 index 0000000..99f1b4d --- /dev/null +++ b/contract/Cargo.toml @@ -0,0 +1,21 @@ +[workspace] +resolver = "2" +members = ["savings-vault"] + +[workspace.dependencies] +soroban-sdk = "=27.0.6" + +[profile.release] +opt-level = "z" +overflow-checks = true +debug = 0 +strip = "symbols" +debug-assertions = false +panic = "abort" +codegen-units = 1 +lto = true + +[profile.release-with-logs] +inherits = "release" +debug-assertions = true + diff --git a/contract/rust-toolchain.toml b/contract/rust-toolchain.toml new file mode 100644 index 0000000..349d83f --- /dev/null +++ b/contract/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "stable" +targets = ["wasm32v1-none"] +profile = "minimal" diff --git a/contract/savings-vault/Cargo.toml b/contract/savings-vault/Cargo.toml new file mode 100644 index 0000000..e9a6fcf --- /dev/null +++ b/contract/savings-vault/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "save-savings-vault" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +soroban-sdk = { workspace = true } + +[dev-dependencies] +soroban-sdk = { workspace = true, features = ["testutils"] } + diff --git a/contract/savings-vault/src/lib.rs b/contract/savings-vault/src/lib.rs new file mode 100644 index 0000000..7b89c82 --- /dev/null +++ b/contract/savings-vault/src/lib.rs @@ -0,0 +1,325 @@ +#![no_std] + +use soroban_sdk::{ + contract, contracterror, contractevent, contractimpl, contracttype, token, Address, Env, Vec, +}; + +const DAY_IN_LEDGERS: u32 = 17_280; +const PERSISTENT_LIFETIME: u32 = 365 * DAY_IN_LEDGERS; +const PERSISTENT_THRESHOLD: u32 = 30 * DAY_IN_LEDGERS; +const INSTANCE_LIFETIME: u32 = 30 * DAY_IN_LEDGERS; +const INSTANCE_THRESHOLD: u32 = 7 * DAY_IN_LEDGERS; + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum GoalStatus { + Active, + Completed, + Cancelled, +} + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct Goal { + pub id: u128, + pub owner: Address, + pub asset: Address, + pub target_amount: i128, + pub target_date: Option, + pub balance: i128, + pub status: GoalStatus, +} + +#[contractevent] +pub struct GoalCreated { + #[topic] + pub goal_id: u128, + #[topic] + pub owner: Address, + pub asset: Address, + pub target_amount: i128, + pub target_date: Option, +} + +#[contractevent] +pub struct Contribution { + #[topic] + pub goal_id: u128, + #[topic] + pub contributor: Address, + pub amount: i128, + pub balance: i128, +} + +#[contractevent] +pub struct GoalCompleted { + #[topic] + pub goal_id: u128, + pub balance: i128, +} + +#[contractevent] +pub struct Withdrawal { + #[topic] + pub goal_id: u128, + #[topic] + pub owner: Address, + pub amount: i128, + pub balance: i128, +} + +#[contractevent] +pub struct GoalCancelled { + #[topic] + pub goal_id: u128, + #[topic] + pub owner: Address, + pub refunded: i128, +} + +#[contracttype] +enum DataKey { + Counter, + Goal(u128), + OwnerGoals(Address), +} + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[repr(u32)] +pub enum VaultError { + GoalNotFound = 1, + InvalidAmount = 2, + InvalidTargetDate = 3, + GoalNotActive = 4, + GoalNotCompleted = 5, + CompletionConditionsNotMet = 6, + InsufficientBalance = 7, + ArithmeticOverflow = 8, +} + +#[contract] +pub struct SavingsVault; + +#[contractimpl] +impl SavingsVault { + pub fn create_goal( + env: Env, + owner: Address, + asset: Address, + target_amount: i128, + target_date: Option, + ) -> Result { + owner.require_auth(); + if target_amount <= 0 { + return Err(VaultError::InvalidAmount); + } + if target_date.is_some_and(|deadline| deadline <= env.ledger().timestamp()) { + return Err(VaultError::InvalidTargetDate); + } + + bump_instance(&env); + let id = env + .storage() + .instance() + .get::<_, u128>(&DataKey::Counter) + .unwrap_or(0) + .checked_add(1) + .ok_or(VaultError::ArithmeticOverflow)?; + env.storage().instance().set(&DataKey::Counter, &id); + + let goal = Goal { + id, + owner: owner.clone(), + asset: asset.clone(), + target_amount, + target_date, + balance: 0, + status: GoalStatus::Active, + }; + write_goal(&env, &goal); + + let owner_key = DataKey::OwnerGoals(owner.clone()); + let mut ids = env + .storage() + .persistent() + .get::<_, Vec>(&owner_key) + .unwrap_or(Vec::new(&env)); + ids.push_back(id); + env.storage().persistent().set(&owner_key, &ids); + bump_persistent(&env, &owner_key); + GoalCreated { + goal_id: id, + owner, + asset, + target_amount, + target_date, + } + .publish(&env); + Ok(id) + } + + pub fn contribute( + env: Env, + goal_id: u128, + contributor: Address, + amount: i128, + ) -> Result { + contributor.require_auth(); + if amount <= 0 { + return Err(VaultError::InvalidAmount); + } + let mut goal = read_goal(&env, goal_id)?; + if goal.status != GoalStatus::Active { + return Err(VaultError::GoalNotActive); + } + let next_balance = goal + .balance + .checked_add(amount) + .ok_or(VaultError::ArithmeticOverflow)?; + token::Client::new(&env, &goal.asset).transfer( + &contributor, + env.current_contract_address(), + &amount, + ); + goal.balance = next_balance; + write_goal(&env, &goal); + Contribution { + goal_id, + contributor, + amount, + balance: next_balance, + } + .publish(&env); + Ok(goal) + } + + pub fn complete_goal(env: Env, goal_id: u128) -> Result { + let mut goal = read_goal(&env, goal_id)?; + if goal.status != GoalStatus::Active { + return Err(VaultError::GoalNotActive); + } + let target_reached = goal.balance >= goal.target_amount; + let deadline_reached = goal + .target_date + .is_some_and(|deadline| env.ledger().timestamp() >= deadline); + if !target_reached && !deadline_reached { + return Err(VaultError::CompletionConditionsNotMet); + } + goal.status = GoalStatus::Completed; + write_goal(&env, &goal); + GoalCompleted { + goal_id, + balance: goal.balance, + } + .publish(&env); + Ok(goal) + } + + pub fn withdraw(env: Env, goal_id: u128, amount: i128) -> Result { + if amount <= 0 { + return Err(VaultError::InvalidAmount); + } + let mut goal = read_goal(&env, goal_id)?; + goal.owner.require_auth(); + if goal.status != GoalStatus::Completed { + return Err(VaultError::GoalNotCompleted); + } + if amount > goal.balance { + return Err(VaultError::InsufficientBalance); + } + token::Client::new(&env, &goal.asset).transfer( + &env.current_contract_address(), + &goal.owner, + &amount, + ); + goal.balance -= amount; + write_goal(&env, &goal); + Withdrawal { + goal_id, + owner: goal.owner.clone(), + amount, + balance: goal.balance, + } + .publish(&env); + Ok(goal) + } + + pub fn cancel_goal(env: Env, goal_id: u128) -> Result { + let mut goal = read_goal(&env, goal_id)?; + goal.owner.require_auth(); + if goal.status != GoalStatus::Active { + return Err(VaultError::GoalNotActive); + } + let refund = goal.balance; + if refund > 0 { + token::Client::new(&env, &goal.asset).transfer( + &env.current_contract_address(), + &goal.owner, + &refund, + ); + goal.balance = 0; + } + goal.status = GoalStatus::Cancelled; + write_goal(&env, &goal); + GoalCancelled { + goal_id, + owner: goal.owner.clone(), + refunded: refund, + } + .publish(&env); + Ok(goal) + } + + pub fn get_goal(env: Env, goal_id: u128) -> Result { + read_goal(&env, goal_id) + } + + pub fn list_goals(env: Env, owner: Address) -> Vec { + let key = DataKey::OwnerGoals(owner); + let Some(ids) = env.storage().persistent().get::<_, Vec>(&key) else { + return Vec::new(&env); + }; + bump_persistent(&env, &key); + let mut goals = Vec::new(&env); + for id in ids.iter() { + if let Ok(goal) = read_goal(&env, id) { + goals.push_back(goal); + } + } + goals + } +} + +fn read_goal(env: &Env, id: u128) -> Result { + let key = DataKey::Goal(id); + let goal = env + .storage() + .persistent() + .get(&key) + .ok_or(VaultError::GoalNotFound)?; + bump_persistent(env, &key); + Ok(goal) +} + +fn write_goal(env: &Env, goal: &Goal) { + let key = DataKey::Goal(goal.id); + env.storage().persistent().set(&key, goal); + bump_persistent(env, &key); + bump_instance(env); +} + +fn bump_persistent(env: &Env, key: &DataKey) { + env.storage() + .persistent() + .extend_ttl(key, PERSISTENT_THRESHOLD, PERSISTENT_LIFETIME); +} + +fn bump_instance(env: &Env) { + env.storage() + .instance() + .extend_ttl(INSTANCE_THRESHOLD, INSTANCE_LIFETIME); +} + +#[cfg(test)] +mod test; diff --git a/contract/savings-vault/src/test.rs b/contract/savings-vault/src/test.rs new file mode 100644 index 0000000..6d98f67 --- /dev/null +++ b/contract/savings-vault/src/test.rs @@ -0,0 +1,133 @@ +extern crate std; + +use super::*; +use soroban_sdk::{ + testutils::{Address as _, Ledger}, + token, Address, Env, +}; + +struct Fixture { + env: Env, + client: SavingsVaultClient<'static>, + owner: Address, + contributor: Address, + token: token::Client<'static>, +} + +fn fixture() -> Fixture { + let env = Env::default(); + env.mock_all_auths(); + env.ledger().set_timestamp(1_800_000_000); + let owner = Address::generate(&env); + let contributor = Address::generate(&env); + let admin = Address::generate(&env); + let asset = env + .register_stellar_asset_contract_v2(admin.clone()) + .address(); + let contract = env.register(SavingsVault, ()); + let client = SavingsVaultClient::new(&env, &contract); + let token = token::Client::new(&env, &asset); + let token_admin = token::StellarAssetClient::new(&env, &asset); + token_admin.mint(&contributor, &100_000); + Fixture { + env, + client, + owner, + contributor, + token, + } +} + +#[test] +fn create_and_list_goal() { + let f = fixture(); + let id = f + .client + .create_goal(&f.owner, &f.token.address, &10_000, &Some(1_900_000_000)); + assert_eq!(id, 1); + let goal = f.client.get_goal(&id); + assert_eq!(goal.owner, f.owner); + assert_eq!(goal.balance, 0); + assert_eq!(goal.status, GoalStatus::Active); + assert_eq!(f.client.list_goals(&goal.owner).len(), 1); +} + +#[test] +fn new_owner_has_an_empty_goal_list() { + let f = fixture(); + assert!(f.client.list_goals(&f.owner).is_empty()); +} + +#[test] +fn contribution_transfers_tokens_and_reaches_target() { + let f = fixture(); + let id = f + .client + .create_goal(&f.owner, &f.token.address, &10_000, &None); + let goal = f.client.contribute(&id, &f.contributor, &10_000); + assert_eq!(goal.balance, 10_000); + assert_eq!(f.token.balance(&f.contributor), 90_000); + assert_eq!(f.token.balance(&f.client.address), 10_000); + assert_eq!(f.client.complete_goal(&id).status, GoalStatus::Completed); + assert_eq!( + f.client.try_complete_goal(&id), + Err(Ok(VaultError::GoalNotActive)) + ); +} + +#[test] +fn deadline_can_complete_and_owner_can_withdraw() { + let f = fixture(); + let id = f + .client + .create_goal(&f.owner, &f.token.address, &50_000, &Some(1_800_000_100)); + f.client.contribute(&id, &f.contributor, &8_000); + f.env.ledger().set_timestamp(1_800_000_101); + f.client.complete_goal(&id); + let goal = f.client.withdraw(&id, &3_000); + assert_eq!(goal.balance, 5_000); + assert_eq!(f.token.balance(&f.owner), 3_000); +} + +#[test] +fn cancellation_refunds_balance() { + let f = fixture(); + let id = f + .client + .create_goal(&f.owner, &f.token.address, &50_000, &None); + f.client.contribute(&id, &f.contributor, &7_500); + let goal = f.client.cancel_goal(&id); + assert_eq!(goal.status, GoalStatus::Cancelled); + assert_eq!(goal.balance, 0); + assert_eq!(f.token.balance(&f.owner), 7_500); + assert_eq!( + f.client.try_cancel_goal(&id), + Err(Ok(VaultError::GoalNotActive)) + ); +} + +#[test] +fn rejects_invalid_lifecycle_actions() { + let f = fixture(); + assert_eq!( + f.client + .try_create_goal(&f.owner, &f.token.address, &0, &None), + Err(Ok(VaultError::InvalidAmount)) + ); + let id = f + .client + .create_goal(&f.owner, &f.token.address, &10_000, &None); + assert_eq!( + f.client.try_complete_goal(&id), + Err(Ok(VaultError::CompletionConditionsNotMet)) + ); + assert_eq!( + f.client.try_withdraw(&id, &1), + Err(Ok(VaultError::GoalNotCompleted)) + ); + f.client.cancel_goal(&id); + assert_eq!( + f.client.try_contribute(&id, &f.contributor, &1), + Err(Ok(VaultError::GoalNotActive)) + ); +} diff --git a/contract/savings-vault/test_snapshots/test/cancellation_refunds_balance.1.json b/contract/savings-vault/test_snapshots/test/cancellation_refunds_balance.1.json new file mode 100644 index 0000000..e90a59d --- /dev/null +++ b/contract/savings-vault/test_snapshots/test/cancellation_refunds_balance.1.json @@ -0,0 +1,705 @@ +{ + "generators": { + "address": 5, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "100000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "create_goal", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + }, + { + "i128": "50000" + }, + "void" + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "contribute", + "args": [ + { + "u128": "1" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "7500" + } + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "i128": "7500" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "cancel_goal", + "args": [ + { + "u128": "1" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 1800000000, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "2032731177588607455" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "Goal" + }, + { + "u128": "1" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "asset" + }, + "val": { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + } + }, + { + "key": { + "symbol": "balance" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u128": "1" + } + }, + { + "key": { + "symbol": "owner" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Cancelled" + } + ] + } + }, + { + "key": { + "symbol": "target_amount" + }, + "val": { + "i128": "50000" + } + }, + { + "key": { + "symbol": "target_date" + }, + "val": "void" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "OwnerGoals" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "u128": "1" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Counter" + } + ] + }, + "val": { + "u128": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "7500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "92500" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 518400 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contract/savings-vault/test_snapshots/test/contribution_transfers_tokens_and_reaches_target.1.json b/contract/savings-vault/test_snapshots/test/contribution_transfers_tokens_and_reaches_target.1.json new file mode 100644 index 0000000..b7206be --- /dev/null +++ b/contract/savings-vault/test_snapshots/test/contribution_transfers_tokens_and_reaches_target.1.json @@ -0,0 +1,616 @@ +{ + "generators": { + "address": 5, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "100000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "create_goal", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + }, + { + "i128": "10000" + }, + "void" + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "contribute", + "args": [ + { + "u128": "1" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "10000" + } + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "i128": "10000" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [], + [], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 1800000000, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "Goal" + }, + { + "u128": "1" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "asset" + }, + "val": { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + } + }, + { + "key": { + "symbol": "balance" + }, + "val": { + "i128": "10000" + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u128": "1" + } + }, + { + "key": { + "symbol": "owner" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Completed" + } + ] + } + }, + { + "key": { + "symbol": "target_amount" + }, + "val": { + "i128": "10000" + } + }, + { + "key": { + "symbol": "target_date" + }, + "val": "void" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "OwnerGoals" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "u128": "1" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Counter" + } + ] + }, + "val": { + "u128": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "90000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "10000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 518400 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contract/savings-vault/test_snapshots/test/create_and_list_goal.1.json b/contract/savings-vault/test_snapshots/test/create_and_list_goal.1.json new file mode 100644 index 0000000..2bd933f --- /dev/null +++ b/contract/savings-vault/test_snapshots/test/create_and_list_goal.1.json @@ -0,0 +1,500 @@ +{ + "generators": { + "address": 5, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "100000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "create_goal", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + }, + { + "i128": "10000" + }, + { + "u64": "1900000000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 1800000000, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "Goal" + }, + { + "u128": "1" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "asset" + }, + "val": { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + } + }, + { + "key": { + "symbol": "balance" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u128": "1" + } + }, + { + "key": { + "symbol": "owner" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Active" + } + ] + } + }, + { + "key": { + "symbol": "target_amount" + }, + "val": { + "i128": "10000" + } + }, + { + "key": { + "symbol": "target_date" + }, + "val": { + "u64": "1900000000" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "OwnerGoals" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "u128": "1" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Counter" + } + ] + }, + "val": { + "u128": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "100000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 518400 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contract/savings-vault/test_snapshots/test/deadline_can_complete_and_owner_can_withdraw.1.json b/contract/savings-vault/test_snapshots/test/deadline_can_complete_and_owner_can_withdraw.1.json new file mode 100644 index 0000000..9c0053f --- /dev/null +++ b/contract/savings-vault/test_snapshots/test/deadline_can_complete_and_owner_can_withdraw.1.json @@ -0,0 +1,712 @@ +{ + "generators": { + "address": 5, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "100000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "create_goal", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + }, + { + "i128": "50000" + }, + { + "u64": "1800000100" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "contribute", + "args": [ + { + "u128": "1" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "8000" + } + ] + } + }, + "sub_invocations": [ + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "transfer", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + }, + { + "i128": "8000" + } + ] + } + }, + "sub_invocations": [] + } + ] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "withdraw", + "args": [ + { + "u128": "1" + }, + { + "i128": "3000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 1800000101, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "1033654523790656264" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "2032731177588607455" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "Goal" + }, + { + "u128": "1" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "asset" + }, + "val": { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + } + }, + { + "key": { + "symbol": "balance" + }, + "val": { + "i128": "5000" + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u128": "1" + } + }, + { + "key": { + "symbol": "owner" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Completed" + } + ] + } + }, + { + "key": { + "symbol": "target_amount" + }, + "val": { + "i128": "50000" + } + }, + { + "key": { + "symbol": "target_date" + }, + "val": { + "u64": "1800000100" + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "OwnerGoals" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "u128": "1" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Counter" + } + ] + }, + "val": { + "u128": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "3000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "92000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "5000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 518400 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contract/savings-vault/test_snapshots/test/new_owner_has_an_empty_goal_list.1.json b/contract/savings-vault/test_snapshots/test/new_owner_has_an_empty_goal_list.1.json new file mode 100644 index 0000000..f680362 --- /dev/null +++ b/contract/savings-vault/test_snapshots/test/new_owner_has_an_empty_goal_list.1.json @@ -0,0 +1,319 @@ +{ + "generators": { + "address": 5, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "100000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 1800000000, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": null + } + } + } + }, + "ext": "v0" + }, + "live_until": 4095 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "100000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 4095 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/contract/savings-vault/test_snapshots/test/rejects_invalid_lifecycle_actions.1.json b/contract/savings-vault/test_snapshots/test/rejects_invalid_lifecycle_actions.1.json new file mode 100644 index 0000000..a8341da --- /dev/null +++ b/contract/savings-vault/test_snapshots/test/rejects_invalid_lifecycle_actions.1.json @@ -0,0 +1,537 @@ +{ + "generators": { + "address": 5, + "nonce": 0, + "mux_id": 0 + }, + "auth": [ + [], + [ + [ + "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "set_admin", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + { + "function": { + "contract_fn": { + "contract_address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "function_name": "mint", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + }, + { + "i128": "100000" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "create_goal", + "args": [ + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + }, + { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + }, + { + "i128": "10000" + }, + "void" + ] + } + }, + "sub_invocations": [] + } + ] + ], + [], + [], + [ + [ + "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + { + "function": { + "contract_fn": { + "contract_address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "function_name": "cancel_goal", + "args": [ + { + "u128": "1" + } + ] + } + }, + "sub_invocations": [] + } + ] + ], + [] + ], + "ledger": { + "protocol_version": 27, + "sequence_number": 0, + "timestamp": 1800000000, + "network_id": "0000000000000000000000000000000000000000000000000000000000000000", + "base_reserve": 0, + "min_persistent_entry_ttl": 4096, + "min_temp_entry_ttl": 16, + "max_entry_ttl": 6312000, + "ledger_entries": [ + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "account": { + "account_id": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "balance": "0", + "seq_num": "0", + "num_sub_entries": 0, + "inflation_dest": null, + "flags": 0, + "home_domain": "", + "thresholds": "01010101", + "signers": [], + "ext": "v0" + } + }, + "ext": "v0" + }, + "live_until": null + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF", + "key": { + "ledger_key_nonce": { + "nonce": "801925984706572462" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "4270020994084947596" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM", + "key": { + "ledger_key_nonce": { + "nonce": "4837995959683129791" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M", + "key": { + "ledger_key_nonce": { + "nonce": "5541220902715666415" + } + }, + "durability": "temporary", + "val": "void" + } + }, + "ext": "v0" + }, + "live_until": 6311999 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "Goal" + }, + { + "u128": "1" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "asset" + }, + "val": { + "address": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN" + } + }, + { + "key": { + "symbol": "balance" + }, + "val": { + "i128": "0" + } + }, + { + "key": { + "symbol": "id" + }, + "val": { + "u128": "1" + } + }, + { + "key": { + "symbol": "owner" + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + }, + { + "key": { + "symbol": "status" + }, + "val": { + "vec": [ + { + "symbol": "Cancelled" + } + ] + } + }, + { + "key": { + "symbol": "target_amount" + }, + "val": { + "i128": "10000" + } + }, + { + "key": { + "symbol": "target_date" + }, + "val": "void" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": { + "vec": [ + { + "symbol": "OwnerGoals" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM" + } + ] + }, + "durability": "persistent", + "val": { + "vec": [ + { + "u128": "1" + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 6307200 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": { + "wasm": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + "storage": [ + { + "key": { + "vec": [ + { + "symbol": "Counter" + } + ] + }, + "val": { + "u128": "1" + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": { + "vec": [ + { + "symbol": "Balance" + }, + { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4" + } + ] + }, + "durability": "persistent", + "val": { + "map": [ + { + "key": { + "symbol": "amount" + }, + "val": { + "i128": "100000" + } + }, + { + "key": { + "symbol": "authorized" + }, + "val": { + "bool": true + } + }, + { + "key": { + "symbol": "clawback" + }, + "val": { + "bool": false + } + } + ] + } + } + }, + "ext": "v0" + }, + "live_until": 518400 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_data": { + "ext": "v0", + "contract": "CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN", + "key": "ledger_key_contract_instance", + "durability": "persistent", + "val": { + "contract_instance": { + "executable": "stellar_asset", + "storage": [ + { + "key": { + "symbol": "METADATA" + }, + "val": { + "map": [ + { + "key": { + "symbol": "decimal" + }, + "val": { + "u32": 7 + } + }, + { + "key": { + "symbol": "name" + }, + "val": { + "string": "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF" + } + }, + { + "key": { + "symbol": "symbol" + }, + "val": { + "string": "aaa" + } + } + ] + } + }, + { + "key": { + "vec": [ + { + "symbol": "Admin" + } + ] + }, + "val": { + "address": "CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M" + } + }, + { + "key": { + "vec": [ + { + "symbol": "AssetInfo" + } + ] + }, + "val": { + "vec": [ + { + "symbol": "AlphaNum4" + }, + { + "map": [ + { + "key": { + "symbol": "asset_code" + }, + "val": { + "string": "aaa\\0" + } + }, + { + "key": { + "symbol": "issuer" + }, + "val": { + "bytes": "0000000000000000000000000000000000000000000000000000000000000004" + } + } + ] + } + ] + } + } + ] + } + } + } + }, + "ext": "v0" + }, + "live_until": 120960 + }, + { + "entry": { + "last_modified_ledger_seq": 0, + "data": { + "contract_code": { + "ext": "v0", + "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "code": "" + } + }, + "ext": "v0" + }, + "live_until": 518400 + } + ] + }, + "events": [] +} \ No newline at end of file diff --git a/docs/COMBINED_SOROBAN_STELLAR_IMPLEMENTATION.md b/docs/COMBINED_SOROBAN_STELLAR_IMPLEMENTATION.md new file mode 100644 index 0000000..55cafaf --- /dev/null +++ b/docs/COMBINED_SOROBAN_STELLAR_IMPLEMENTATION.md @@ -0,0 +1,335 @@ +# Combined Soroban Savings Goal Vault Implementation & Stellar/Soroban Integration + +--- + +## Part 1 – Soroban Smart Savings Goal Vault – Phase‑by‑Phase Implementation Plan + +*This section is the original `SOROBAN_SAVINGS_GOAL_IMPLEMENTATION.md` content.* + +# Soroban Smart Savings Goal Vault – Phase‑by‑Phase Implementation Plan + +**Project:** NFJPIA – Savings Goals (S.A.V.E.) +**Deliverable:** Build and deploy a focused Soroban contract for test savings goals. + +--- + +### Overview +The goal is to create a **Soroban smart contract** that manages savings‑goal vaults on the Stellar testnet. The contract will handle goal creation, owner authorization, contributions, target metadata, status tracking, controlled withdrawals, and emit events. Off‑chain data (receipts, merchant info, PII, etc.) will remain in the existing backend/database. + +--- + +#### Phase 1 – Foundations & Tooling Setup +| Step | Description | Owner | Acceptance Criteria | +|------|-------------|-------|----------------------| +| 1.1 | Add Soroban toolchain to repo (`soroban-cli`, `cargo-xbuild`) and ensure Rust toolchain version consistency. | DevOps / Backend | `soroban --version` runs and `cargo build --target wasm32-unknown-unknown` succeeds. | +| 1.2 | Create a new Cargo workspace `soroban_savings` inside `nfjpia-project/contract/`. | Backend Engineer | `Cargo.toml` with `[workspace]` includes the contract crate. | +| 1.3 | Add CI job (GitHub Actions) to compile, lint, and run contract unit tests on every PR. | CI Engineer | Workflow badge shows *passing* on PRs. | +| 1.4 | Set up local Stellar testnet sandbox (`docker run stellar/quickstart`) and configure environment variables (`STELLAR_NETWORK=TESTNET`, `HORIZON_URL`, `FRIENDBOT_URL`). | DevOps | Local testnet reachable; `soroban contract list` works. | + +--- + +#### Phase 2 – Contract Data Model & Basic Storage +| Step | Description | Owner | Acceptance Criteria | +|------|-------------|-------|----------------------| +| 2.1 | Define `GoalId` as `u128` (or `bytes`) and a `Goal` struct with minimal on‑chain fields: `owner`, `target_amount`, `target_date`, `balance`, `status`. | Backend Engineer | Rust struct compiles, `#[contracttype]` derives. | +| 2.2 | Implement storage maps using `Map` and `Map>` for owner indexing. | Backend Engineer | `storage::set` / `storage::get` compile without errors. | +| 2.3 | Write unit tests for storage CRUD (create, read, update). | QA Engineer | `cargo test` passes 100% for storage layer. | + +--- + +#### Phase 3 – Core Entry Points (Create & Contribute) +| Step | Description | Owner | Acceptance Criteria | +|------|-------------|-------|----------------------| +| 3.1 | Implement `create_goal(owner: Address, target_amount: i128, target_date: Option) → GoalId` (unique counter). | +| 3.2 | Implement `contribute(goal_id: GoalId, amount: i128, contributor: Address)` – validate amount, status, update balance, emit `Contribution`. | +| 3.3 | Add basic access control: only `owner` can later call `withdraw`/`cancel`. | +| 3.4 | Write comprehensive unit tests (success, insufficient funds, wrong status, overflow). | +| 3.5 | CI runs these tests on each commit. | +| Owner | Backend Engineer | +| Acceptance | All tests pass; `soroban contract invoke` works on local testnet. | + +--- + +#### Phase 4 – Goal Lifecycle & Withdrawal Logic +| Step | Description | Owner | Acceptance Criteria | +|------|-------------|-------|----------------------| +| 4.1 | Implement `complete_goal(goal_id)` – transition to `Completed` when balance ≥ target or deadline passed. | +| 4.2 | Implement `withdraw(goal_id, amount)` – only owner, only when `Completed`, transfer via `pay`, emit `Withdrawal`, guard double‑withdrawal. | +| 4.3 | Implement `cancel_goal(goal_id)` – owner can cancel before completion; status → `Cancelled`. | +| 4.4 | Unit tests for each transition and edge cases. | +| Owner | Backend Engineer | +| Acceptance | Lifecycle tests pass; contract enforces correct state transitions. | + +--- + +#### Phase 5 – Event Emission & Off‑Chain Integration +| Step | Description | Owner | Acceptance Criteria | +|------|-------------|-------|----------------------| +| 5.1 | Define events: `GoalCreated`, `Contribution`, `GoalCompleted`, `Withdrawal`, `GoalCancelled`. | +| 5.2 | Emit events via `env::emit_event` in each entry point. | +| 5.3 | Add a small off‑chain listener (Node/TS) that subscribes to Horizon testnet streaming and persists events to MongoDB. | +| 5.4 | Backend API fetches goal state via RPC and merges with off‑chain receipt data. | +| Owner | Full‑stack Engineer | +| Acceptance | Events appear in Horizon stream; backend can query on‑chain state and combine with DB models. | + +--- + +#### Phase 6 – Testnet Deployment & Verification +| Step | Description | Owner | Acceptance Criteria | +|------|-------------|-------|----------------------| +| 6.1 | Build contract WASM (`cargo build --target wasm32-unknown-unknown --release`). | +| 6.2 | Deploy to Stellar **testnet** (`soroban contract deploy …`). Record contract address. | +| 6.3 | Integration test suite: create goal, multiple contributions, status checks, withdrawal. | +| 6.4 | CI runs integration test against fresh testnet (Docker quickstart). | +| 6.5 | Document deployment steps & contract address in `README.md`. | +| Owner | DevOps / Backend Engineer | +| Acceptance | Contract deployed, integration tests pass, README reproducible. | + +--- + +#### Phase 7 – UI/UX Front‑End Hook‑up (Optional MVP) +| Step | Description | Owner | Acceptance Criteria | +|------|-------------|-------|----------------------| +| 7.1 | Add React page `/savings/soroban` using existing design system (Heroicons, typography tokens). | +| 7.2 | Connect frontend to backend proxy for Soroban RPC calls. | +| 7.3 | Show real‑time transaction status via Horizon events. | +| 7.4 | Follow NFJPIA visual standards (icons, button colors, typography). | +| Owner | Front‑end Engineer | +| Acceptance | User can create a goal, fund it with a real Stellar testnet transaction, UI reflects on‑chain state. | + +--- + +#### Phase 8 – Documentation, Security Review & Release +| Step | Description | Owner | Acceptance Criteria | +|------|-------------|-------|----------------------| +| 8.1 | Write contract docs (`docs/CONTRACT.md`). | +| 8.2 | Conduct lightweight security audit (re‑entrancy, overflow, auth). | +| 8.3 | Add audit logs to backend actions (NFJPIA audit middleware). | +| 8.4 | Tag release candidate (`v0.1-soroban`), publish contract address & ABI. | +| Owner | Security Engineer / Lead Developer | +| Acceptance | Docs merged, audit sign‑off, release tag created. | + +--- + +### Summary Timeline (4 weeks) +| Week | Focus | +|------|-------| +| 1 | Phase 1 & 2 – environment, data model, storage basics | +| 2 | Phase 3 – core entry points & unit tests | +| 3 | Phase 4 & 5 – lifecycle, events, off‑chain integration | +| 4 | Phase 6 – testnet deployment, integration tests; optional Phase 7 UI | +| End | Phase 8 – docs, security review, release | + +--- + +**Next Steps** +1. Verify repository structure (create `contract/` folder if missing). +2. Assign owners for each phase. +3. Kick off Phase 1 by adding the Soroban toolchain. + +--- + +## Part 2 – Stellar and Soroban Integration Options for SAVE +*This section is the original `STELLAR_SOROBAN_INTEGRATIONS.md` content.* + +# Stellar and Soroban Integration Options for SAVE + +## Assessment date: 2026-08-27 + +### Purpose and scope +This document catalogs the meaningful Stellar and Soroban integrations that fit the current SAVE project. It is a product and technical options map, not a claim that every option should be built. + +#### Current repository includes +- Expo 57 / React Native client (Android, iOS, web) +- NestJS API +- Next.js admin app +- Transaction, category, budget features +- Offline SQLite caching and Zustand state +- SecureStore, local authentication, linking, web‑browser capabilities +- Planned MongoDB, Redis/BullMQ, object storage + +### Recommended product direction +| Priority | Integration | Why it fits SAVE | +|---|---|---| +| P0 | Read-only Stellar portfolio & transaction import | Adds real financial data without custody or signing risk. | +| P0 | Connect or create a non‑custodial account | Establishes on‑chain identity and balance source. | +| P0 | Send/receive XLM and selected stablecoins | Maps directly to existing income/expense flows. | +| P0 | Sponsored account reserves & fee‑bump transactions | Removes most XLM onboarding friction. | +| P1 | Anchor deposit/withdrawal & KYC flows | Enables fiat‑on/off‑ramps. | +| P1 | Soroban goal vault | Enforces on‑chain savings rules. | +| P1 | RPC event ingestion & reconciliation | Keeps views consistent with ledger state. | +| P2 | Cross‑asset path payments & quotes | Pay in one asset, receive another. | +| P2 | Shared savings, allowances, recovery policies | Adds programmable‑finance features. | +| P3 | Rewards asset, DeFi, remittance operator, custody | Valuable after demand & regulatory review. | + +### Integration catalog (selected excerpts) +#### 1. Accounts, wallets, and signing +| Option | User experience | SAVE implementation | Notes | +|---|---|---|---| +| Watch‑only account | Paste/scan address, view balances. | Client validates; backend indexes via Stellar RPC. | Safest first integration; no signing. | +| External wallet connection | User approves each tx in compatible wallet. | Build unsigned XDR/SEP‑7 request, deep‑link, reconcile hash. | Default when mobile wallet compatibility OK. | +| App‑managed non‑custodial classic account | SAVE generates/imports Ed25519 key, signs locally. | Encrypt secret, gate signing with device auth, never send secret to backend. | Requires backup/recovery, threat modelling. | +| Soroban smart wallet / contract account | Seedless passkey‑style signing with programmable controls. | Rust contract implements `__check_auth`; app supplies signatures; relayer submits. | Future‑fit for spend limits, allowlists, recovery. | +| Classic multisig account | Multiple signers approve actions. | Configure signers/thresholds, collect signatures before submission. | Useful for joint savings, treasury, issuer, sponsor. | +| Custodial/omnibus wallet | SAVE controls funds, exposes internal balances. | HSM/KMS signing, pooled account with muxed IDs/memos, withdrawals, reconciliation. | Not recommended for first release (regulated). | +| Account recovery | User recovers after losing key/device. | SEP‑30 recovery servers for classic accounts, or contract‑account recovery policies. | Design before allowing material balances. | + +#### 2. Network data and portfolio features +- XLM, issued‑asset, contract‑token balances +- Trustlines, pending/failed txs, payment/transfer/mint/burn events +- Claimable balances, offers, liquidity‑pool positions +- Soroban contract state & vault positions +- Explorer links, cost‑basis reporting (with price source) +- Use Stellar RPC for live state; persist normalized events; Hubble/Galexie for historical analytics. + +#### 3. Payments and money movement +| Integration | Application to SAVE | +|---|---| +| Native XLM payments | Send, receive, request, record XLM. | +| Issued‑asset payments | Support selected stablecoins after validation. | +| Contract‑account payments | Transfer between classic `G…` and contract `C…` via SAC. | +| Payment requests | QR codes & deep links (SEP‑7). | +| Contacts & aliases | Save verified addresses, resolve via SEP‑2 federation. | +| Pooled account routing | Use muxed accounts or memos for shared account funds. | +| Claimable balances | Send before trustline, add time predicates. | +| Batched payments | Bundle operations for reimbursements. | +| Fee sponsorship | Pay users' fees via fee‑bump without custody. | +| Reserve sponsorship | Sponsor account creation, trustlines, offers, etc. | +| Merchant/receipt matching | Attach memo for internal reference; never place private receipt data on‑chain. | + +#### 4. Fiat on/off‑ramps, KYC, and remittances +- Use existing anchor (SEP‑1, SEP‑10, SEP‑45, SEP‑12/9, SEP‑24, SEP‑6, SEP‑38, SEP‑31) instead of building one. +- Expo linking & web‑browser handle hosted‑flow callbacks. +- Becoming an anchor requires banking partners, AML, legal review – treat as separate program. + +#### 5. Asset conversion and liquidity +| Integration | What SAVE could expose | Risk/constraint | +|---|---|---| +| Path payment | User pays XLM, recipient receives stablecoin (or vice versa). | Quote expiry, slippage, trustlines, route availability. | +| SDEX order | Buy/sell assets, show order status. | Asset verification, thin liquidity, price impact. | +| Liquidity‑pool deposit/withdrawal | Track/manage LP positions. | Impermanent loss, reserve requirements. | +| Soroban DEX/DeFi adapter | Route swaps/deposits to reviewed contracts. | Contract/oracle liquidity risk; allowlist contract IDs. | + +#### 6. Soroban savings and finance contracts (most relevant) +| Contract feature | Core behavior | Suggested priority | +|---|---|---| +| Goal vault | Deposit XLM or approved SAC asset toward a named goal; withdraw under defined rules. | P1 | +| Time‑locked savings | Prevent withdrawal until timestamp/ledger deadline. | P1 | +| Shared savings pot | Multiple members contribute; withdrawal requires threshold/role approval. | P2 | +| Envelope vaults | Auditable balances for categories/goals while assets stay in contract custody. | P2 | +| Allowance/spending policy | Capped amount per period, recipient allowlist, dual approval. | P2 | +| Milestone escrow | Release funds after payer/payee approval, deadline, or arbiter decision. | P2 | +| Matching contribution | Sponsor matches deposits up to a cap. | P2 | +| Rewards distribution | Distribute existing Stellar asset for streaks or participation. | P2/P3 | +| Round‑up aggregation | Accumulate round‑ups, periodically deposit into a goal. | P2 (off‑chain computation) | +| Recurring contribution | Store schedule/allowance; keeper submits due contributions. | P2 (contract cannot initiate) | +| Conditional disbursement | Release based on attestations or oracle data. | P3 (oracle trust) | +| Group lending / rotating savings | Savings circle contributions/payouts. | P3 (regulatory risk) | +| DeFi yield adapter | Deposit assets into lending/liquidity protocol, track shares/yield. | P3 (no fixed yield guarantee) | +| Governance | Voting over shared treasury rules or upgrades. | P3 | +| Proof/attestation | Publish hash/minimal event proving milestone. | Optional (no personal data) | + +*Soroban contracts are Rust → Wasm; they can authorize accounts & contracts, interact via SAC, but cannot directly invoke SDEX, claimable‑balance, or sponsorship – those must be composed externally.* + +#### 7. Assets and tokens +1. Display & transfer existing assets (allowlist). +2. Use existing assets in a vault (SAC). +3. Issue a SAVE rewards asset (classic Stellar asset, with issuer & distribution accounts, cold/multisig controls). +4. Build a SEP‑41 contract token or regulated token only if needed. + +#### 8. Authentication and identity protocols +- SEP‑10 (classic) or SEP‑45 (contract) for wallet login. +- App session linked to Stellar addresses. +- KYC without putting PII on‑chain. +- Federation names, SEP‑1 domain discovery, SEP‑8 regulated‑asset approval, SEP‑33 identicons. + +#### 9. Admin, reconciliation, and operations +- Per‑network contract & asset allowlists. +- Sponsor account balance/reserve/fee monitoring. +- Transaction submission queue, idempotent retries. +- RPC cursor checkpoints, ledger confirmation, failed‑tx reconciliation. +- Vault totals & contract‑event dashboards. +- Anchor transaction & KYC status tools. +- Signer/threshold & issuer monitoring. +- Suspicious activity alerts. +- Contract Wasm hash, deployment, upgrade, TTL tracking. +- Audit exports distinguishing on‑chain facts from app metadata. + +#### Required data‑model changes (high‑level) +- `StellarAccount`, `Asset`, `LedgerTransaction`, `LedgerOperation`/`ContractEvent`, `SigningRequest`, `VaultPosition`, `AnchorTransaction`, `ChainLink` etc. +- Store amounts as exact integer/string representation, never JavaScript `number`. + +#### Expo 57 integration notes +- `expo-secure-store` appropriate for small encrypted values; design backup/recovery. +- `expo-local-authentication` for signing gating (Face ID needs dev build). +- Custom scheme for callbacks; production should add universal/app links. +- `@stellar/stellar-sdk` compatibility with React Native – validate polyfills or use backend‑only signing. +- `stellar-wallet-sdk` for common wallet/anchor flows; lower‑level SDK/RPC for advanced ops & Soroban. + +#### Security, privacy, and correctness requirements +- Default to Testnet until proven. +- Bind signatures to network passphrase. +- Never send secret seed or PII to backend or logs. +- Show decoded transaction summary before signing. +- Simulate Soroban tx before signing; enforce fee/resource bounds. +- Treat all external input (deep links, callbacks, RPC) as untrusted. +- Use allowlists for destinations, assets, contracts. +- Idempotency keys; reconcile via transaction hash, ledger, operation/event IDs. +- Keep PII, receipt images, budget names, KYC docs off‑chain. +- Separate sponsor, relayer, issuer, distribution, admin keys; protect with HSM/KMS. +- Audit contracts (property/fuzz tests, invariants, Testnet deploys, source verification, upgrade controls, pause strategy). +- Plan storage TTL & restoration; TTL not safe for deadline. +- Legal review before custody, fiat ramps, rewards, swaps, lending, pooled funds, securities, etc. + +#### Known limitations and non‑goals +- Soroban cannot initiate transactions; recurring deposits need user/relayer. +- Cannot directly operate classic SDEX, claimable balances, sponsorships. +- On‑chain data is public; encryption elsewhere does not make it private. +- Stellar address ≠ verified person. +- On‑chain balances lack fiat price, tax lots, merchant identity. +- Offline mode cannot confirm ledger finality. +- Stablecoin does not guarantee redemption or regulatory compliance. +- Smart‑contract programmability does not remove custody, consumer‑protection, tax, AML, securities obligations. + +#### Delivery roadmap (phases) +**Phase 0 — Decisions & proof of compatibility** +1. Choose wallet model (watch‑only, external, app‑managed, smart‑wallet). +2. Choose Testnet asset allowlist & RPC provider. +3. Prove `@stellar/stellar-sdk`, Wallet SDK, polyfills, deep links, SecureStore, biometric confirmation on Android/iOS/web. +4. Define amount, network, account, ledger‑event, idempotency models. +5. Write threat, custody, recovery, compliance decisions. + +**Phase 1 — Read‑only vertical slice** +1. Link a Testnet address. +2. Import balances & payment events via RPC. +3. Store cursors & normalized ledger data in backend. +4. Display explorer‑verified activity linked to optional SAVE categories. +5. Add admin reconciliation & RPC‑health views. + +**Phase 2 — Payments** +1. Build, decode, review, sign, submit, reconcile Testnet payments. +2. Add receive/request QR & deep‑link flows. +3. Add fee‑bump & reserve sponsorship with quotas. +4. Add trustline & claimable‑balance handling for one stablecoin. +5. Test timeout, duplicate submission, sequence conflict, fee surge, bad memo, wrong network, callback spoofing. + +**Phase 3 — Fiat access** +1. Integrate one test anchor (SEP‑1/10/12/24/38). +2. Handle browser callbacks, anchor status, ledger status, cancellation. +3. Add production KYC/privacy/legal controls before Mainnet. + +**Phase 4 — Goal vault** +1. Specify owner, asset, deposit, withdrawal, deadline, emergency, upgrade, fee, TTL invariants. +2. Implement & test minimal Rust contract. +3. Generate typed client bindings, simulate invocations, index contract events. +4. Audit, deploy to Testnet, verify Wasm/source, complete failure/recovery drills before Mainnet. + +**Phase 5 — Optional expansion** +- Add shared savings, smart‑wallet policies, path payments, recovery, rewards, remittances, DeFi adapters as needed, each with threat model & go/no‑go review. + +### Final recommendation +Build the first release as a non‑custodial, Testnet‑first wallet companion: watch/link an account, import balances/payments via RPC, send/request a reviewed asset with external or locally protected signing, sponsor fees/reserves, reconcile every action through backend. Then add a deliberately small Soroban goal‑vault contract. This path reuses existing SAVE components while keeping custody, contract, and regulatory risk bounded. + +--- + +*End of combined document.* diff --git a/docs/CONTRACT.md b/docs/CONTRACT.md new file mode 100644 index 0000000..d7f6830 --- /dev/null +++ b/docs/CONTRACT.md @@ -0,0 +1,79 @@ +# SAVE Savings Vault Contract + +## Scope + +`save-savings-vault` is a deliberately small, Testnet-first Soroban contract. It accepts approved Stellar Asset Contract tokens, holds them per savings goal, enforces owner authorization for lifecycle actions, and emits indexable events. Names, receipts, merchant information, account profiles, and all other private metadata stay off-chain. + +## Interface + +| Function | Authorization | Result | +|---|---|---| +| `create_goal(owner, asset, target_amount, target_date)` | owner | Creates an active goal and returns its `u128` ID. | +| `contribute(goal_id, contributor, amount)` | contributor | Transfers SAC tokens into the vault and updates exact balance. | +| `complete_goal(goal_id)` | permissionless | Completes when target is reached or optional Unix deadline has passed. | +| `withdraw(goal_id, amount)` | owner | Transfers tokens from a completed goal to its owner. | +| `cancel_goal(goal_id)` | owner | Cancels an active goal and atomically refunds its full balance. | +| `get_goal(goal_id)` | none | Reads one goal. | +| `list_goals(owner)` | none | Reads goals indexed to an owner. | + +Amounts are atomic `i128` token units, never floating-point values. `target_date` is a Unix timestamp used as a condition only; contract storage TTL is extended separately and is not used as a clock. + +## Events + +The typed ABI contains `GoalCreated`, `Contribution`, `GoalCompleted`, `Withdrawal`, and `GoalCancelled`. Backend ingestion uses Stellar RPC `getEvents`; Horizon is used only for classic account/payment history. + +## Build and test + +```bash +npm run contract:test +npm run contract:build +``` + +The Wasm output is `contract/target/wasm32v1-none/release/save_savings_vault.wasm`. + +## Testnet deployment + +The project currently uses this dedicated Testnet deployment: + +| Setting | Value | +|---|---| +| Vault contract | `CALFEOYNTNJYB5HTUPYHHFHMNNYLYEBOCV43Z73J54G3CQNSH5VCNP7H` | +| Native XLM SAC | `CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC` | +| Wasm SHA-256 | `3c6be5dbf17042fcf1041b7a66c7a1f90a4f95233139246ab12cd7eb44bc40ef` | +| Deployed | 2026-08-31 | + +This deployment fixes first-time-owner reads so `list_goals` returns an empty list instead of +attempting to extend a nonexistent storage key. The prior Testnet deployment remains available +for its historical Deliverables 1–2 evidence and sample goal. + +Both IDs are public network identifiers, not credentials. They are configured in +`backend/.env.example`; production and Mainnet must use separately reviewed deployments. + +Reviewer evidence for the deployed sample goal and controlled contributions is recorded in +[`DELIVERABLES_1_2_TEST_REPORT.md`](./DELIVERABLES_1_2_TEST_REPORT.md). + +No application or backend secret is required for normal operation. Deployment is an explicit operator action: + +```bash +stellar keys generate save-deployer --network testnet --fund +stellar contract deploy \ + --wasm contract/target/wasm32v1-none/release/save_savings_vault.wasm \ + --source save-deployer \ + --network testnet +``` + +Record the returned `C…` address as `STELLAR_VAULT_CONTRACT_ID` in the backend environment. Do not commit the deployer seed or local Stellar CLI identity directory. Verify the deployed Wasm hash and source before allowing material Testnet balances. + +## Security review + +- Every token debit from a user is preceded by `require_auth`. +- Withdrawal and cancellation require the stored owner. +- Checked arithmetic prevents contribution overflow. +- Status transitions prevent contribution after completion/cancellation and withdrawal before completion. +- Cancellation refunds funds instead of trapping them. +- Token transfer and state mutation execute atomically. +- Persistent and instance storage TTLs are extended on access. +- Backend simulation enforces a maximum fee before external-wallet signing. +- Backend never accepts or stores secret seeds. + +Before Mainnet: independent audit, invariant/property testing, asset and contract allowlists, upgrade/pause decision, recovery drills, sponsor/relayer separation, and legal review are mandatory. diff --git a/docs/DELIVERABLES_1_2_TEST_REPORT.md b/docs/DELIVERABLES_1_2_TEST_REPORT.md new file mode 100644 index 0000000..82d47d5 --- /dev/null +++ b/docs/DELIVERABLES_1_2_TEST_REPORT.md @@ -0,0 +1,75 @@ +# Deliverables 1–2 Test Report + +Source scope: [S.A.V.E. Instawards Statement of Work](https://docs.google.com/document/d/1MNAtfmaTvSXxTdJkjGg4FwTJSKF_efkiQA666VXEjTM/edit) + +Network: Stellar Testnet +Evidence deployment: `CAJOBHJQORFRFFWN4X5LKLQIURQJNQFABQG6L452SWCFPAPDIWLRILYG` +Native XLM SAC: `CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC` +Verified Wasm hash: `774d426c6165e362bc14930abd04152fbaf3bd9e13a1d8522d6942c99e1bf1a6` + +Current app deployment: `CALFEOYNTNJYB5HTUPYHHFHMNNYLYEBOCV43Z73J54G3CQNSH5VCNP7H` +Current Wasm hash: `3c6be5dbf17042fcf1041b7a66c7a1f90a4f95233139246ab12cd7eb44bc40ef`. +It preserves the reviewed interface and lifecycle behavior while fixing empty `list_goals` +queries for first-time owners; the regression suite now contains six contract tests. + +## Deliverable 1 — Stellar Testnet Savings Funding Flow + +| Acceptance item | Implementation and evidence | +|---|---| +| Controlled Testnet account/wallet | Watch-only public account in SAVE; transaction approval remains in a SEP-7 external wallet. No user secret reaches the app or API. | +| Designated test asset | Native Testnet XLM through its Stellar Asset Contract. Mobile amounts are entered as XLM and converted exactly to seven-decimal atomic units. | +| Real goal contribution | `contribute` transfers XLM SAC tokens from the authenticated contributor into the deployed vault. No mocked balance update is used. | +| Transaction status | The API stores the deterministic transaction hash at preparation, accepts a SEP-7 signed-XDR callback, verifies the signed body matches the prepared XDR, submits it, and reconciles `prepared`, `pending`, `success`, or `failed`. | +| Failure and retry | Invalid zero contributions fail during simulation with contract error `#2` (`InvalidAmount`) and do not change state. Expired wallet approvals surface a fresh-retry action in the app. | +| Explorer references | Transaction cards and goal event cards link directly to Stellar Expert Testnet proof. | + +### Controlled contribution evidence + +Sample goal `1` targets `0.3 XLM` (`3,000,000` atomic units). + +1. Goal creation: [2c1d2b…9576](https://stellar.expert/explorer/testnet/tx/2c1d2b8210a9a00dd7b95b0999f01945973a28702f07a7156f89c68afa759576) +2. Contribution `0.1 XLM`: [3b9fdb…cfeb](https://stellar.expert/explorer/testnet/tx/3b9fdb087e71fb0e33e228c0f5f853af4e417d10142176ef920486d00cadcfeb) +3. Contribution `0.2 XLM`: [ddc102…bc9f](https://stellar.expert/explorer/testnet/tx/ddc102e0abfc62df0ddcdfa67260fd1de5b2823c143cad9ab8ffbd1f2199bc9f) +4. Controlled failure: a zero-amount contribution was rejected during simulation with `VaultError::InvalidAmount`; no transaction was submitted and the balance remained `0.3 XLM`. +5. Valid retry `0.01 XLM`: [b524b0…b9e0](https://stellar.expert/explorer/testnet/tx/b524b0cb1a40ba55c13f0ba8e635fa1c5c6ad975563df647c585a24f3418b9e0) +6. App-equivalent prepare/sign/callback/status flow, withdrawing `0.01 XLM`: [4ec369…bfcc](https://stellar.expert/explorer/testnet/tx/4ec369a69f32eb022ec0fe7a78e60d2d0cc6b2dd0abdf84a0a42df988830bfcc) + +The last transaction was prepared by `POST /stellar/vault/prepare`, signed externally, returned as form-encoded XDR to the SEP-7 callback, submitted by the API, and reconciled to `success` through `GET /stellar/signing-requests/:idempotencyKey`. + +## Deliverable 2 — Soroban Smart Savings Goal Vault + +| Acceptance item | Implementation and evidence | +|---|---| +| Goal creation and metadata | Owner, SAC asset, target amount, optional Unix target date, balance, status, and numeric ID. | +| Owner/contributor authorization | `require_auth` protects goal creation, contributions, withdrawal, and cancellation. | +| Controlled release | Completion requires target or deadline; withdrawal requires completed status and owner authorization; cancellation atomically refunds the full active balance. | +| Invalid/duplicate transitions | Invalid amounts, premature completion/withdrawal, contribution after cancellation, duplicate completion, and duplicate cancellation are rejected. | +| Events | Typed `GoalCreated`, `Contribution`, `GoalCompleted`, `Withdrawal`, and `GoalCancelled` events are indexed by the API and linked to explorer proof. | +| Privacy boundary | Only minimum goal and token state is on-chain. Receipts, merchants, income, TIN, budgets, and PII remain off-chain. | +| Tests and deployment | Five Rust contract tests pass; the deployed Testnet Wasm hash matches the local release build. | + +Sample goal completion: [f99595…df29](https://stellar.expert/explorer/testnet/tx/f99595d542fb4cb98ee67c00a560494687073a938d696f697aaabea23e58df29). The goal completed with `3,100,000` atomic units before the callback-path withdrawal test. + +## Repeatable verification + +```bash +npm run contract:test +npm run contract:build +cd backend && npm test +cd .. && npx tsc --noEmit +``` + +Runtime checks: + +```bash +curl http://localhost:3000/stellar/network +curl http://localhost:3000/.well-known/stellar.toml +curl http://localhost:3000/stellar/vault/goals/GCH4EU75Q77NF2BEB4W2QFMM5MCTJ5DIJGZVEPRRT6OWEXREOBEOQQMF +``` + +## Security and deployment notes + +- This scope is Testnet-only; it does not enable Mainnet, real-value custody, fiat ramps, yield, KYC/AML, or private records on-chain. +- `STELLAR_INTEGRITY_SIGNER_SECRET_FILE` signs SEP-7 request provenance only. It never signs user transactions. +- Request provenance signing remains disabled until `STELLAR_ORIGIN_DOMAIN` is set to a public HTTPS domain serving `/.well-known/stellar.toml`. The local API still exposes the configured public signing key for verification. +- The local callback base URL must be reachable from the test wallet. Production callback URLs require HTTPS. diff --git a/docs/STELLAR_ARCHITECTURE.md b/docs/STELLAR_ARCHITECTURE.md new file mode 100644 index 0000000..7e2d2c9 --- /dev/null +++ b/docs/STELLAR_ARCHITECTURE.md @@ -0,0 +1,47 @@ +# Stellar Architecture Decisions + +## MVP decisions + +- Network: Stellar Testnet only. Every signature is bound to `Test SDF Network ; September 2015`. +- Wallet model: watch-only account plus external-wallet approval through SEP-7. SAVE does not generate, import, transmit, log, or store secret seeds. +- Asset allowlist: native XLM through its Testnet Stellar Asset Contract. Additional SAC assets require explicit backend configuration and product review. +- Data sources: Horizon for classic accounts/payments; Stellar RPC for Soroban simulation, submission, transaction status, contract reads, and events. +- Amount representation: classic payment inputs are validated decimal strings with at most seven fractional digits; Soroban values are atomic-unit decimal strings converted to `bigint` server-side. +- Private data: receipt content, merchant/category labels, user profile data, and goal names remain off-chain. The vault contains only owner, asset, target amount/date, balance, status, and ID. +- Submission: backend prepares and simulates XDR; the external wallet signs. Signed XDR may then be submitted to the backend, which reconciles by transaction hash. +- Fees: simulated Soroban fees above `STELLAR_MAX_SOROBAN_FEE` are rejected before signing. +- SEP-7 callback: each prepared request may include a unique callback URL. The backend accepts form-encoded signed XDR only when its transaction body hash exactly matches the prepared request, then submits and reconciles it. +- Request provenance: a dedicated integrity key may sign SEP-7 URIs only when a public `STELLAR_ORIGIN_DOMAIN` is configured and publishes the matching `URI_REQUEST_SIGNING_KEY` from `/.well-known/stellar.toml`. This key never signs user transactions. + +## Trust boundaries + +```text +Mobile app ── public address / unsigned intent ──> SAVE API + │ │ + │ SEP-7 unsigned XDR ├── Horizon (classic read/submit) + ▼ └── Stellar RPC (simulate/events/status) +External wallet ── explicit user approval/signature ──> Stellar Testnet +``` + +The API treats addresses, callbacks, XDR, RPC data, and wallet responses as untrusted. Validation pipes reject unknown DTO fields, signed XDR is decoded against the Testnet passphrase, and an empty signature set is rejected. + +## Persistence and reconciliation + +- `StellarAccount`: linked public address and last sync time. +- `StellarSigningRequest`: idempotency key, unsigned XDR, action, status, and transaction hash. +- `StellarContractEvent`: unique RPC event ID, contract, ledger, transaction hash, topics, and value. +- Event polling uses the RPC cursor and idempotent MongoDB upserts. It is disabled until a valid vault contract ID is configured. + +## Deliberate non-goals for this release + +Mainnet, local key custody, sponsor/relayer keys, fee bumps, reserve sponsorship, stablecoin trustlines, anchors/KYC, path payments, DeFi, rewards, smart-wallet recovery, and shared vaults are not enabled. They remain separate, threat-modeled phases; enabling them requires infrastructure, wallet compatibility, compliance decisions, and credentials not present in this repository. + +## Failure behavior + +- Offline mobile data is never represented as ledger-final. +- RPC/Horizon failure returns an unavailable status instead of inventing balances. +- Duplicate prepare requests return the prior signing request by idempotency key. +- Prepared transaction hashes are deterministic before signing, allowing reconciliation even when a wallet submits directly instead of using the callback. +- Expired approvals become explicit failed requests with a fresh-retry action; an idempotency key cannot be reused for a different source or action. +- Contract submission is `pending` until RPC reports final success or failure. +- Contract cancellation refunds the complete vault balance atomically before marking the goal cancelled. diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..02dd782 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,7 @@ +const { defineConfig, globalIgnores } = require('eslint/config'); +const expoConfig = require('eslint-config-expo/flat'); + +module.exports = defineConfig([ + globalIgnores(['dist/*', '.expo/*']), + expoConfig, +]); diff --git a/metro.config.js b/metro.config.js new file mode 100644 index 0000000..4c963d4 --- /dev/null +++ b/metro.config.js @@ -0,0 +1,11 @@ +const { getDefaultConfig } = require('expo/metro-config'); + +const config = getDefaultConfig(__dirname); + +// WalletConnect's noble/scure dependencies still publish browser mappings that +// point at file-extension subpaths omitted from their package export maps. +// Metro already falls back to file resolution for them; opting out of package +// exports makes that compatible resolution deterministic and removes warnings. +config.resolver.unstable_enablePackageExports = false; + +module.exports = config; diff --git a/package-lock.json b/package-lock.json index d6585b0..0c9ac9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,17 @@ "version": "1.0.0", "dependencies": { "@expo/ui": "~57.0.14", + "@react-native-async-storage/async-storage": "2.2.0", + "@react-native-community/netinfo": "12.0.1", "@tanstack/react-query": "^5.101.4", + "@walletconnect/react-native-compat": "^2.23.10", + "@walletconnect/sign-client": "^2.23.10", "expo": "~57.0.18", + "expo-application": "~57.0.2", "expo-camera": "~57.0.4", + "expo-clipboard": "~57.0.1", "expo-constants": "~57.0.12", + "expo-crypto": "~57.0.2", "expo-dev-client": "~57.0.16", "expo-device": "~57.0.1", "expo-file-system": "~57.0.4", @@ -33,6 +40,7 @@ "react-dom": "19.2.3", "react-native": "0.86.3", "react-native-gesture-handler": "~2.32.0", + "react-native-get-random-values": "~1.11.0", "react-native-reanimated": "4.5.1", "react-native-safe-area-context": "~5.7.0", "react-native-screens": "~4.26.0", @@ -42,9 +50,17 @@ }, "devDependencies": { "@types/react": "~19.2.2", + "eslint": "^9.0.0", + "eslint-config-expo": "~57.0.2", "typescript": "~6.0.3" } }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", + "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", + "license": "MIT" + }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -1195,6 +1211,246 @@ "node": ">=0.8.0" } }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@expo-google-fonts/material-symbols": { "version": "0.4.44", "resolved": "https://registry.npmjs.org/@expo-google-fonts/material-symbols/-/material-symbols-0.4.44.tgz", @@ -1950,6 +2206,72 @@ "excpretty": "build/cli.js" } }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@isaacs/ttlcache": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", @@ -2043,6 +2365,86 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@msgpack/msgpack": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.1.3.tgz", + "integrity": "sha512-47XIizs9XZXvuJgoaJUIE2lFoID8ugvc0jzSHP+Ptfk8nTbnR8g788wv48N03Kx0UkAv559HWRQ3yzOgzlRNUA==", + "license": "ISC", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.3.tgz", + "integrity": "sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@noble/ciphers": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", + "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.0.tgz", + "integrity": "sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.0.tgz", + "integrity": "sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, "node_modules/@radix-ui/primitive": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.7.tgz", @@ -2476,6 +2878,28 @@ } } }, + "node_modules/@react-native-async-storage/async-storage": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz", + "integrity": "sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw==", + "license": "MIT", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || >=0.65 <1.0" + } + }, + "node_modules/@react-native-community/netinfo": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-12.0.1.tgz", + "integrity": "sha512-P/3caXIvfYSJG8AWJVefukg+ZGRPs+M4Lp3pNJtgcTYoJxCjWrKQGNnCkj/Cz//zWa/avGed0i/wzm0T8vV2IQ==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": ">=0.59" + } + }, "node_modules/@react-native-masked-view/masked-view": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@react-native-masked-view/masked-view/-/masked-view-0.3.2.tgz", @@ -2794,6 +3218,88 @@ } } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@scure/base": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", + "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", + "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.9.0", + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", + "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.8.0", + "@scure/base": "~1.2.5" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.12", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", @@ -2826,12 +3332,30 @@ "react": "^18 || ^19" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/emscripten": { "version": "1.41.5", "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.41.5.tgz", "integrity": "sha512-cMQm7pxu6BxtHyqJ7mQZ2kXWV5SLmugybFdHCBbJ5eHzOo6VhBckEgAT3//rP5FwPHNPeEiq4SmQ5ucBwsOo4Q==", "license": "MIT" }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/hammerjs": { "version": "2.0.46", "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.46.tgz", @@ -2862,6 +3386,20 @@ "@types/istanbul-lib-report": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "26.2.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz", @@ -2904,262 +3442,1807 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "license": "MIT" }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", - "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", - "license": "ISC" - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.14.tgz", - "integrity": "sha512-T4EDRUBVZYRldYApjEJiU0e1stYWaRAX7CuSnKzrpwdZKo53zGV8/pqfzV6FfwNl9YThD2OumQYvqtvjvgG7aQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.68.0.tgz", + "integrity": "sha512-WASHDpCm6qO5jj9g1a+8NiW5+GCkAyLReR56/4VruYmNgfUmqpxOfZ2Yfb8xGfJPWv5Qi6LSD8sXdces3vbp/Q==", + "dev": true, "license": "MIT", "dependencies": { - "event-target-shim": "^5.0.0" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/type-utils": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", - "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, - "engines": { - "node": ">=0.4.0" + "peerDependencies": { + "@typescript-eslint/parser": "^8.68.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.7.tgz", + "integrity": "sha512-dML0wP6oak21rsNYCJpJB6O1BJIEwNpGrTw0URPfAk4hm0e3pRfCtzkfB6olBcXcVlU2rouCyz7lCyRB0OMVCA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 4" } }, - "node_modules/agent-cli-detector": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/agent-cli-detector/-/agent-cli-detector-0.1.6.tgz", - "integrity": "sha512-vKrPeEVN3upDF3GjWxsWBbwQgMtNJ8VB1cduPvK3svmmz4ENpS7yaPxbogsbe3w+xp9xp2Cu+0Ar41rjAR4+lA==", + "node_modules/@typescript-eslint/parser": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.68.0.tgz", + "integrity": "sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==", + "dev": true, "license": "MIT", - "bin": { - "agent-cli-detector": "dist/cli.js" + "dependencies": { + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3" }, "engines": { - "node": ">=18.18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/anser": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", - "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", - "license": "MIT" - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.68.0.tgz", + "integrity": "sha512-5GQtWZCXFcFYux955pvoS02WLc49pXNlvIxocKjS0clvwo3in1RdlzVKyiqQH9vE5AKWFLTaUgeQkOrTS+0Qxw==", + "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "@typescript-eslint/tsconfig-utils": "^8.68.0", + "@typescript-eslint/types": "^8.68.0", + "debug": "^4.4.3" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "license": "(MIT OR CC0-1.0)", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.68.0.tgz", + "integrity": "sha512-T5eXpcaJNg8bhjHJ8Rjp68Vq/QBteYtTKY8TZqVNPaUbuz0f6jI9t6aDkylwvalpAB9XTTFeFOjrjXAZ3YvmVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0" + }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.68.0.tgz", + "integrity": "sha512-F7zrGQfiJHojPwi8vhxZQC1tWtJzvL74cK/nqri2lk8YUXvYaYwl263xOJ69jDWPUk1hmcdoayFwk9lX09npVw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.68.0.tgz", + "integrity": "sha512-X77zqoY1EjeWGs/0JNxeaMfp5C5lIz4Tw8y66F1Ne8Faq6g424sBNYM6xBAqElfGZPLpWS+CZAp0DXyKDzWiHg==", + "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0", + "@typescript-eslint/utils": "8.68.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/aria-hidden": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", - "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "node_modules/@typescript-eslint/types": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.68.0.tgz", + "integrity": "sha512-9RnpsGJjrAllCMefGVVsImJM24YurhC0Q1h4UbvivtvOqXmR/vEJge2OoE++z9m6hyg8T1Q8t5SNT6tHSbrxcg==", + "dev": true, "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "license": "MIT" - }, - "node_modules/await-lock": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", - "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==", - "license": "MIT" - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.17", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", - "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.68.0.tgz", + "integrity": "sha512-OKKsD0tYmoNiU5PW2zehO1yO56jYOm1ShYlxon/Z0SJNidAkdVg86eg9ruRuoXf8xfnuWZGbwDsStkoXbZtIIA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-define-polyfill-provider": "^0.6.8", - "semver": "^6.3.1" + "@typescript-eslint/project-service": "8.68.0", + "@typescript-eslint/tsconfig-utils": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/visitor-keys": "8.68.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "node_modules/@typescript-eslint/utils": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.68.0.tgz", + "integrity": "sha512-PB5gJMMOg0Q5P1tsgWtEAqQacJXq0qEqRHDX/YJ4FaTMLfZPpHB3gjl2EJuiZyPABxmj4ZQYiY9m1bdAJ5y7tQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.68.0", + "@typescript-eslint/types": "8.68.0", + "@typescript-eslint/typescript-estree": "8.68.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", - "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.68.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.68.0.tgz", + "integrity": "sha512-YR65gGdGvTUAWLldC3xLOvOzamdGzB4A5/N8rehEaHs3Zvoe39BhgY+u0SPch1OvrVTfLcc55wsSgK2NcnTS/A==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.8" + "@typescript-eslint/types": "8.68.0", + "eslint-visitor-keys": "^5.0.0" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/babel-plugin-react-compiler": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz", - "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.26.0" + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/babel-plugin-react-native-web": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.21.2.tgz", - "integrity": "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==", - "license": "MIT" + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "license": "ISC" }, - "node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.36.1", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.36.1.tgz", - "integrity": "sha512-ycduwJbvdvIMmVvlAZqGggS+pm5Eu4Bk9pcV9Sm2Z4PJNRVsKkv0g7vHj+LeuC1gHTeF67sJXFOq61IlqCa2hA==", + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", + "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "hermes-parser": "0.36.1" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/babel-plugin-transform-flow-enums": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", - "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", + "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-flow": "^7.12.1" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/babel-preset-expo": { - "version": "57.0.9", - "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-57.0.9.tgz", - "integrity": "sha512-T19biGOBTnMp161PyBqWOoSIEeZug8/EjtuUdVob8JPQKZMTalHUQaQt+qtQQE7XsEkZJ6erb3k0CohneTFzQg==", + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", + "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@babel/generator": "^7.20.5", - "@babel/helper-module-imports": "^7.25.9", - "@babel/plugin-proposal-decorators": "^7.12.9", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", + "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", + "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", + "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", + "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", + "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", + "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", + "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-loong64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", + "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", + "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", + "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", + "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", + "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", + "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", + "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-openharmony-arm64": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", + "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", + "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", + "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", + "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", + "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@walletconnect/core": { + "version": "2.23.10", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-2.23.10.tgz", + "integrity": "sha512-Qq2btHEoCgruvkZCWLSrVsvg/dYbM9Z045qeClwhJR4meL32jbIRT0mKWjf0HkRc2LA82MsnszVnfuZl3yWl5A==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-provider": "1.0.14", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/jsonrpc-ws-connection": "1.0.16", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "3.0.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.23.10", + "@walletconnect/utils": "2.23.10", + "@walletconnect/window-getters": "1.0.1", + "es-toolkit": "1.45.1", + "events": "3.3.0", + "uint8arrays": "3.1.1" + }, + "engines": { + "node": ">=18.20.8" + } + }, + "node_modules/@walletconnect/core/node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@walletconnect/core/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@walletconnect/core/node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/@walletconnect/environment": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.1.tgz", + "integrity": "sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/environment/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/events": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/events/-/events-1.0.1.tgz", + "integrity": "sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ==", + "license": "MIT", + "dependencies": { + "keyvaluestorage-interface": "^1.0.0", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/events/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/heartbeat": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz", + "integrity": "sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==", + "license": "MIT", + "dependencies": { + "@walletconnect/events": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/jsonrpc-provider": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz", + "integrity": "sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0" + } + }, + "node_modules/@walletconnect/jsonrpc-types": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz", + "integrity": "sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ==", + "license": "MIT", + "dependencies": { + "events": "^3.3.0", + "keyvaluestorage-interface": "^1.0.0" + } + }, + "node_modules/@walletconnect/jsonrpc-utils": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz", + "integrity": "sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw==", + "license": "MIT", + "dependencies": { + "@walletconnect/environment": "^1.0.1", + "@walletconnect/jsonrpc-types": "^1.0.3", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/jsonrpc-utils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/jsonrpc-ws-connection": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.16.tgz", + "integrity": "sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-utils": "^1.0.6", + "@walletconnect/safe-json": "^1.0.2", + "events": "^3.3.0", + "ws": "^7.5.1" + } + }, + "node_modules/@walletconnect/logger": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/logger/-/logger-3.0.2.tgz", + "integrity": "sha512-7wR3wAwJTOmX4gbcUZcFMov8fjftY05+5cO/d4cpDD8wDzJ+cIlKdYOXaXfxHLSYeDazMXIsxMYjHYVDfkx+nA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.2", + "pino": "10.0.0" + } + }, + "node_modules/@walletconnect/react-native-compat": { + "version": "2.23.10", + "resolved": "https://registry.npmjs.org/@walletconnect/react-native-compat/-/react-native-compat-2.23.10.tgz", + "integrity": "sha512-fTYsOO0YY+RtcJ3UVz/Z0Czb9BEPMXkk5VSdIJ5MoOVJ0EFsFJ/1mDtHLGMBi68W2ceXW2W4pDuuufaiZ48Bbg==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "events": "3.3.0", + "fast-text-encoding": "1.0.6", + "react-native-url-polyfill": "2.0.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "*", + "@react-native-community/netinfo": "*", + "expo-application": "*", + "react-native": "*", + "react-native-get-random-values": "*" + }, + "peerDependenciesMeta": { + "expo-application": { + "optional": true + } + } + }, + "node_modules/@walletconnect/relay-api": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-api/-/relay-api-1.0.11.tgz", + "integrity": "sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==", + "license": "MIT", + "dependencies": { + "@walletconnect/jsonrpc-types": "^1.0.2" + } + }, + "node_modules/@walletconnect/relay-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@walletconnect/relay-auth/-/relay-auth-1.1.0.tgz", + "integrity": "sha512-qFw+a9uRz26jRCDgL7Q5TA9qYIgcNY8jpJzI1zAWNZ8i7mQjaijRnWFKsCHAU9CyGjvt6RKrRXyFtFOpWTVmCQ==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.0", + "@noble/hashes": "1.7.0", + "@walletconnect/safe-json": "^1.0.1", + "@walletconnect/time": "^1.0.2", + "uint8arrays": "^3.0.0" + } + }, + "node_modules/@walletconnect/safe-json": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.2.tgz", + "integrity": "sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/safe-json/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/sign-client": { + "version": "2.23.10", + "resolved": "https://registry.npmjs.org/@walletconnect/sign-client/-/sign-client-2.23.10.tgz", + "integrity": "sha512-vO7DGRRmKo+rykmjVyQR1aM4I2nbk9kJ6olbxgjFRR6Jdhy+Kz+zgN7Ce5xVhPfWYVu4bV/XhOQxhvnQw7S5ng==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@walletconnect/core": "2.23.10", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/logger": "3.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.23.10", + "@walletconnect/utils": "2.23.10", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@walletconnect/time/-/time-1.0.2.tgz", + "integrity": "sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/time/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/types": { + "version": "2.23.10", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-2.23.10.tgz", + "integrity": "sha512-XP8d41979anTrc1OJF3ISF+g81cvp1wim+ObdNnbcaT/jhwLwv+0T7rRe9VwRv+h8EaRgLyeb5YGy7oJ49vxVg==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@walletconnect/events": "1.0.1", + "@walletconnect/heartbeat": "1.2.2", + "@walletconnect/jsonrpc-types": "1.0.4", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "3.0.2", + "events": "3.3.0" + } + }, + "node_modules/@walletconnect/types/node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@walletconnect/types/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@walletconnect/types/node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/@walletconnect/utils": { + "version": "2.23.10", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-2.23.10.tgz", + "integrity": "sha512-b1c9FRF2g7vNnz66oLW5WZD2VCMrbu9xhpmwJJwqGarBiGW7cY8NbUtS9/w2/qc0vsBVKJ/bzDn4TGjpELU6aQ==", + "license": "SEE LICENSE IN LICENSE.md", + "dependencies": { + "@msgpack/msgpack": "3.1.3", + "@noble/ciphers": "1.3.0", + "@noble/curves": "1.9.7", + "@noble/hashes": "1.8.0", + "@scure/base": "1.2.6", + "@walletconnect/jsonrpc-utils": "1.0.8", + "@walletconnect/keyvaluestorage": "1.1.1", + "@walletconnect/logger": "3.0.2", + "@walletconnect/relay-api": "1.0.11", + "@walletconnect/relay-auth": "1.1.0", + "@walletconnect/safe-json": "1.0.2", + "@walletconnect/time": "1.0.2", + "@walletconnect/types": "2.23.10", + "@walletconnect/window-getters": "1.0.1", + "@walletconnect/window-metadata": "1.0.1", + "blakejs": "1.2.1", + "detect-browser": "5.3.0", + "ox": "0.9.3", + "uint8arrays": "3.1.1" + } + }, + "node_modules/@walletconnect/utils/node_modules/@noble/curves": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.7.tgz", + "integrity": "sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@walletconnect/utils/node_modules/@walletconnect/keyvaluestorage": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz", + "integrity": "sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA==", + "license": "MIT", + "dependencies": { + "@walletconnect/safe-json": "^1.0.1", + "idb-keyval": "^6.2.1", + "unstorage": "^1.9.0" + }, + "peerDependencies": { + "@react-native-async-storage/async-storage": "1.x" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@walletconnect/utils/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@walletconnect/utils/node_modules/unstorage": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^5.0.0", + "destr": "^2.0.5", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.3" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6 || ^7 || ^8", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1 || ^2 || ^3", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/@walletconnect/window-getters": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.1.tgz", + "integrity": "sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==", + "license": "MIT", + "dependencies": { + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/window-getters/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@walletconnect/window-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz", + "integrity": "sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA==", + "license": "MIT", + "dependencies": { + "@walletconnect/window-getters": "^1.0.1", + "tslib": "1.14.1" + } + }, + "node_modules/@walletconnect/window-metadata/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.14.tgz", + "integrity": "sha512-T4EDRUBVZYRldYApjEJiU0e1stYWaRAX7CuSnKzrpwdZKo53zGV8/pqfzV6FfwNl9YThD2OumQYvqtvjvgG7aQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/abitype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.3.0.tgz", + "integrity": "sha512-fk6Te+bojIFrMvMZrnOO+SxCB+RUksTGOzq/60ZRvs1L+BVzvi2bqt9L3W/17ZLdZsyM1FuYf65P5nlmoiH1Bg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3.22.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/agent-cli-detector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/agent-cli-detector/-/agent-cli-detector-0.1.6.tgz", + "integrity": "sha512-vKrPeEVN3upDF3GjWxsWBbwQgMtNJ8VB1cduPvK3svmmz4ENpS7yaPxbogsbe3w+xp9xp2Cu+0Ar41rjAR4+lA==", + "license": "MIT", + "bin": { + "agent-cli-detector": "dist/cli.js" + }, + "engines": { + "node": ">=18.18" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/await-lock": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", + "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==", + "license": "MIT" + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-react-compiler": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz", + "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + } + }, + "node_modules/babel-plugin-react-native-web": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.21.2.tgz", + "integrity": "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==", + "license": "MIT" + }, + "node_modules/babel-plugin-syntax-hermes-parser": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.36.1.tgz", + "integrity": "sha512-ycduwJbvdvIMmVvlAZqGggS+pm5Eu4Bk9pcV9Sm2Z4PJNRVsKkv0g7vHj+LeuC1gHTeF67sJXFOq61IlqCa2hA==", + "license": "MIT", + "dependencies": { + "hermes-parser": "0.36.1" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-expo": { + "version": "57.0.9", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-57.0.9.tgz", + "integrity": "sha512-T19biGOBTnMp161PyBqWOoSIEeZug8/EjtuUdVob8JPQKZMTalHUQaQt+qtQQE7XsEkZJ6erb3k0CohneTFzQg==", + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.20.5", + "@babel/helper-module-imports": "^7.25.9", + "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", @@ -3201,1835 +5284,3724 @@ "debug": "^4.3.4" }, "peerDependencies": { - "@babel/runtime": "^7.20.0", - "expo": "*", - "expo-widgets": "^57.0.13", - "react-refresh": ">=0.14.0 <1.0.0" + "@babel/runtime": "^7.20.0", + "expo": "*", + "expo-widgets": "^57.0.13", + "react-refresh": ">=0.14.0 <1.0.0" + }, + "peerDependenciesMeta": { + "@babel/runtime": { + "optional": true + }, + "expo": { + "optional": true + }, + "expo-widgets": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/barcode-detector": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-3.2.2.tgz", + "integrity": "sha512-/4QOrrNrCRmDSBWiiP4aC72dnkuXUEdcFRidHgbPRXUpy82XcCMvJssI6fEs6JT42LS7DvBVZO70qasJbYKyrA==", + "license": "MIT", + "dependencies": { + "zxing-wasm": "3.1.3" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.15", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.15.tgz", + "integrity": "sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "license": "MIT" + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chromium-edge-launcher": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.3.0.tgz", + "integrity": "sha512-p03azHlGjtyRvFEee3cyvtsRYdniSkwjkzmM/KmVnqT5d7QkkwpJBhis/zCLMYdQMVJ5tt140TBNqqrZPaWeFA==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie-es": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz", + "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.7" + }, + "engines": { + "node": ">=6.4.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "license": "MIT", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "license": "MIT", + "dependencies": { + "hyphenate-style-name": "^1.0.3" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-browser": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", + "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/dnssd-advertise": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/dnssd-advertise/-/dnssd-advertise-1.1.6.tgz", + "integrity": "sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg==", + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.411", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.411.tgz", + "integrity": "sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-toolkit": { + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.1.tgz", + "integrity": "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" }, "peerDependenciesMeta": { - "@babel/runtime": { + "jiti": { "optional": true - }, - "expo": { + } + } + }, + "node_modules/eslint-config-expo": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-expo/-/eslint-config-expo-57.0.2.tgz", + "integrity": "sha512-dOWkx+MWclLVnYpPPBzas4sfnPaAjk+fe/dbvJSzbWtHUR4fGGaTT/lTcOpxqhwRIlTKKBUYGKude0tcTBsZHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "^8.59.0", + "@typescript-eslint/parser": "^8.59.0", + "eslint-import-resolver-typescript": "^3.6.3", + "eslint-plugin-expo": "^1.1.0", + "eslint-plugin-import": "^2.30.0", + "eslint-plugin-react": "^7.37.3", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "^16.0.0" + }, + "peerDependencies": { + "eslint": ">=8.10" + } + }, + "node_modules/eslint-config-expo/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { "optional": true }, - "expo-widgets": { + "eslint-plugin-import-x": { "optional": true } } }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "node_modules/eslint-module-utils": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz", + "integrity": "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==", + "dev": true, "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/barcode-detector": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/barcode-detector/-/barcode-detector-3.2.2.tgz", - "integrity": "sha512-/4QOrrNrCRmDSBWiiP4aC72dnkuXUEdcFRidHgbPRXUpy82XcCMvJssI6fEs6JT42LS7DvBVZO70qasJbYKyrA==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "license": "MIT", "dependencies": { - "zxing-wasm": "3.1.3" + "ms": "^2.1.1" } }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/eslint-plugin-expo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-expo/-/eslint-plugin-expo-1.1.0.tgz", + "integrity": "sha512-vPP0EPx7IA7ZfP49dY4rq9RV5jqkFWG+Pih3/oGjzIRjMI+ogcOE8i6isYkLXAdw/yvFV2BRZkTaQaiOGQqn6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "^8.59.0", + "@typescript-eslint/utils": "^8.59.0", + "eslint": "^9.24.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "eslint": ">=8.10" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, - "node_modules/baseline-browser-mapping": { - "version": "2.11.15", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.15.tgz", - "integrity": "sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA==", - "license": "Apache-2.0", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", "bin": { - "baseline-browser-mapping": "dist/cli.cjs" + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "license": "Unlicense", + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-plugin-react-hooks/node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-react-hooks/node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=0.6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/bplist-creator": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", - "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, "license": "MIT", "dependencies": { - "stream-buffers": "2.2.x" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/bplist-parser": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", - "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", - "license": "MIT", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", "dependencies": { - "big-integer": "1.6.x" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 5.10.0" + "node": "*" } }, - "node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", - "license": "MIT", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "balanced-match": "^4.0.2" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "20 || >=22" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "fill-range": "^7.1.1" + "estraverse": "^5.1.0" }, "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "node_modules/browserslist": { - "version": "4.28.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", - "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "baseline-browser-mapping": "^2.11.12", - "caniuse-lite": "^1.0.30001809", - "electron-to-chromium": "^1.5.402", - "node-releases": "^2.0.53", - "update-browserslist-db": "^1.3.0" - }, - "bin": { - "browserslist": "cli.js" + "estraverse": "^5.2.0" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=4.0" } }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">= 0.6" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001809", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", - "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.8.x" } }, - "node_modules/chrome-launcher": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", - "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", - "license": "Apache-2.0", + "node_modules/expo": { + "version": "57.0.18", + "resolved": "https://registry.npmjs.org/expo/-/expo-57.0.18.tgz", + "integrity": "sha512-6nax9hJPhf9dWrstliXUABTJXDNIJrfJKcCtjSxuYVs2Yf127GIhKf3wsEYSFUl+LFdRbPPTNaweJePH159wZA==", + "license": "MIT", "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0" + "@babel/runtime": "^7.20.0", + "@expo/cli": "^57.0.20", + "@expo/config": "~57.0.9", + "@expo/config-plugins": "~57.0.9", + "@expo/devtools": "~57.0.1", + "@expo/dom-webview": "~57.0.1", + "@expo/fingerprint": "^0.20.11", + "@expo/local-build-cache-provider": "^57.0.8", + "@expo/log-box": "^57.0.4", + "@expo/metro": "~56.0.2", + "@expo/metro-config": "~57.0.12", + "@ungap/structured-clone": "^1.3.0", + "babel-preset-expo": "~57.0.9", + "expo-asset": "~57.0.15", + "expo-constants": "~57.0.16", + "expo-file-system": "~57.0.6", + "expo-font": "~57.0.2", + "expo-keep-awake": "~57.0.1", + "expo-modules-autolinking": "~57.0.12", + "expo-modules-core": "~57.0.14", + "pretty-format": "^29.7.0", + "react-refresh": "^0.14.2", + "whatwg-url-minimum": "^0.1.2" }, "bin": { - "print-chrome-path": "bin/print-chrome-path.js" + "expo": "bin/cli", + "expo-modules-autolinking": "bin/autolinking", + "fingerprint": "bin/fingerprint" }, - "engines": { - "node": ">=12.13.0" + "peerDependencies": { + "@expo/dom-webview": "*", + "@expo/metro-runtime": "*", + "react": "*", + "react-dom": "*", + "react-native": "*", + "react-native-web": "*", + "react-native-webview": "*" + }, + "peerDependenciesMeta": { + "@expo/dom-webview": { + "optional": true + }, + "@expo/metro-runtime": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native-web": { + "optional": true + }, + "react-native-webview": { + "optional": true + } } }, - "node_modules/chromium-edge-launcher": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.3.0.tgz", - "integrity": "sha512-p03azHlGjtyRvFEee3cyvtsRYdniSkwjkzmM/KmVnqT5d7QkkwpJBhis/zCLMYdQMVJ5tt140TBNqqrZPaWeFA==", - "license": "Apache-2.0", - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^1.0.0", - "mkdirp": "^1.0.4" + "node_modules/expo-application": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-57.0.2.tgz", + "integrity": "sha512-q31YwcXyymviAmdrtDfAg3Dld4VMxLCNAfgMHip7vZpPX4lzF/AfwsywqBJUAjQnJknzaNAkzqvMVjO5XmKYDA==", + "license": "MIT", + "peerDependencies": { + "expo": "*" } }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "license": "MIT" - }, - "node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "node_modules/expo-asset": { + "version": "57.0.15", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-57.0.15.tgz", + "integrity": "sha512-ZoiUftQb1Nn1jvL6l1kZoUXvgRCx57tMQYxSsp+g4ZvY+jgVWp/THruXOtPtZVdC/WWZxPUTct53bfAm2EPDAQ==", + "license": "MIT", + "dependencies": { + "@expo/image-utils": "^0.11.5", + "expo-constants": "~57.0.15" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-camera": { + "version": "57.0.4", + "resolved": "https://registry.npmjs.org/expo-camera/-/expo-camera-57.0.4.tgz", + "integrity": "sha512-MqbbQ63O+cA8JbK3lfFHiD0f2jv8jB+EG/ILK6f5xnOPV9IR37yaG5+lGtRZNoOeYBzGypyOi17USItleMyuGw==", "license": "MIT", "dependencies": { - "restore-cursor": "^2.0.0" + "barcode-detector": "^3.0.0" }, - "engines": { - "node": ">=4" + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } } }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/expo-clipboard": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-clipboard/-/expo-clipboard-57.0.1.tgz", + "integrity": "sha512-HWICri4+1ao7S6QEfcorxVumXDiDnx1guGGewjZgGJWLGxFYs0RgH8ujBs+lkTzBkMmlwADaWSlaesR+nDJt5Q==", "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", - "license": "MIT" - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", + "node_modules/expo-constants": { + "version": "57.0.16", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-57.0.16.tgz", + "integrity": "sha512-HG3yJjGZo2BPTo2F1sBoxdJZRwX7d9C554EhKn8m12K62pxGolCsvPSoh/lQf95OEP9vO34wwXB2C3QFs0KG0g==", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "@expo/env": "~2.4.3" }, - "engines": { - "node": ">=12" + "peerDependencies": { + "expo": "*", + "react-native": "*" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/expo-crypto": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-crypto/-/expo-crypto-57.0.2.tgz", + "integrity": "sha512-OGLvHK7Hb7qsONMWGB9pJw3n+iY4OnZQmM/KwQEHRMrrOmNg0Lxj9+tp9bj46aAMMzXx0FTVA2jUKoplpXPnkA==", "license": "MIT", - "engines": { - "node": ">=0.8" + "peerDependencies": { + "expo": "*" } }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "node_modules/expo-dev-client": { + "version": "57.0.16", + "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-57.0.16.tgz", + "integrity": "sha512-Txss9sgzEFI0E+4I34E76vPiukeVDHnqCj0ZXy8SDijVM31/P6MCNniVbEZk7MBPQclD0aopfuaCFtkV8+r1sw==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" + "expo-dev-launcher": "~57.0.16", + "expo-dev-menu": "~57.0.16", + "expo-dev-menu-interface": "~57.0.0", + "expo-manifests": "~57.0.1", + "expo-updates-interface": "~57.0.1" }, - "engines": { - "node": ">=12.5.0" + "peerDependencies": { + "expo": "*" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/expo-dev-launcher": { + "version": "57.0.16", + "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-57.0.16.tgz", + "integrity": "sha512-jaBr6q4A5js/r465m2mRxN8A87YOi8I6PiIt8XIt4qfQWDgw6hqGovaF1AVFGT1Z5jxkjtgK8WNz/rAeypjqPQ==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@expo/schema-utils": "^57.0.2", + "expo-dev-menu": "~57.0.16", + "expo-manifests": "~57.0.1" }, - "engines": { - "node": ">=7.0.0" + "peerDependencies": { + "expo": "*", + "react-native": "*" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "node_modules/expo-dev-menu": { + "version": "57.0.16", + "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-57.0.16.tgz", + "integrity": "sha512-KzMHtAmnr0GqyU6MCrKLzIo/AfOjcToGhzK+pFeXlcqSPOrPJbTGlZqQ3E1o2G2jZMs+M1XvXh/VgnRyJUaRGw==", "license": "MIT", "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "expo-dev-menu-interface": "~57.0.0" + }, + "peerDependencies": { + "expo": "*", + "react-native": "*" } }, - "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "node_modules/expo-dev-menu-interface": { + "version": "57.0.0", + "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-57.0.0.tgz", + "integrity": "sha512-F47VdzOHYc19FhI/jBgctpO8a5UskTIxG6a1E5t3W5gF8VImuvBQffdXXfLHhsuCl7dS3v3U0R45cleeVXO1Zg==", "license": "MIT", - "engines": { - "node": ">= 10" + "peerDependencies": { + "expo": "*" } }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "node_modules/expo-device": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-device/-/expo-device-57.0.1.tgz", + "integrity": "sha512-jyEMDUticH+dhcL3GHa2aiifOvGXJsmb3oVT2R2q4i8bN7Bddy61+NkpMmuS2VAZrvoLQwf0TJJ/1vi1ukvutA==", "license": "MIT", "dependencies": { - "mime-db": ">= 1.43.0 < 2" + "ua-parser-js": "^0.7.33" }, - "engines": { - "node": ">= 0.6" + "peerDependencies": { + "expo": "*" } }, - "node_modules/compression": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", - "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "node_modules/expo-file-system": { + "version": "57.0.6", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-57.0.6.tgz", + "integrity": "sha512-pm8PMYEW6BnVOCBJ7df9FcDmQtE1tqImuYphlfYe1ipQRLYtdCayRczJcbKIsnB3mqEyp4gC2gWmMbsAsAOjVg==", "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "compressible": "~2.0.18", - "debug": "2.6.9", - "negotiator": "~0.6.4", - "on-headers": "~1.1.0", - "safe-buffer": "5.2.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" + "peerDependencies": { + "expo": "*", + "react-native": "*" } }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/expo-font": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-57.0.2.tgz", + "integrity": "sha512-eWR0CAdysgVqg8VewJ8b5wKh1pa6C8YShIEU3SP0+hlSqOk4djUwuJjn3P04KHVzL3hws9FrUuPxCNmd4TGung==", "license": "MIT", "dependencies": { - "ms": "2.0.0" + "fontfaceobserver": "^2.1.0" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/compression/node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "node_modules/expo-glass-effect": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-glass-effect/-/expo-glass-effect-57.0.1.tgz", + "integrity": "sha512-m/n8maxqNcHk6ZDhuqXBfD5Kt1Iz3M8xykVgdB0iSCIXvF70IqWXmQhX8Psswhrp8eZ+3r0mAD0Jh/2gFA3QaA==", "license": "MIT", - "engines": { - "node": ">= 0.6" + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "node_modules/expo-image": { + "version": "57.0.3", + "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-57.0.3.tgz", + "integrity": "sha512-EYfV8tIQxXLQPHhgZxc+bESUn2NcVw1U0RM28qqFeFfHyD1sBpIYJC2JTy24OtfBowYVoUyTvgf2ykWydiZVCw==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "sf-symbols-typescript": "^2.2.0" }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } } }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/expo-json-utils": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-57.0.1.tgz", + "integrity": "sha512-cgTe1NqzQdYs/WN+3nIY5IZg8s0pb0xaTUbhYvxQDn137GbwRfHoGM2se3m3Vsl4Qu+B9G4RPEK5WJDEU2Do7g==", "license": "MIT" }, - "node_modules/core-js-compat": { - "version": "3.50.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz", - "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", + "node_modules/expo-keep-awake": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-57.0.1.tgz", + "integrity": "sha512-28lkFImeXTS+bhAjuCFV7w7tW5bXg27BJVrxv+nC/nyYa86qEa0oFeHwqol6ha5k4pdVDQgBF09GM4A1k76Ssg==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*" + } + }, + "node_modules/expo-linking": { + "version": "57.0.8", + "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-57.0.8.tgz", + "integrity": "sha512-gv0ZNaF7tILbcvX8xinNbQr6GIGQStxeUAJseweP+LjC9ped7Wl6EeyIMBlDR83U6Da+8drVeqBQSMvwAXgytA==", "license": "MIT", "dependencies": { - "browserslist": "^4.28.7" - }, - "engines": { - "node": ">=6.4.0" + "expo-constants": "~57.0.15", + "invariant": "^2.2.4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "peerDependencies": { + "react": "*", + "react-native": "*" } }, - "node_modules/cross-fetch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", - "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "node_modules/expo-local-authentication": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-local-authentication/-/expo-local-authentication-57.0.2.tgz", + "integrity": "sha512-8K4zcrQ5wZkRS1rwEWY8qHbeGVMNh35e9D1VTVKlMHz1O47itW+pW6iBVuqwGFLozN4fRBeEDQH8hu9Gt58YuQ==", "license": "MIT", "dependencies": { - "node-fetch": "^2.7.0" + "invariant": "^2.2.4" + }, + "peerDependencies": { + "expo": "*" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/expo-manifests": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-57.0.1.tgz", + "integrity": "sha512-qB/mDG2dYdl+EvUeQuqP8KFYCFgFCQjJYdWIHo8SFBgDzMYmdF286DFY2M1M9Okr99wkb5M4tgA3aCcwv3aEQA==", "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "expo-json-utils": "~57.0.1" }, - "engines": { - "node": ">= 8" + "peerDependencies": { + "expo": "*" } }, - "node_modules/css-in-js-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", - "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "node_modules/expo-modules-autolinking": { + "version": "57.0.12", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-57.0.12.tgz", + "integrity": "sha512-Q8KAlq37nLKsQ+HsS9NpQVpd5jCgqtu694TDUNHBUBpV9ViD82mRBh8Uug/h68RG9xnLS+kuL4nYaCuFRghHjg==", "license": "MIT", "dependencies": { - "hyphenate-style-name": "^1.0.3" + "@expo/require-utils": "^57.0.5", + "@expo/spawn-async": "^1.8.0", + "chalk": "^4.1.0", + "commander": "^7.2.0" + }, + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/expo-modules-core": { + "version": "57.0.14", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-57.0.14.tgz", + "integrity": "sha512-Cg3aQnVsQhZcMOF/RFgPGzMuhIak5W9eR9ecwmFSeQ813r4/49ut6RMA6PqUuUKuPCUIRqnBAHfSyTm1W9nfzg==", "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@expo/expo-modules-macros-plugin": "0.6.1", + "expo-modules-jsi": "~57.0.6", + "invariant": "^2.2.4" }, - "engines": { - "node": ">=6.0" + "peerDependencies": { + "react": "*", + "react-native": "*", + "react-native-worklets": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0" }, "peerDependenciesMeta": { - "supports-color": { + "react-native-worklets": { "optional": true } } }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/expo-modules-jsi": { + "version": "57.0.6", + "resolved": "https://registry.npmjs.org/expo-modules-jsi/-/expo-modules-jsi-57.0.6.tgz", + "integrity": "sha512-WK0xFEe0FdZTCLCdfXK+HVNYfAmEbA6goecRxqjr0gh3XYRKAr9tikxqcM0ItLQoEPKntscPZhWcPLGvr97Tfw==", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "react-native": "*" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/expo-router": { + "version": "57.0.17", + "resolved": "https://registry.npmjs.org/expo-router/-/expo-router-57.0.17.tgz", + "integrity": "sha512-zKAfGLxrbdkUFzzW1xHezLXPSa0V4DlYKEWweDUUFGgnPWPNy3OY0EKYAqOhlBGSDebAvtnJXn+2zyyJjYKwyg==", "license": "MIT", "dependencies": { - "clone": "^1.0.2" + "@expo/log-box": "^57.0.4", + "@expo/metro-runtime": "^57.0.14", + "@expo/schema-utils": "^57.0.2", + "@expo/ui": "^57.0.14", + "@radix-ui/react-slot": "^1.2.0", + "@radix-ui/react-tabs": "^1.1.12", + "@react-native-masked-view/masked-view": "^0.3.2", + "client-only": "^0.0.1", + "color": "^4.2.3", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "expo-glass-effect": "^57.0.1", + "expo-server": "^57.0.3", + "expo-symbols": "^57.0.2", + "fast-deep-equal": "^3.1.3", + "invariant": "^2.2.4", + "nanoid": "^3.3.8", + "query-string": "^7.1.3", + "react-fast-compare": "^3.2.2", + "react-is": "^19.1.0", + "react-native-drawer-layout": "^4.2.2", + "react-native-screens": "^4.26.0", + "server-only": "^0.0.1", + "sf-symbols-typescript": "^2.1.0", + "shallowequal": "^1.1.0", + "standard-navigation": "^0.0.5", + "vaul": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" + "peerDependencies": { + "@expo/log-box": "^57.0.4", + "@expo/metro-runtime": "^57.0.14", + "@testing-library/react-native": ">= 13.2.0", + "expo": "*", + "expo-constants": "^57.0.15", + "expo-linking": "^57.0.8", + "react": "*", + "react-dom": "*", + "react-native": "*", + "react-native-gesture-handler": "*", + "react-native-reanimated": "*", + "react-native-safe-area-context": ">= 5.4.0", + "react-native-screens": "^4.26.0", + "react-native-web": "*", + "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" + }, + "peerDependenciesMeta": { + "@testing-library/react-native": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native-gesture-handler": { + "optional": true + }, + "react-native-reanimated": { + "optional": true + }, + "react-native-web": { + "optional": true + }, + "react-server-dom-webpack": { + "optional": true + } } }, - "node_modules/detect-node-es": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", - "license": "MIT" - }, - "node_modules/dnssd-advertise": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/dnssd-advertise/-/dnssd-advertise-1.1.6.tgz", - "integrity": "sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg==", - "license": "MIT" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.411", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.411.tgz", - "integrity": "sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg==", - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" + "node_modules/expo-secure-store": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-57.0.2.tgz", + "integrity": "sha512-PhrPMKnI7YSObLEQZOoP9evB2ZOCv9kFuG2L7cZfNlOwWjGbir711PlppkXVoM3JE8vamDrTqzMLGv266FhJJg==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/expo-server": { + "version": "57.0.3", + "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-57.0.3.tgz", + "integrity": "sha512-aK+LdKzauHSGmsOStZtyxdzv0zWssCkxTw3m4QuOhfDSJsZaMRTd9O41d8ixU/QfELTbaJ0oRNcF7JFV/7O9YQ==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=20.16.0" } }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "node_modules/expo-splash-screen": { + "version": "57.0.8", + "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-57.0.8.tgz", + "integrity": "sha512-BEsrKg4niYBZa5AFzWRyGqxA4ZemtBOPwbCy+C336iGYYPuZYLEgWJGmm2xD1gRfCdrM/TP+l2ONd86Zvk3KyA==", "license": "MIT", "dependencies": { - "stackframe": "^1.3.4" + "@expo/config-plugins": "~57.0.9", + "@expo/image-utils": "^0.11.5", + "xml2js": "0.6.0" + }, + "peerDependencies": { + "expo": "*" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/expo-sqlite": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-sqlite/-/expo-sqlite-57.0.2.tgz", + "integrity": "sha512-5KVbT7BQFZlIcQBXKWvwBERK3ODF6PSqct27GQKukZzAjsx2B97R+mwtYqrTUtUbw71VJrQrdr9Yl2OWYC7UpA==", "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "await-lock": "^2.2.2" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/expo-status-bar": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-57.0.1.tgz", + "integrity": "sha512-Xwaq1gAoVRWx5dPG5VhT5RSbnI9OilhZnO5qoPBnUaBAa5VzRzfdS8q0/bsPt0jR2DKLtGuP0bQ6efMJ4RIMDg==", "license": "MIT", - "engines": { - "node": ">=6" + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" + "node_modules/expo-symbols": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-symbols/-/expo-symbols-57.0.2.tgz", + "integrity": "sha512-qZ0iqOflm5lZGwRsQ5Y8sDksw3GAUKwHSX1bJBoocXf7gu14vafIXXYWte+JT9VfXAUGyKodJhLHP/GoOrcNWg==", + "license": "MIT", + "dependencies": { + "@expo-google-fonts/material-symbols": "^0.4.1", + "sf-symbols-typescript": "^2.0.0" + }, + "peerDependencies": { + "expo": "*", + "expo-font": "*", + "react": "*", + "react-native": "*" + } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/expo-system-ui": { + "version": "57.0.3", + "resolved": "https://registry.npmjs.org/expo-system-ui/-/expo-system-ui-57.0.3.tgz", + "integrity": "sha512-3N3BoagGojEvQw0h7kL0Lvv2LrVjqEvODSNS+Nc9lj/kzaTaVx4K1HI8qqxeALMf5jui3rLP2b3Ai2pXotoNuA==", "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@react-native/normalize-colors": "0.86.3", + "debug": "^4.3.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "expo": "*", + "react-native": "*", + "react-native-web": "*" + }, + "peerDependenciesMeta": { + "react-native-web": { + "optional": true + } } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/expo-updates-interface": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-57.0.1.tgz", + "integrity": "sha512-+LUWwJ0gf/TEKMVdQAw/Gjih4dvrk+URgy24X9qEGKuuMDZqjBRm9T4yQyBVALGL5TTdPUaB6ILxx3lshm3pwQ==", "license": "MIT", - "engines": { - "node": ">= 0.6" + "peerDependencies": { + "expo": "*" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/expo-web-browser": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-57.0.2.tgz", + "integrity": "sha512-3vl5kvd7PB48ub6PpNIJUuPxO8xVa6D8RnIgNba6SXRwqFprOfeEZgwTgtm41kz0AAtvMOztUVNEUkwrHKjqMQ==", "license": "MIT", - "engines": { - "node": ">=6" + "peerDependencies": { + "expo": "*", + "react-native": "*" } }, - "node_modules/expo": { - "version": "57.0.18", - "resolved": "https://registry.npmjs.org/expo/-/expo-57.0.18.tgz", - "integrity": "sha512-6nax9hJPhf9dWrstliXUABTJXDNIJrfJKcCtjSxuYVs2Yf127GIhKf3wsEYSFUl+LFdRbPPTNaweJePH159wZA==", + "node_modules/expo/node_modules/@expo/cli": { + "version": "57.0.20", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-57.0.20.tgz", + "integrity": "sha512-ZjWz7SA5TBTyKq4+aFRUPgMFxmqHtKkDMv6d85J2UAAjdRhkNRf+B80t+rr5IFo2ywuTvyrPRBth4ei4w08olA==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.20.0", - "@expo/cli": "^57.0.20", + "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~57.0.9", "@expo/config-plugins": "~57.0.9", - "@expo/devtools": "~57.0.1", - "@expo/dom-webview": "~57.0.1", - "@expo/fingerprint": "^0.20.11", - "@expo/local-build-cache-provider": "^57.0.8", + "@expo/devcert": "^1.2.1", + "@expo/env": "~2.4.3", + "@expo/image-utils": "^0.11.5", + "@expo/inline-modules": "^0.1.7", + "@expo/json-file": "^11.0.1", "@expo/log-box": "^57.0.4", "@expo/metro": "~56.0.2", "@expo/metro-config": "~57.0.12", - "@ungap/structured-clone": "^1.3.0", - "babel-preset-expo": "~57.0.9", - "expo-asset": "~57.0.15", - "expo-constants": "~57.0.16", - "expo-file-system": "~57.0.6", - "expo-font": "~57.0.2", - "expo-keep-awake": "~57.0.1", - "expo-modules-autolinking": "~57.0.12", - "expo-modules-core": "~57.0.14", + "@expo/metro-file-map": "^57.0.2", + "@expo/osascript": "^2.7.1", + "@expo/package-manager": "^1.13.1", + "@expo/plist": "^0.8.1", + "@expo/prebuild-config": "^57.0.15", + "@expo/require-utils": "^57.0.5", + "@expo/router-server": "^57.0.8", + "@expo/schema-utils": "^57.0.2", + "@expo/spawn-async": "^1.8.0", + "@expo/ws-tunnel": "^2.0.0", + "@expo/xcpretty": "^4.4.4", + "@react-native/dev-middleware": "0.86.3", + "accepts": "^1.3.8", + "agent-cli-detector": "0.1.6", + "arg": "^5.0.2", + "bplist-creator": "0.1.0", + "bplist-parser": "^0.3.1", + "chalk": "^4.0.0", + "ci-info": "^3.3.0", + "compression": "^1.7.4", + "connect": "^3.7.0", + "debug": "^4.3.4", + "dnssd-advertise": "^1.1.4", + "expo-server": "^57.0.3", + "fetch-nodeshim": "^0.4.10", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "lan-network": "^0.2.1", + "multitars": "^1.0.2", + "node-forge": "^1.3.3", + "npm-package-arg": "^11.0.0", + "ora": "^3.4.0", + "picomatch": "^4.0.4", "pretty-format": "^29.7.0", - "react-refresh": "^0.14.2", - "whatwg-url-minimum": "^0.1.2" + "progress": "^2.0.3", + "prompts": "^2.3.2", + "resolve-from": "^5.0.0", + "sandbox-cli-detector": "^0.2.0", + "semver": "^7.6.0", + "send": "^0.19.0", + "slugify": "^1.3.4", + "stacktrace-parser": "^0.1.10", + "structured-headers": "^0.4.1", + "terminal-link": "^2.1.1", + "toqr": "^0.1.1", + "wrap-ansi": "^7.0.0", + "ws": "^8.12.1", + "zod": "^3.25.76" }, "bin": { - "expo": "bin/cli", - "expo-modules-autolinking": "bin/autolinking", - "fingerprint": "bin/fingerprint" + "expo-internal": "main.js" }, "peerDependencies": { - "@expo/dom-webview": "*", - "@expo/metro-runtime": "*", - "react": "*", - "react-dom": "*", - "react-native": "*", - "react-native-web": "*", - "react-native-webview": "*" + "expo": "*", + "expo-router": "*", + "react-native": "*" }, "peerDependenciesMeta": { - "@expo/dom-webview": { - "optional": true - }, - "@expo/metro-runtime": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-native-web": { + "expo-router": { "optional": true }, - "react-native-webview": { + "react-native": { "optional": true } } }, - "node_modules/expo-asset": { - "version": "57.0.15", - "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-57.0.15.tgz", - "integrity": "sha512-ZoiUftQb1Nn1jvL6l1kZoUXvgRCx57tMQYxSsp+g4ZvY+jgVWp/THruXOtPtZVdC/WWZxPUTct53bfAm2EPDAQ==", - "license": "MIT", - "dependencies": { - "@expo/image-utils": "^0.11.5", - "expo-constants": "~57.0.15" - }, - "peerDependencies": { - "expo": "*", - "react": "*", - "react-native": "*" - } - }, - "node_modules/expo-camera": { - "version": "57.0.4", - "resolved": "https://registry.npmjs.org/expo-camera/-/expo-camera-57.0.4.tgz", - "integrity": "sha512-MqbbQ63O+cA8JbK3lfFHiD0f2jv8jB+EG/ILK6f5xnOPV9IR37yaG5+lGtRZNoOeYBzGypyOi17USItleMyuGw==", + "node_modules/expo/node_modules/@expo/cli/node_modules/@expo/router-server": { + "version": "57.0.8", + "resolved": "https://registry.npmjs.org/@expo/router-server/-/router-server-57.0.8.tgz", + "integrity": "sha512-lEPGYoDmh97yyEcY/MFWQsfE7yIgMRnGDcnsBN7B6AiWBFSJIMEcGnO0aYPgY0ZjNWyJDi7Ee8QZRGqB+LhI6w==", "license": "MIT", "dependencies": { - "barcode-detector": "^3.0.0" + "debug": "^4.3.4" }, "peerDependencies": { + "@expo/metro-runtime": "^57.0.14", "expo": "*", + "expo-constants": "^57.0.15", + "expo-font": "^57.0.1", + "expo-router": "*", + "expo-server": "^57.0.3", "react": "*", - "react-native": "*", - "react-native-web": "*" + "react-dom": "*", + "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "peerDependenciesMeta": { - "react-native-web": { + "@expo/metro-runtime": { + "optional": true + }, + "expo-router": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-server-dom-webpack": { "optional": true } } }, - "node_modules/expo-constants": { - "version": "57.0.16", - "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-57.0.16.tgz", - "integrity": "sha512-HG3yJjGZo2BPTo2F1sBoxdJZRwX7d9C554EhKn8m12K62pxGolCsvPSoh/lQf95OEP9vO34wwXB2C3QFs0KG0g==", + "node_modules/expo/node_modules/@expo/ws-tunnel": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-2.0.0.tgz", + "integrity": "sha512-j+JfTRdCk820J9dU0sA2SqshQIKFOMo7ED84w9MJFcebfbNQgsLztEY/SABDkGnjatrW4xGqnUhVRxSBVyCkXw==", "license": "MIT", - "dependencies": { - "@expo/env": "~2.4.3" - }, "peerDependencies": { - "expo": "*", - "react-native": "*" + "ws": "^8.0.0" } }, - "node_modules/expo-dev-client": { - "version": "57.0.16", - "resolved": "https://registry.npmjs.org/expo-dev-client/-/expo-dev-client-57.0.16.tgz", - "integrity": "sha512-Txss9sgzEFI0E+4I34E76vPiukeVDHnqCj0ZXy8SDijVM31/P6MCNniVbEZk7MBPQclD0aopfuaCFtkV8+r1sw==", + "node_modules/expo/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", "dependencies": { - "expo-dev-launcher": "~57.0.16", - "expo-dev-menu": "~57.0.16", - "expo-dev-menu-interface": "~57.0.0", - "expo-manifests": "~57.0.1", - "expo-updates-interface": "~57.0.1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, - "peerDependencies": { - "expo": "*" + "engines": { + "node": ">= 0.6" } }, - "node_modules/expo-dev-launcher": { - "version": "57.0.16", - "resolved": "https://registry.npmjs.org/expo-dev-launcher/-/expo-dev-launcher-57.0.16.tgz", - "integrity": "sha512-jaBr6q4A5js/r465m2mRxN8A87YOi8I6PiIt8XIt4qfQWDgw6hqGovaF1AVFGT1Z5jxkjtgK8WNz/rAeypjqPQ==", + "node_modules/expo/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "dependencies": { - "@expo/schema-utils": "^57.0.2", - "expo-dev-menu": "~57.0.16", - "expo-manifests": "~57.0.1" - }, - "peerDependencies": { - "expo": "*", - "react-native": "*" + "engines": { + "node": ">=8" } }, - "node_modules/expo-dev-menu": { - "version": "57.0.16", - "resolved": "https://registry.npmjs.org/expo-dev-menu/-/expo-dev-menu-57.0.16.tgz", - "integrity": "sha512-KzMHtAmnr0GqyU6MCrKLzIo/AfOjcToGhzK+pFeXlcqSPOrPJbTGlZqQ3E1o2G2jZMs+M1XvXh/VgnRyJUaRGw==", + "node_modules/expo/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/expo/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { - "expo-dev-menu-interface": "~57.0.0" + "mime-db": "1.52.0" }, - "peerDependencies": { - "expo": "*", - "react-native": "*" + "engines": { + "node": ">= 0.6" } }, - "node_modules/expo-dev-menu-interface": { - "version": "57.0.0", - "resolved": "https://registry.npmjs.org/expo-dev-menu-interface/-/expo-dev-menu-interface-57.0.0.tgz", - "integrity": "sha512-F47VdzOHYc19FhI/jBgctpO8a5UskTIxG6a1E5t3W5gF8VImuvBQffdXXfLHhsuCl7dS3v3U0R45cleeVXO1Zg==", + "node_modules/expo/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "license": "MIT", - "peerDependencies": { - "expo": "*" + "engines": { + "node": ">= 0.6" } }, - "node_modules/expo-device": { - "version": "57.0.1", - "resolved": "https://registry.npmjs.org/expo-device/-/expo-device-57.0.1.tgz", - "integrity": "sha512-jyEMDUticH+dhcL3GHa2aiifOvGXJsmb3oVT2R2q4i8bN7Bddy61+NkpMmuS2VAZrvoLQwf0TJJ/1vi1ukvutA==", + "node_modules/expo/node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", "license": "MIT", - "dependencies": { - "ua-parser-js": "^0.7.33" + "engines": { + "node": ">=10.0.0" }, "peerDependencies": { - "expo": "*" + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/expo-file-system": { - "version": "57.0.6", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-57.0.6.tgz", - "integrity": "sha512-pm8PMYEW6BnVOCBJ7df9FcDmQtE1tqImuYphlfYe1ipQRLYtdCayRczJcbKIsnB3mqEyp4gC2gWmMbsAsAOjVg==", + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "license": "Apache-2.0" + }, + "node_modules/fast-base64-decode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz", + "integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-text-encoding": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==", + "license": "Apache-2.0" + }, + "node_modules/fb-dotslash": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz", + "integrity": "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "dotslash": "bin/dotslash" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fbjs": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", + "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", "license": "MIT", - "peerDependencies": { - "expo": "*", - "react-native": "*" + "dependencies": { + "cross-fetch": "^3.1.5", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^1.0.35" } }, - "node_modules/expo-font": { - "version": "57.0.2", - "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-57.0.2.tgz", - "integrity": "sha512-eWR0CAdysgVqg8VewJ8b5wKh1pa6C8YShIEU3SP0+hlSqOk4djUwuJjn3P04KHVzL3hws9FrUuPxCNmd4TGung==", + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", + "license": "MIT" + }, + "node_modules/fbjs/node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "license": "MIT", "dependencies": { - "fontfaceobserver": "^2.1.0" - }, - "peerDependencies": { - "expo": "*", - "react": "*", - "react-native": "*" + "asap": "~2.0.3" } }, - "node_modules/expo-glass-effect": { - "version": "57.0.1", - "resolved": "https://registry.npmjs.org/expo-glass-effect/-/expo-glass-effect-57.0.1.tgz", - "integrity": "sha512-m/n8maxqNcHk6ZDhuqXBfD5Kt1Iz3M8xykVgdB0iSCIXvF70IqWXmQhX8Psswhrp8eZ+3r0mAD0Jh/2gFA3QaA==", + "node_modules/fbjs/node_modules/ua-parser-js": { + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", + "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], "license": "MIT", - "peerDependencies": { - "expo": "*", - "react": "*", - "react-native": "*" + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" } }, - "node_modules/expo-image": { - "version": "57.0.3", - "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-57.0.3.tgz", - "integrity": "sha512-EYfV8tIQxXLQPHhgZxc+bESUn2NcVw1U0RM28qqFeFfHyD1sBpIYJC2JTy24OtfBowYVoUyTvgf2ykWydiZVCw==", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", - "dependencies": { - "sf-symbols-typescript": "^2.2.0" + "engines": { + "node": ">=12.0.0" }, "peerDependencies": { - "expo": "*", - "react": "*", - "react-native": "*", - "react-native-web": "*" + "picomatch": "^3 || ^4" }, "peerDependenciesMeta": { - "react-native-web": { + "picomatch": { "optional": true } } }, - "node_modules/expo-json-utils": { - "version": "57.0.1", - "resolved": "https://registry.npmjs.org/expo-json-utils/-/expo-json-utils-57.0.1.tgz", - "integrity": "sha512-cgTe1NqzQdYs/WN+3nIY5IZg8s0pb0xaTUbhYvxQDn137GbwRfHoGM2se3m3Vsl4Qu+B9G4RPEK5WJDEU2Do7g==", + "node_modules/fetch-nodeshim": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/fetch-nodeshim/-/fetch-nodeshim-0.4.10.tgz", + "integrity": "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==", "license": "MIT" }, - "node_modules/expo-keep-awake": { - "version": "57.0.1", - "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-57.0.1.tgz", - "integrity": "sha512-28lkFImeXTS+bhAjuCFV7w7tW5bXg27BJVrxv+nC/nyYa86qEa0oFeHwqol6ha5k4pdVDQgBF09GM4A1k76Ssg==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, "license": "MIT", - "peerDependencies": { - "expo": "*", - "react": "*" + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/expo-linking": { - "version": "57.0.8", - "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-57.0.8.tgz", - "integrity": "sha512-gv0ZNaF7tILbcvX8xinNbQr6GIGQStxeUAJseweP+LjC9ped7Wl6EeyIMBlDR83U6Da+8drVeqBQSMvwAXgytA==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "license": "MIT", "dependencies": { - "expo-constants": "~57.0.15", - "invariant": "^2.2.4" + "to-regex-range": "^5.0.1" }, - "peerDependencies": { - "react": "*", - "react-native": "*" + "engines": { + "node": ">=8" } }, - "node_modules/expo-local-authentication": { - "version": "57.0.2", - "resolved": "https://registry.npmjs.org/expo-local-authentication/-/expo-local-authentication-57.0.2.tgz", - "integrity": "sha512-8K4zcrQ5wZkRS1rwEWY8qHbeGVMNh35e9D1VTVKlMHz1O47itW+pW6iBVuqwGFLozN4fRBeEDQH8hu9Gt58YuQ==", + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "license": "MIT", "dependencies": { - "invariant": "^2.2.4" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" }, - "peerDependencies": { - "expo": "*" + "engines": { + "node": ">= 0.8" } }, - "node_modules/expo-manifests": { - "version": "57.0.1", - "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-57.0.1.tgz", - "integrity": "sha512-qB/mDG2dYdl+EvUeQuqP8KFYCFgFCQjJYdWIHo8SFBgDzMYmdF286DFY2M1M9Okr99wkb5M4tgA3aCcwv3aEQA==", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "expo-json-utils": "~57.0.1" + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, - "peerDependencies": { - "expo": "*" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/expo-modules-autolinking": { - "version": "57.0.12", - "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-57.0.12.tgz", - "integrity": "sha512-Q8KAlq37nLKsQ+HsS9NpQVpd5jCgqtu694TDUNHBUBpV9ViD82mRBh8Uug/h68RG9xnLS+kuL4nYaCuFRghHjg==", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, "license": "MIT", "dependencies": { - "@expo/require-utils": "^57.0.5", - "@expo/spawn-async": "^1.8.0", - "chalk": "^4.1.0", - "commander": "^7.2.0" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, - "bin": { - "expo-modules-autolinking": "bin/expo-modules-autolinking.js" + "engines": { + "node": ">=16" } }, - "node_modules/expo-modules-core": { - "version": "57.0.14", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-57.0.14.tgz", - "integrity": "sha512-Cg3aQnVsQhZcMOF/RFgPGzMuhIak5W9eR9ecwmFSeQ813r4/49ut6RMA6PqUuUKuPCUIRqnBAHfSyTm1W9nfzg==", + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "license": "MIT" + }, + "node_modules/fontfaceobserver": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz", + "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==", + "license": "BSD-2-Clause" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, "license": "MIT", "dependencies": { - "@expo/expo-modules-macros-plugin": "0.6.1", - "expo-modules-jsi": "~57.0.6", - "invariant": "^2.2.4" + "is-callable": "^1.2.7" }, - "peerDependencies": { - "react": "*", - "react-native": "*", - "react-native-worklets": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "react-native-worklets": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expo-modules-jsi": { - "version": "57.0.6", - "resolved": "https://registry.npmjs.org/expo-modules-jsi/-/expo-modules-jsi-57.0.6.tgz", - "integrity": "sha512-WK0xFEe0FdZTCLCdfXK+HVNYfAmEbA6goecRxqjr0gh3XYRKAr9tikxqcM0ItLQoEPKntscPZhWcPLGvr97Tfw==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", - "peerDependencies": { - "react-native": "*" + "engines": { + "node": ">= 0.6" } }, - "node_modules/expo-router": { - "version": "57.0.17", - "resolved": "https://registry.npmjs.org/expo-router/-/expo-router-57.0.17.tgz", - "integrity": "sha512-zKAfGLxrbdkUFzzW1xHezLXPSa0V4DlYKEWweDUUFGgnPWPNy3OY0EKYAqOhlBGSDebAvtnJXn+2zyyJjYKwyg==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, "license": "MIT", "dependencies": { - "@expo/log-box": "^57.0.4", - "@expo/metro-runtime": "^57.0.14", - "@expo/schema-utils": "^57.0.2", - "@expo/ui": "^57.0.14", - "@radix-ui/react-slot": "^1.2.0", - "@radix-ui/react-tabs": "^1.1.12", - "@react-native-masked-view/masked-view": "^0.3.2", - "client-only": "^0.0.1", - "color": "^4.2.3", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "expo-glass-effect": "^57.0.1", - "expo-server": "^57.0.3", - "expo-symbols": "^57.0.2", - "fast-deep-equal": "^3.1.3", - "invariant": "^2.2.4", - "nanoid": "^3.3.8", - "query-string": "^7.1.3", - "react-fast-compare": "^3.2.2", - "react-is": "^19.1.0", - "react-native-drawer-layout": "^4.2.2", - "react-native-screens": "^4.26.0", - "server-only": "^0.0.1", - "sf-symbols-typescript": "^2.1.0", - "shallowequal": "^1.1.0", - "standard-navigation": "^0.0.5", - "vaul": "^1.1.2" + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" }, - "peerDependencies": { - "@expo/log-box": "^57.0.4", - "@expo/metro-runtime": "^57.0.14", - "@testing-library/react-native": ">= 13.2.0", - "expo": "*", - "expo-constants": "^57.0.15", - "expo-linking": "^57.0.8", - "react": "*", - "react-dom": "*", - "react-native": "*", - "react-native-gesture-handler": "*", - "react-native-reanimated": "*", - "react-native-safe-area-context": ">= 5.4.0", - "react-native-screens": "^4.26.0", - "react-native-web": "*", - "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@testing-library/react-native": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-native-gesture-handler": { - "optional": true - }, - "react-native-reanimated": { - "optional": true - }, - "react-native-web": { - "optional": true - }, - "react-server-dom-webpack": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "node_modules/expo-secure-store": { - "version": "57.0.2", - "resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-57.0.2.tgz", - "integrity": "sha512-PhrPMKnI7YSObLEQZOoP9evB2ZOCv9kFuG2L7cZfNlOwWjGbir711PlppkXVoM3JE8vamDrTqzMLGv266FhJJg==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "license": "MIT", - "peerDependencies": { - "expo": "*" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/expo-server": { - "version": "57.0.3", - "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-57.0.3.tgz", - "integrity": "sha512-aK+LdKzauHSGmsOStZtyxdzv0zWssCkxTw3m4QuOhfDSJsZaMRTd9O41d8ixU/QfELTbaJ0oRNcF7JFV/7O9YQ==", - "license": "MIT", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { - "node": ">=20.16.0" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/expo-splash-screen": { - "version": "57.0.8", - "resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-57.0.8.tgz", - "integrity": "sha512-BEsrKg4niYBZa5AFzWRyGqxA4ZemtBOPwbCy+C336iGYYPuZYLEgWJGmm2xD1gRfCdrM/TP+l2ONd86Zvk3KyA==", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, "license": "MIT", "dependencies": { - "@expo/config-plugins": "~57.0.9", - "@expo/image-utils": "^0.11.5", - "xml2js": "0.6.0" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, - "peerDependencies": { - "expo": "*" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expo-sqlite": { - "version": "57.0.2", - "resolved": "https://registry.npmjs.org/expo-sqlite/-/expo-sqlite-57.0.2.tgz", - "integrity": "sha512-5KVbT7BQFZlIcQBXKWvwBERK3ODF6PSqct27GQKukZzAjsx2B97R+mwtYqrTUtUbw71VJrQrdr9Yl2OWYC7UpA==", + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, "license": "MIT", "dependencies": { - "await-lock": "^2.2.2" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, - "peerDependencies": { - "expo": "*", - "react": "*", - "react-native": "*" + "engines": { + "node": ">= 0.4" } }, - "node_modules/expo-status-bar": { - "version": "57.0.1", - "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-57.0.1.tgz", - "integrity": "sha512-Xwaq1gAoVRWx5dPG5VhT5RSbnI9OilhZnO5qoPBnUaBAa5VzRzfdS8q0/bsPt0jR2DKLtGuP0bQ6efMJ4RIMDg==", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, "license": "MIT", - "peerDependencies": { - "expo": "*", - "react": "*", - "react-native": "*" + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expo-symbols": { - "version": "57.0.2", - "resolved": "https://registry.npmjs.org/expo-symbols/-/expo-symbols-57.0.2.tgz", - "integrity": "sha512-qZ0iqOflm5lZGwRsQ5Y8sDksw3GAUKwHSX1bJBoocXf7gu14vafIXXYWte+JT9VfXAUGyKodJhLHP/GoOrcNWg==", + "node_modules/get-tsconfig": { + "version": "4.14.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.3.tgz", + "integrity": "sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==", + "dev": true, "license": "MIT", "dependencies": { - "@expo-google-fonts/material-symbols": "^0.4.1", - "sf-symbols-typescript": "^2.0.0" + "resolve-pkg-maps": "^1.0.0" }, - "peerDependencies": { - "expo": "*", - "expo-font": "*", - "react": "*", - "react-native": "*" + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/expo-system-ui": { - "version": "57.0.3", - "resolved": "https://registry.npmjs.org/expo-system-ui/-/expo-system-ui-57.0.3.tgz", - "integrity": "sha512-3N3BoagGojEvQw0h7kL0Lvv2LrVjqEvODSNS+Nc9lj/kzaTaVx4K1HI8qqxeALMf5jui3rLP2b3Ai2pXotoNuA==", + "node_modules/getenv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/getenv/-/getenv-2.0.0.tgz", + "integrity": "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==", "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "license": "BlueOak-1.0.0", "dependencies": { - "@react-native/normalize-colors": "0.86.3", - "debug": "^4.3.2" + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" }, - "peerDependencies": { - "expo": "*", - "react-native": "*", - "react-native-web": "*" + "engines": { + "node": "18 || 20 || >=22" }, - "peerDependenciesMeta": { - "react-native-web": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/expo-updates-interface": { - "version": "57.0.1", - "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-57.0.1.tgz", - "integrity": "sha512-+LUWwJ0gf/TEKMVdQAw/Gjih4dvrk+URgy24X9qEGKuuMDZqjBRm9T4yQyBVALGL5TTdPUaB6ILxx3lshm3pwQ==", - "license": "MIT", - "peerDependencies": { - "expo": "*" + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/expo-web-browser": { - "version": "57.0.2", - "resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-57.0.2.tgz", - "integrity": "sha512-3vl5kvd7PB48ub6PpNIJUuPxO8xVa6D8RnIgNba6SXRwqFprOfeEZgwTgtm41kz0AAtvMOztUVNEUkwrHKjqMQ==", + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, "license": "MIT", - "peerDependencies": { - "expo": "*", - "react-native": "*" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/expo/node_modules/@expo/cli": { - "version": "57.0.20", - "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-57.0.20.tgz", - "integrity": "sha512-ZjWz7SA5TBTyKq4+aFRUPgMFxmqHtKkDMv6d85J2UAAjdRhkNRf+B80t+rr5IFo2ywuTvyrPRBth4ei4w08olA==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, "license": "MIT", "dependencies": { - "@expo/code-signing-certificates": "^0.0.6", - "@expo/config": "~57.0.9", - "@expo/config-plugins": "~57.0.9", - "@expo/devcert": "^1.2.1", - "@expo/env": "~2.4.3", - "@expo/image-utils": "^0.11.5", - "@expo/inline-modules": "^0.1.7", - "@expo/json-file": "^11.0.1", - "@expo/log-box": "^57.0.4", - "@expo/metro": "~56.0.2", - "@expo/metro-config": "~57.0.12", - "@expo/metro-file-map": "^57.0.2", - "@expo/osascript": "^2.7.1", - "@expo/package-manager": "^1.13.1", - "@expo/plist": "^0.8.1", - "@expo/prebuild-config": "^57.0.15", - "@expo/require-utils": "^57.0.5", - "@expo/router-server": "^57.0.8", - "@expo/schema-utils": "^57.0.2", - "@expo/spawn-async": "^1.8.0", - "@expo/ws-tunnel": "^2.0.0", - "@expo/xcpretty": "^4.4.4", - "@react-native/dev-middleware": "0.86.3", - "accepts": "^1.3.8", - "agent-cli-detector": "0.1.6", - "arg": "^5.0.2", - "bplist-creator": "0.1.0", - "bplist-parser": "^0.3.1", - "chalk": "^4.0.0", - "ci-info": "^3.3.0", - "compression": "^1.7.4", - "connect": "^3.7.0", - "debug": "^4.3.4", - "dnssd-advertise": "^1.1.4", - "expo-server": "^57.0.3", - "fetch-nodeshim": "^0.4.10", - "getenv": "^2.0.0", - "glob": "^13.0.0", - "lan-network": "^0.2.1", - "multitars": "^1.0.2", - "node-forge": "^1.3.3", - "npm-package-arg": "^11.0.0", - "ora": "^3.4.0", - "picomatch": "^4.0.4", - "pretty-format": "^29.7.0", - "progress": "^2.0.3", - "prompts": "^2.3.2", - "resolve-from": "^5.0.0", - "sandbox-cli-detector": "^0.2.0", - "semver": "^7.6.0", - "send": "^0.19.0", - "slugify": "^1.3.4", - "stacktrace-parser": "^0.1.10", - "structured-headers": "^0.4.1", - "terminal-link": "^2.1.1", - "toqr": "^0.1.1", - "wrap-ansi": "^7.0.0", - "ws": "^8.12.1", - "zod": "^3.25.76" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, - "bin": { - "expo-internal": "main.js" + "engines": { + "node": ">= 0.4" }, - "peerDependencies": { - "expo": "*", - "expo-router": "*", - "react-native": "*" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/h3": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", + "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==", + "license": "MIT", + "dependencies": { + "cookie-es": "^1.2.3", + "crossws": "^0.3.5", + "defu": "^6.1.6", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.4", + "radix3": "^1.1.2", + "ufo": "^1.6.3", + "uncrypto": "^0.1.3" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" }, - "peerDependenciesMeta": { - "expo-router": { - "optional": true - }, - "react-native": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expo/node_modules/@expo/cli/node_modules/@expo/router-server": { - "version": "57.0.8", - "resolved": "https://registry.npmjs.org/@expo/router-server/-/router-server-57.0.8.tgz", - "integrity": "sha512-lEPGYoDmh97yyEcY/MFWQsfE7yIgMRnGDcnsBN7B6AiWBFSJIMEcGnO0aYPgY0ZjNWyJDi7Ee8QZRGqB+LhI6w==", + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.4" + "dunder-proto": "^1.0.0" }, - "peerDependencies": { - "@expo/metro-runtime": "^57.0.14", - "expo": "*", - "expo-constants": "^57.0.15", - "expo-font": "^57.0.1", - "expo-router": "*", - "expo-server": "^57.0.3", - "react": "*", - "react-dom": "*", - "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@expo/metro-runtime": { - "optional": true - }, - "expo-router": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "react-server-dom-webpack": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expo/node_modules/@expo/ws-tunnel": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-2.0.0.tgz", - "integrity": "sha512-j+JfTRdCk820J9dU0sA2SqshQIKFOMo7ED84w9MJFcebfbNQgsLztEY/SABDkGnjatrW4xGqnUhVRxSBVyCkXw==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, "license": "MIT", - "peerDependencies": { - "ws": "^8.0.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expo/node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "has-symbols": "^1.0.3" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/expo/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/expo/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/hermes-compiler": { + "version": "250829098.0.17", + "resolved": "https://registry.npmjs.org/hermes-compiler/-/hermes-compiler-250829098.0.17.tgz", + "integrity": "sha512-qG1PXzTEtriF6oQLZF3vyHhSMxOdW5h2TqqLri0rdpstPustd2fSvRZQMVAPdlhgFwBfYnj3OUZtiO6LjYsEFw==", + "license": "MIT" + }, + "node_modules/hermes-estree": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.36.1.tgz", + "integrity": "sha512-guv1nQ6IJ7S83NRFPWc3SA7IBZrdNC9kapwOq6uXvF4wP+sDCgjzQbKPCoyYmoyZRzztF/n/c36l/rccCZSiCw==", + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.36.1.tgz", + "integrity": "sha512-GApNk4zLHi2UWoWZZkx7LNCOSzLSc5lB55pZ/PhK7ycFeg7u5LcF88p/WbpIi1XUDtE0MpHE3uRR3u3KB7TjSQ==", "license": "MIT", + "dependencies": { + "hermes-estree": "0.36.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, "engines": { - "node": ">= 0.6" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/expo/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/expo/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, - "node_modules/expo/node_modules/ws": { - "version": "8.21.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", - "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">= 14" } }, - "node_modules/exponential-backoff": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "license": "BSD-3-Clause" + }, + "node_modules/idb-keyval": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.3.0.tgz", + "integrity": "sha512-um+2dgAWmYsu615EXpWVwSmapJhON0G43t3Ka/EVaohzPQXSMqKEqeDK/oIW3Ow+BXaF2PvSc+oBTFp793A5Ow==", "license": "Apache-2.0" }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/fb-dotslash": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz", - "integrity": "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==", - "license": "(MIT OR Apache-2.0)", - "bin": { - "dotslash": "bin/dotslash" + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=20" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, - "node_modules/fbjs": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", - "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", - "dependencies": { - "cross-fetch": "^3.1.5", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^1.0.35" + "engines": { + "node": ">=0.8.19" } }, - "node_modules/fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", - "license": "MIT" + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, - "node_modules/fbjs/node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "node_modules/inline-style-prefixer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", + "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", "license": "MIT", "dependencies": { - "asap": "~2.0.3" + "css-in-js-utils": "^3.1.0" } }, - "node_modules/fbjs/node_modules/ua-parser-js": { - "version": "1.0.41", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", - "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, "license": "MIT", - "bin": { - "ua-parser-js": "script/cli.js" + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": "*" + "node": ">= 0.4" } }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "license": "MIT", - "engines": { - "node": ">=12.0.0" + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, - "peerDependencies": { - "picomatch": "^3 || ^4" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fetch-nodeshim": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/fetch-nodeshim/-/fetch-nodeshim-0.4.10.tgz", - "integrity": "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==", + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", "license": "MIT" }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/filter-obj": { + "node_modules/is-bigint": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "semver": "^7.7.1" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/flow-enums-runtime": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", - "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", - "license": "MIT" - }, - "node_modules/fontfaceobserver": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz", - "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==", - "license": "BSD-2-Clause" + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-nonce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/getenv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/getenv/-/getenv-2.0.0.tgz", - "integrity": "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "license": "BlueOak-1.0.0", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" + "call-bound": "^1.0.3" }, "engines": { - "node": "18 || 20 || >=22" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hermes-compiler": { - "version": "250829098.0.17", - "resolved": "https://registry.npmjs.org/hermes-compiler/-/hermes-compiler-250829098.0.17.tgz", - "integrity": "sha512-qG1PXzTEtriF6oQLZF3vyHhSMxOdW5h2TqqLri0rdpstPustd2fSvRZQMVAPdlhgFwBfYnj3OUZtiO6LjYsEFw==", - "license": "MIT" - }, - "node_modules/hermes-estree": { - "version": "0.36.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.36.1.tgz", - "integrity": "sha512-guv1nQ6IJ7S83NRFPWc3SA7IBZrdNC9kapwOq6uXvF4wP+sDCgjzQbKPCoyYmoyZRzztF/n/c36l/rccCZSiCw==", - "license": "MIT" - }, - "node_modules/hermes-parser": { - "version": "0.36.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.36.1.tgz", - "integrity": "sha512-GApNk4zLHi2UWoWZZkx7LNCOSzLSc5lB55pZ/PhK7ycFeg7u5LcF88p/WbpIi1XUDtE0MpHE3uRR3u3KB7TjSQ==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { - "hermes-estree": "0.36.1" + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "license": "BSD-3-Clause", - "dependencies": { - "react-is": "^16.7.0" + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" - }, - "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, "license": "MIT", "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">= 14" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hyphenate-style-name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", - "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/inline-style-prefixer": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", - "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, "license": "MIT", "dependencies": { - "css-in-js-utils": "^3.1.0" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, "license": "MIT", "dependencies": { - "loose-envify": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", - "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", - "license": "MIT" - }, - "node_modules/is-core-module": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", - "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.3" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -5038,37 +9010,66 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, "license": "MIT", - "bin": { - "is-docker": "cli.js" + "dependencies": { + "which-typed-array": "^1.1.16" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, "engines": { - "node": ">=0.12.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-wsl": { @@ -5083,12 +9084,37 @@ "node": ">=8" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "license": "ISC" }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -5241,6 +9267,27 @@ "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -5253,6 +9300,38 @@ "node": ">=6" } }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/keyvaluestorage-interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz", + "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==", + "license": "MIT" + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -5280,6 +9359,20 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lighthouse-logger": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", @@ -5566,12 +9659,35 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.throttle": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", @@ -5697,12 +9813,34 @@ "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", "license": "Apache-2.0" }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/memoize-one": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", "license": "MIT" }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -6108,6 +10246,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", @@ -6135,6 +10283,12 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/multiformats": { + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-9.9.0.tgz", + "integrity": "sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==", + "license": "(Apache-2.0 AND MIT)" + }, "node_modules/multitars": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/multitars/-/multitars-1.0.2.tgz", @@ -6159,6 +10313,29 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -6168,6 +10345,35 @@ "node": ">= 0.6" } }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -6188,6 +10394,12 @@ } } }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" + }, "node_modules/node-forge": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", @@ -6203,6 +10415,12 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "license": "MIT" }, + "node_modules/node-mock-http": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.5.tgz", + "integrity": "sha512-KQyt/wLjG3TAc7DOUhpqWzgd4ERxR80JOlTK5VE5R1S12IaPVN5qkj4klBce9HPG1Njuup4Sb5bljaT34lIyjw==", + "license": "MIT" + }, "node_modules/node-releases": { "version": "2.0.53", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", @@ -6212,6 +10430,15 @@ "node": ">=18" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-package-arg": { "version": "11.0.3", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", @@ -6254,6 +10481,139 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -6303,6 +10663,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", @@ -6394,22 +10772,143 @@ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "license": "MIT", "dependencies": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ox": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.3.tgz", + "integrity": "sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.0.9", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ox/node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "callsites": "^3.0.0" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/parse-png": { @@ -6433,6 +10932,16 @@ "node": ">= 0.8" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -6491,6 +11000,43 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pino": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.0.0.tgz", + "integrity": "sha512-eI9pKwWEix40kfvSzqEP6ldqOoBIN7dwD/o91TY5z8vQI12sAffpR/pOqAD1IVVwIVHDpHjkq0joBPdJD0rafA==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^2.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "slow-redact": "^0.3.0", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", + "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "license": "MIT" + }, "node_modules/plist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", @@ -6523,6 +11069,16 @@ "node": ">=4.0.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.5.26", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", @@ -6557,6 +11113,16 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -6598,6 +11164,22 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/process-warning": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.1.0.tgz", + "integrity": "sha512-jQSaVHsPgtyw60e1rQ/A+/ArPEj/S8pS/vFnyGa/gYFXrKk/6RuDkoqVDQ5NI5MmS01698ltlAk0NoDBNLujRw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -6629,6 +11211,34 @@ "node": ">= 6" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/query-string": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", @@ -6656,6 +11266,18 @@ "inherits": "~2.0.3" } }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "license": "MIT" + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -6811,6 +11433,18 @@ "react-native": "*" } }, + "node_modules/react-native-get-random-values": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/react-native-get-random-values/-/react-native-get-random-values-1.11.0.tgz", + "integrity": "sha512-4BTbDbRmS7iPdhYLRcz3PGFIpFJBwNZg9g42iwa2P6FOv9vZj/xJc678RZXnLNZzd0qd7Q3CCF6Yd+CU2eoXKQ==", + "license": "MIT", + "dependencies": { + "fast-base64-decode": "^1.0.0" + }, + "peerDependencies": { + "react-native": ">=0.56" + } + }, "node_modules/react-native-is-edge-to-edge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.3.1.tgz", @@ -6860,6 +11494,18 @@ "react-native": "*" } }, + "node_modules/react-native-url-polyfill": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz", + "integrity": "sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA==", + "license": "MIT", + "dependencies": { + "whatwg-url-without-unicode": "8.0.0-3" + }, + "peerDependencies": { + "react-native": "*" + } + }, "node_modules/react-native-web": { "version": "0.21.2", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz", @@ -7029,6 +11675,51 @@ } } }, + "node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -7053,6 +11744,27 @@ "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "license": "MIT" }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpu-core": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", @@ -7127,6 +11839,16 @@ "node": ">=8" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/resolve-workspace-root": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.1.tgz", @@ -7146,6 +11868,26 @@ "node": ">=4" } }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -7166,6 +11908,50 @@ ], "license": "MIT" }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/sandbox-cli-detector": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/sandbox-cli-detector/-/sandbox-cli-detector-0.2.0.tgz", @@ -7313,6 +12099,55 @@ "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", "license": "MIT" }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -7373,6 +12208,82 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -7405,6 +12316,12 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "license": "MIT" }, + "node_modules/slow-redact": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/slow-redact/-/slow-redact-0.3.2.tgz", + "integrity": "sha512-MseHyi2+E/hBRqdOi5COy6wZ7j7DxXRz9NkseavNYSvvWC06D8a5cidVZX3tcG5eCW3NIyVU4zT63hw0Q486jw==", + "license": "MIT" + }, "node_modules/slugify": { "version": "1.6.9", "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", @@ -7414,6 +12331,15 @@ "node": ">=8.0.0" } }, + "node_modules/sonic-boom": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -7457,9 +12383,25 @@ "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=6" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" } }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -7493,6 +12435,20 @@ "node": ">= 0.6" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stream-buffers": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", @@ -7525,6 +12481,105 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.1.0.tgz", + "integrity": "sha512-tHNHTxInrYLCga9O9YGxWA3G9/nnzQw8UGAyqGx3Ar1pSTTzIuM4woFSq4SowkXCjJIwq5sIiQvEfRI9tCH1qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "get-intrinsic": "^1.3.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.4", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -7537,6 +12592,29 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/structured-headers": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", @@ -7638,6 +12716,15 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, + "node_modules/thread-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.2.0.tgz", + "integrity": "sha512-zLBvqpwr4Esa0kRjcrzGU6zL25lePWaCLMx0RQFrmteozIfeNdaMLpG5U7PeHzvlFkAWaRKA9/KVW4F60iB+qw==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + } + }, "node_modules/throat": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", @@ -7699,12 +12786,64 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", @@ -7714,6 +12853,84 @@ "node": ">=8" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", @@ -7754,6 +12971,46 @@ "node": "*" } }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" + }, + "node_modules/uint8arrays": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-3.1.1.tgz", + "integrity": "sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==", + "license": "MIT", + "dependencies": { + "multiformats": "^9.4.2" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "license": "MIT" + }, "node_modules/undici-types": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", @@ -7809,6 +13066,44 @@ "node": ">= 0.8" } }, + "node_modules/unrs-resolver": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", + "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.4" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.12.2", + "@unrs/resolver-binding-android-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-arm64": "1.12.2", + "@unrs/resolver-binding-darwin-x64": "1.12.2", + "@unrs/resolver-binding-freebsd-x64": "1.12.2", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", + "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", + "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", + "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", + "@unrs/resolver-binding-linux-x64-musl": "1.12.2", + "@unrs/resolver-binding-openharmony-arm64": "1.12.2", + "@unrs/resolver-binding-wasm32-wasi": "1.12.2", + "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", + "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", + "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + } + }, "node_modules/update-browserslist-db": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", @@ -7839,6 +13134,16 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/use-callback-ref": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", @@ -7989,6 +13294,29 @@ "integrity": "sha512-XPEm0XFQWNVG292lII1PrRRJl3sItrs7CettZ4ncYxuDVpLyy+NwlGyut2hXI0JswcJUxeCH+CyOJK0ZzAXD6A==", "license": "MIT" }, + "node_modules/whatwg-url-without-unicode": { + "version": "8.0.0-3", + "resolved": "https://registry.npmjs.org/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz", + "integrity": "sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==", + "license": "MIT", + "dependencies": { + "buffer": "^5.4.3", + "punycode": "^2.1.1", + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/whatwg-url-without-unicode/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=8" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8004,6 +13332,105 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -8153,6 +13580,19 @@ "node": ">=12" } }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/zod": { "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", @@ -8162,6 +13602,19 @@ "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, "node_modules/zustand": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.15.tgz", diff --git a/package.json b/package.json index fda4a93..a39280b 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,17 @@ "version": "1.0.0", "dependencies": { "@expo/ui": "~57.0.14", + "@react-native-async-storage/async-storage": "2.2.0", + "@react-native-community/netinfo": "12.0.1", "@tanstack/react-query": "^5.101.4", + "@walletconnect/react-native-compat": "^2.23.10", + "@walletconnect/sign-client": "^2.23.10", "expo": "~57.0.18", + "expo-application": "~57.0.2", "expo-camera": "~57.0.4", + "expo-clipboard": "~57.0.1", "expo-constants": "~57.0.12", + "expo-crypto": "~57.0.2", "expo-dev-client": "~57.0.16", "expo-device": "~57.0.1", "expo-file-system": "~57.0.4", @@ -28,6 +35,7 @@ "react-dom": "19.2.3", "react-native": "0.86.3", "react-native-gesture-handler": "~2.32.0", + "react-native-get-random-values": "~1.11.0", "react-native-reanimated": "4.5.1", "react-native-safe-area-context": "~5.7.0", "react-native-screens": "~4.26.0", @@ -37,6 +45,8 @@ }, "devDependencies": { "@types/react": "~19.2.2", + "eslint": "^9.0.0", + "eslint-config-expo": "~57.0.2", "typescript": "~6.0.3" }, "scripts": { @@ -48,7 +58,9 @@ "lint": "expo lint", "admin": "npm --prefix admin run dev", "admin:build": "npm --prefix admin run build", - "admin:start": "npm --prefix admin run start" + "admin:start": "npm --prefix admin run start", + "contract:test": "cargo +stable test --manifest-path contract/Cargo.toml --locked", + "contract:build": "stellar contract build --manifest-path contract/Cargo.toml --locked" }, "resolutions": { "uuid": "11.1.1", diff --git a/src/app/(tabs)/more.tsx b/src/app/(tabs)/more.tsx index 66dd1f4..6704815 100644 --- a/src/app/(tabs)/more.tsx +++ b/src/app/(tabs)/more.tsx @@ -8,7 +8,7 @@ export default function MoreScreen() { return ( - {[['Categories', '/categories'], ['Custom Fields', '/custom-fields'], ['Reports', '/reports'], ['Settings', '/settings']].map(([label, route]) => ( + {[['Stellar Testnet', '/stellar'], ['Categories', '/categories'], ['Custom Fields', '/custom-fields'], ['Reports', '/reports'], ['Settings', '/settings']].map(([label, route]) => ( router.push(route as '/reports')}> {label} diff --git a/src/app/(tabs)/savings.tsx b/src/app/(tabs)/savings.tsx index 06fcfbd..8548bab 100644 --- a/src/app/(tabs)/savings.tsx +++ b/src/app/(tabs)/savings.tsx @@ -1,5 +1,6 @@ import { useCallback, useEffect, useState } from 'react'; -import { Alert, Pressable, StyleSheet, Text, TextInput, View } from 'react-native'; +import { Alert, Linking, Pressable, StyleSheet, Text, TextInput, View } from 'react-native'; +import { useRouter } from 'expo-router'; import { FinancePage, financePageStyles as styles } from '@/components/layout/finance-page'; import { @@ -10,6 +11,7 @@ import { } from '@/lib/api'; export default function SavingsScreen() { + const router = useRouter(); const [goals, setGoals] = useState([]); const [loading, setLoading] = useState(true); const [form, setForm] = useState({ @@ -34,8 +36,25 @@ export default function SavingsScreen() { }, []); useEffect(() => { - void loadGoals(); - }, [loadGoals]); + let active = true; + + fetchSavingsGoals() + .then((items) => { + if (!active) return; + setGoals(items); + setMessage(null); + }) + .catch(() => { + if (active) setMessage('Savings API unavailable.'); + }) + .finally(() => { + if (active) setLoading(false); + }); + + return () => { + active = false; + }; + }, []); const create = async () => { const targetAmount = Number(form.targetAmount); @@ -82,6 +101,10 @@ export default function SavingsScreen() { + + Stellar Testnet vaultLink a watch-only account and prepare externally signed Soroban transactions. + router.push('/stellar')}>Open + Active Goals ({goals.length}) @@ -95,6 +118,7 @@ export default function SavingsScreen() { Math.round(((goal.fundedAmount || 0) / Math.max(goal.targetAmount, 1)) * 100), 100, ); + const hasOnChainProof = Boolean(goal.contractId && goal.transactionHash); return ( @@ -141,6 +165,47 @@ export default function SavingsScreen() { Off-chain draft )} + + + + {hasOnChainProof ? '✓ Funding verified on Stellar' : 'Tracker only · no funds held'} + + + {hasOnChainProof + ? 'This amount has an on-chain transaction proof.' + : 'Saving this draft does not transfer XLM. Use the Stellar vault to fund a real goal.'} + + + + { + if (hasOnChainProof && goal.transactionHash) { + void Linking.openURL( + `https://stellar.expert/explorer/testnet/tx/${goal.transactionHash}`, + ); + } else { + router.push('/stellar'); + } + }}> + + {hasOnChainProof ? 'View Transaction Proof' : 'Open Stellar Vault to Fund'} + + ); })} @@ -214,6 +279,10 @@ export default function SavingsScreen() { } const localStyles = StyleSheet.create({ + stellarBanner: { flexDirection: 'row', alignItems: 'center', gap: 10, backgroundColor: '#10233a', borderWidth: 1, borderColor: '#275382', borderRadius: 12, padding: 13 }, + stellarTitle: { color: '#72b7ff', fontWeight: '800', fontSize: 13 }, + stellarButton: { backgroundColor: '#5ca9ff', borderRadius: 8, paddingHorizontal: 14, paddingVertical: 10 }, + stellarButtonText: { color: '#07111f', fontWeight: '800' }, headerRow: { flexDirection: 'row', justifyContent: 'space-between', @@ -322,6 +391,58 @@ const localStyles = StyleSheet.create({ fontSize: 10, fontStyle: 'italic', }, + fundingState: { + borderRadius: 8, + borderWidth: 1, + padding: 9, + gap: 3, + }, + fundingDraft: { + backgroundColor: '#171c29', + borderColor: '#343d50', + }, + fundingVerified: { + backgroundColor: '#0d2925', + borderColor: '#226a57', + }, + fundingDraftTitle: { + color: '#f0bd62', + fontSize: 11, + fontWeight: '800', + }, + fundingVerifiedTitle: { + color: '#38d695', + fontSize: 11, + fontWeight: '800', + }, + fundingStateText: { + color: '#8e9ab0', + fontSize: 10, + lineHeight: 15, + }, + fundButton: { + backgroundColor: '#5ca9ff', + borderRadius: 8, + paddingVertical: 10, + alignItems: 'center', + }, + fundButtonText: { + color: '#07111f', + fontSize: 11, + fontWeight: '800', + }, + proofButton: { + borderWidth: 1, + borderColor: '#2d745f', + borderRadius: 8, + paddingVertical: 10, + alignItems: 'center', + }, + proofButtonText: { + color: '#43d79b', + fontSize: 11, + fontWeight: '800', + }, input: { backgroundColor: '#081120', color: '#f4f7fb', diff --git a/src/app/receipt.tsx b/src/app/receipt.tsx index 20dd27d..075a697 100644 --- a/src/app/receipt.tsx +++ b/src/app/receipt.tsx @@ -8,13 +8,6 @@ import { saveTransactions } from '@/lib/sqlite'; import { useExpenseDraftStore } from '@/store/expense-draft-store'; import { useFinanceStore } from '@/store/finance-store'; -const peso = new Intl.NumberFormat('en-PH', { - style: 'currency', - currency: 'PHP', - minimumFractionDigits: 2, - maximumFractionDigits: 2, -}); - export default function ReceiptScreen() { const router = useRouter(); const { transactions, setTransactions, categories } = useFinanceStore(); diff --git a/src/app/stellar.tsx b/src/app/stellar.tsx new file mode 100644 index 0000000..1cc3c3b --- /dev/null +++ b/src/app/stellar.tsx @@ -0,0 +1,353 @@ +import { useCallback, useEffect, useMemo, useState } from 'react'; +import * as Clipboard from 'expo-clipboard'; +import { Alert, AppState, Linking, Platform, Pressable, StyleSheet, Text, TextInput, View } from 'react-native'; + +import { FinancePage } from '@/components/layout/finance-page'; +import { + fetchStellarNetwork, fetchStellarPayments, fetchStellarSigningRequest, fetchVaultGoals, + linkStellarAccount, prepareVaultInvocation, submitStellarTransaction, type StellarNetworkStatus, type StellarPortfolio, + type StellarSigningRequest, type StellarVaultEvent, type StellarVaultGoal, type StellarVaultGoalsResponse, +} from '@/lib/api'; +import { + createStellarWalletPairing, + disconnectStellarWallet, + restoreStellarWalletSession, + signStellarXdr, + subscribeStellarWalletSession, + walletConnectConfiguration, + type StellarWalletConnectSession, +} from '@/lib/wallet-connect'; + +const ACCOUNT_KEY = 'save.stellar.testnet.account'; +const STROOPS_PER_XLM = 10_000_000n; +const newIdempotencyKey = (action: string) => `${action}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`; + +const saveAccount = async (address: string) => { + if (Platform.OS === 'web') { if (typeof window !== 'undefined') window.localStorage.setItem(ACCOUNT_KEY, address); return; } + const { setItemAsync } = await import('expo-secure-store'); await setItemAsync(ACCOUNT_KEY, address); +}; +const loadAccount = async () => { + if (Platform.OS === 'web') return typeof window === 'undefined' ? null : window.localStorage.getItem(ACCOUNT_KEY); + const { getItemAsync } = await import('expo-secure-store'); return getItemAsync(ACCOUNT_KEY); +}; +const xlmToAtomic = (value: string) => { + if (!/^\d+(\.\d{1,7})?$/.test(value.trim())) throw new Error('Enter an XLM amount with no more than 7 decimal places.'); + const [whole, fraction = ''] = value.trim().split('.'); + const amount = BigInt(whole) * STROOPS_PER_XLM + BigInt(fraction.padEnd(7, '0')); + if (amount <= 0n) throw new Error('Amount must be greater than zero.'); + return amount.toString(); +}; +const atomicToXlm = (value: string) => { + const atomic = BigInt(value || '0'); + const whole = atomic / STROOPS_PER_XLM; + const fraction = (atomic % STROOPS_PER_XLM).toString().padStart(7, '0').replace(/0+$/, ''); + return fraction ? `${whole}.${fraction}` : whole.toString(); +}; +const eventField = (event: StellarVaultEvent | undefined, field: string) => { + if (!event?.value || typeof event.value !== 'object' || Array.isArray(event.value)) { + return undefined; + } + const value = (event.value as Record)[field]; + return typeof value === 'string' || typeof value === 'number' || typeof value === 'bigint' + ? String(value) + : undefined; +}; +const fundingStatusCopy = (status: StellarSigningRequest['status']) => { + if (status === 'success') return 'Funded successfully · confirmed on Stellar Testnet'; + if (status === 'failed') return 'Not funded · the transaction failed or expired'; + if (status === 'prepared') return 'Not funded yet · waiting for wallet approval'; + return 'Submitted · waiting for Stellar ledger confirmation'; +}; +type VaultIntent = Omit[0], 'idempotencyKey'>; + +export default function StellarScreen() { + const [network, setNetwork] = useState(null); + const [portfolio, setPortfolio] = useState(null); + const [vault, setVault] = useState(null); + const [payments, setPayments] = useState>>([]); + const [address, setAddress] = useState(''); + const [targetXlm, setTargetXlm] = useState('1'); + const [targetDate, setTargetDate] = useState(''); + const [contributions, setContributions] = useState>({}); + const [withdrawals, setWithdrawals] = useState>({}); + const [request, setRequest] = useState(null); + const [lastIntent, setLastIntent] = useState(null); + const [walletSession, setWalletSession] = useState(null); + const [pairingUri, setPairingUri] = useState(null); + const [walletBusy, setWalletBusy] = useState(false); + const [busy, setBusy] = useState(null); + const [message, setMessage] = useState(null); + const walletConfig = useMemo(() => walletConnectConfiguration(), []); + + const loadVault = useCallback(async (owner: string) => { const result = await fetchVaultGoals(owner); setVault(result); return result; }, []); + const connect = useCallback(async (nextAddress: string) => { + if (!nextAddress.trim()) return; + setBusy('account'); + try { + const linked = await linkStellarAccount(nextAddress.trim()); + setPortfolio(linked); setAddress(linked.address); setMessage(null); await saveAccount(linked.address); + + const [activityResult, vaultResult] = await Promise.allSettled([ + fetchStellarPayments(linked.address), + loadVault(linked.address), + ]); + if (activityResult.status === 'fulfilled') setPayments(activityResult.value); + + const unavailable: string[] = []; + if (activityResult.status === 'rejected') unavailable.push('payment history'); + if (vaultResult.status === 'rejected') unavailable.push('Soroban vault'); + if (unavailable.length) { + setMessage(`Wallet connected. ${unavailable.join(' and ')} could not refresh yet.`); + } + } catch (error) { setMessage(error instanceof Error ? error.message : 'Unable to link Testnet account.'); } + finally { setBusy(null); } + }, [loadVault]); + + const refreshRequest = useCallback(async () => { + if (!request) return; + try { + const updated = await fetchStellarSigningRequest(request.idempotencyKey); setRequest(updated); + if (updated.status === 'success' && portfolio) { + const [linked, activity] = await Promise.all([linkStellarAccount(portfolio.address), fetchStellarPayments(portfolio.address), loadVault(portfolio.address)]); + setPortfolio(linked); setPayments(activity); setMessage(`${updated.action.replaceAll('_', ' ')} confirmed on Stellar Testnet.`); + } + } catch (error) { setMessage(error instanceof Error ? error.message : 'Unable to refresh transaction status.'); } + }, [loadVault, portfolio, request]); + + useEffect(() => { + void fetchStellarNetwork().then(setNetwork).catch(() => setMessage('Stellar Testnet RPC is unavailable.')); + void Promise.all([restoreStellarWalletSession(), loadAccount()]) + .then(([session, saved]) => { + if (session) setWalletSession(session); + const account = session?.address ?? saved; + if (account) void connect(account); + }) + .catch((error) => setMessage(error instanceof Error ? error.message : 'Unable to restore wallet session.')); + }, [connect]); + useEffect(() => subscribeStellarWalletSession((reason) => { + setWalletSession(null); + setPairingUri(null); + setMessage(reason); + }), []); + useEffect(() => { + if (!request || !['prepared', 'submitted', 'pending'].includes(request.status)) return; + const timer = setInterval(() => void refreshRequest(), 3_000); + const subscription = AppState.addEventListener('change', (state) => { if (state === 'active') void refreshRequest(); }); + return () => { clearInterval(timer); subscription.remove(); }; + }, [refreshRequest, request]); + + const connectFreighter = useCallback(async () => { + setWalletBusy(true); + setMessage(null); + try { + const pairing = await createStellarWalletPairing(); + setPairingUri(pairing.uri); + await Clipboard.setStringAsync(pairing.uri); + setMessage('WalletConnect pairing copied. Approve the Testnet session in Freighter Mobile.'); + try { + await Linking.openURL(pairing.freighterDeepLink); + } catch { + setMessage('Could not open Freighter automatically. Open Freighter, choose WalletConnect, and paste the copied pairing URI.'); + } + const session = await pairing.approval(); + setWalletSession(session); + setPairingUri(null); + await connect(session.address); + setMessage(`Wallet connected through ${session.walletName}.`); + } catch (error) { + setMessage(error instanceof Error ? error.message : 'Freighter connection failed.'); + } finally { + setWalletBusy(false); + } + }, [connect]); + + const disconnectFreighter = useCallback(async () => { + if (!walletSession) return; + setWalletBusy(true); + try { + await disconnectStellarWallet(walletSession); + setWalletSession(null); + setPairingUri(null); + setMessage('Freighter disconnected. The public account remains available in watch-only mode.'); + } catch (error) { + setMessage(error instanceof Error ? error.message : 'Unable to disconnect Freighter.'); + } finally { + setWalletBusy(false); + } + }, [walletSession]); + + const copyPairingUri = useCallback(async () => { + if (!pairingUri) return; + await Clipboard.setStringAsync(pairingUri); + setMessage('WalletConnect pairing URI copied. Paste it into Freighter Mobile.'); + }, [pairingUri]); + + const signWithFreighter = useCallback(async (prepared: StellarSigningRequest) => { + if (!walletSession || !portfolio) throw new Error('Connect the matching Freighter Testnet account first.'); + setBusy(`sign-${prepared.idempotencyKey}`); + try { + const signatureRequest = signStellarXdr(walletSession, prepared.unsignedXdr, portfolio.address); + void Linking.openURL('freighterwallet://').catch(() => undefined); + const signedXdr = await signatureRequest; + await submitStellarTransaction({ + signedXdr, + kind: prepared.kind, + idempotencyKey: prepared.idempotencyKey, + }); + const updated = await fetchStellarSigningRequest(prepared.idempotencyKey); + setRequest(updated); + setMessage('Freighter signed the transaction. Waiting for Stellar ledger confirmation.'); + } catch (error) { + setMessage(error instanceof Error ? error.message : 'Freighter signing failed.'); + } finally { + setBusy(null); + } + }, [portfolio, walletSession]); + + const copyUnsignedXdr = useCallback(async (prepared: StellarSigningRequest) => { + await Clipboard.setStringAsync(prepared.unsignedXdr); + setMessage('Unsigned Testnet XDR copied for manual wallet or Stellar Laboratory testing.'); + }, []); + + const prepareIntent = useCallback(async (intent: VaultIntent) => { + setBusy(`${intent.action}-${intent.goalId ?? 'new'}`); + try { + const prepared = await prepareVaultInvocation({ ...intent, idempotencyKey: newIdempotencyKey(intent.action) }); + setRequest(prepared); setLastIntent(intent); setMessage(null); + const buttons = walletSession && portfolio?.address === walletSession.address + ? [ + { text: 'Cancel', style: 'cancel' as const }, + { text: 'SEP-7 fallback', onPress: () => void Linking.openURL(prepared.signingUrl).catch(() => void copyUnsignedXdr(prepared)) }, + { text: 'Approve in Freighter', onPress: () => void signWithFreighter(prepared) }, + ] + : [ + { text: 'Cancel', style: 'cancel' as const }, + { text: 'Copy XDR', onPress: () => void copyUnsignedXdr(prepared) }, + { text: 'Open SEP-7 Wallet', onPress: () => void Linking.openURL(prepared.signingUrl).catch(() => void copyUnsignedXdr(prepared)) }, + ]; + Alert.alert( + 'External wallet approval required', + `${prepared.action.replaceAll('_', ' ')} was simulated for Stellar Testnet. Fee: ${prepared.fee ?? '—'} stroops. Review every field before signing.`, + buttons, + ); + } catch (error) { setMessage(error instanceof Error ? error.message : 'Unable to prepare vault transaction.'); } + finally { setBusy(null); } + }, [copyUnsignedXdr, portfolio, signWithFreighter, walletSession]); + + const createGoal = async () => { + if (!portfolio || !network) return; + try { + const deadline = targetDate.trim() ? Math.floor(new Date(`${targetDate.trim()}T23:59:59Z`).getTime() / 1000) : undefined; + if (deadline !== undefined && (!Number.isFinite(deadline) || deadline <= Date.now() / 1000)) throw new Error('Target date must be a future YYYY-MM-DD date.'); + await prepareIntent({ source: portfolio.address, owner: portfolio.address, action: 'create_goal', assetContractId: network.xlmSacId, targetAmount: xlmToAtomic(targetXlm), targetDate: deadline?.toString() }); + } catch (error) { setMessage(error instanceof Error ? error.message : 'Invalid goal details.'); } + }; + const actOnGoal = async (goal: StellarVaultGoal, action: VaultIntent['action']) => { + if (!portfolio) return; + try { + const amount = action === 'contribute' ? xlmToAtomic(contributions[goal.id] ?? '') : action === 'withdraw' ? xlmToAtomic(withdrawals[goal.id] ?? '') : undefined; + await prepareIntent({ source: portfolio.address, action, goalId: goal.id, contributor: action === 'contribute' ? portfolio.address : undefined, amount }); + } catch (error) { setMessage(error instanceof Error ? error.message : 'Invalid transaction details.'); } + }; + const xlmBalance = useMemo(() => portfolio?.balances.find((balance) => balance.asset === 'XLM')?.balance ?? '0', [portfolio]); + + return + Non-custodial Testnet flowSAVE prepares transactions and tracks their public proof. Your external wallet remains the only user-transaction signer. + + Network{network ? `LIVE · ledger ${network.latestLedger}` : 'UNAVAILABLE'} + Stellar Testnet · Protocol {network?.protocolVersion ?? '—'} · Asset: XLM + Vault: {network?.vaultContractId ?? 'Not configured'} + Wallet callback: {network?.sep7.callbackEnabled ? 'enabled' : 'wallet submits directly'} · SEP-7 request signer: {network?.sep7.requestSigningPublicKey ? 'loaded' : 'not configured'} + + + Freighter Mobile signer{walletSession ? 'CONNECTED' : walletConfig.configured ? 'READY' : 'SETUP REQUIRED'} + WalletConnect signs the prepared Testnet XDR in Freighter. SAVE never receives your secret key. + {!walletConfig.configured ? WalletConnect configuration requiredSet EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID in the root .env, then restart Expo. A custom metadata URL is optional. : null} + {walletConfig.configured && walletConfig.usingDefaultMetadata ? Using the SAVE GitHub repository as temporary WalletConnect metadata. : null} + {walletSession ? <>✓ {walletSession.walletName}{walletSession.address} void disconnectFreighter()}>{walletBusy ? 'Disconnecting…' : 'Disconnect Freighter'} : void connectFreighter()}>{walletBusy ? 'Waiting for Freighter approval…' : 'Connect Freighter Mobile'}} + {pairingUri ? void copyPairingUri()}>Copy Pairing URI void Linking.openURL(`freighterwallet://wc?uri=${encodeURIComponent(pairingUri)}`)}>Open Freighter : null} + + + Watch-only Testnet account + + void connect(address)}>{busy === 'account' ? 'Loading…' : 'Link Watch-Only Account'} + {portfolio ? <>{portfolio.address}Available Testnet XLM{xlmBalance} : null} + + {portfolio && network ? + Create on-chain savings goalDesignated test asset: native XLM SAC. Private labels and financial records remain off-chain. + + + void createGoal()}>{busy === 'create_goal-new' ? 'Simulating…' : 'Create Goal in External Wallet'} + : null} + {request ? + {request.action === 'contribute' ? 'Funding confirmation' : 'Latest transaction'}{request.status.toUpperCase()} + + + {request.action === 'contribute' + ? fundingStatusCopy(request.status) + : `${request.action.replaceAll('_', ' ')} ${request.status}`} + + {request.action === 'contribute' && lastIntent?.amount ? {atomicToXlm(lastIntent.amount)} XLM · Goal #{lastIntent.goalId} : null} + + {request.action.replaceAll('_', ' ')} · fee {request.fee ?? '—'} stroops{request.hash} + {request.error ? {request.error} : null} + void refreshRequest()}>Refresh Status{request.status !== 'prepared' ? void Linking.openURL(request.explorerUrl)}>Explorer Proof : null} + {request.status === 'prepared' ? {walletSession && portfolio?.address === walletSession.address ? void signWithFreighter(request)}>{busy === `sign-${request.idempotencyKey}` ? 'Waiting for Freighter…' : 'Approve in Freighter'} : null} void copyUnsignedXdr(request)}>Copy XDR : null} + {request.status === 'failed' && lastIntent ? void prepareIntent(lastIntent)}>Prepare Fresh Retry : null} + : null} + {portfolio ? Soroban goals void loadVault(portfolio.address)}>Refresh : null} + {vault?.goals.map((goal) => { + const target = BigInt(goal.targetAmount || '0'); const balance = BigInt(goal.balance || '0'); + const progress = target > 0n ? Math.min(Number((balance * 10000n) / target) / 100, 100) : 0; + const goalEvents = vault.events.filter((item) => item.goalId === goal.id); + const event = [...goalEvents].reverse().find((item) => item.successful); + const contributionEvent = [...goalEvents].reverse().find((item) => item.successful && item.type.toLowerCase().includes('contribution')); + return setContributions((current) => ({ ...current, [goal.id]: value }))} + onWithdrawalChange={(value) => setWithdrawals((current) => ({ ...current, [goal.id]: value }))} + onAction={(action) => void actOnGoal(goal, action)} />; + })} + {portfolio && vault && !vault.goals.length ? No Soroban goals yet. Create one above, approve it in your wallet, then refresh. : null} + {portfolio && payments.length ? Recent account activity{payments.slice(0, 5).map((payment) => void Linking.openURL(payment.explorerUrl)} style={styles.activity}>{payment.type.replaceAll('_', ' ')}{payment.createdAt}{payment.amount ?? '—'} {payment.asset ?? ''})} : null} + {message ? {message} : null} + ; +} + +function GoalCard(props: { goal: StellarVaultGoal; event?: StellarVaultEvent; contributionEvent?: StellarVaultEvent; ledgerVerified: boolean; progress: number; contribution: string; withdrawal: string; busy: string | null; onContributionChange: (value: string) => void; onWithdrawalChange: (value: string) => void; onAction: (action: VaultIntent['action']) => void }) { + const { goal, event, contributionEvent } = props; + const balance = BigInt(goal.balance || '0'); + const target = BigInt(goal.targetAmount || '0'); + const fundingState = balance === 0n ? 'NOT FUNDED' : balance >= target ? 'TARGET REACHED' : 'PARTIALLY FUNDED'; + const lastContribution = eventField(contributionEvent, 'amount'); + return + Goal #{goal.id}{goal.status} + + {props.ledgerVerified ? '✓ LIVE SOROBAN BALANCE' : 'BALANCE UNVERIFIED'} 0n && styles.fundingBadgeActive]}>{fundingState} + {atomicToXlm(goal.balance)} XLM funded + This is the vault contract balance, not a locally entered amount. + + Progress toward target{props.progress.toFixed(1)}% + + Target {atomicToXlm(goal.targetAmount)} XLM{goal.targetDate ? ` · ${new Date(Number(goal.targetDate) * 1000).toLocaleDateString()}` : ''} + {contributionEvent ? void Linking.openURL(contributionEvent.explorerUrl)} style={styles.contributionProof}>✓ Last funding confirmed{lastContribution ? ` · ${atomicToXlm(lastContribution)} XLM` : ''}Ledger {contributionEvent.ledger}{contributionEvent.ledgerClosedAt ? ` · ${new Date(contributionEvent.ledgerClosedAt).toLocaleString()}` : ''}{contributionEvent.txHash}View transaction proof → : balance > 0n ? The balance is verified, but its contribution event is outside the current event window. : null} + {event ? void Linking.openURL(event.explorerUrl)} style={styles.proof}>Latest proof · {event.type.replaceAll('_', ' ')}{event.txHash} : null} + {goal.status === 'Active' ? <> props.onAction('contribute')}>Fund Goal with Testnet XLM props.onAction('complete_goal')}>Complete props.onAction('cancel_goal')}>Cancel & Refund : null} + {goal.status === 'Completed' && BigInt(goal.balance) > 0n ? <> props.onAction('withdraw')}>Withdraw to Owner Wallet : null} + ; +} + +const statusColor = (status: StellarSigningRequest['status']) => status === 'success' ? styles.successStatus : status === 'failed' ? styles.failedStatus : status === 'prepared' ? styles.preparedStatus : styles.pendingStatus; +const confirmationBannerStyle = (status: StellarSigningRequest['status']) => status === 'success' ? styles.confirmationSuccess : status === 'failed' ? styles.confirmationFailed : status === 'prepared' ? styles.confirmationPrepared : styles.confirmationPending; +const styles = StyleSheet.create({ + card: { backgroundColor: '#0d1629', borderWidth: 1, borderColor: '#1c2941', borderRadius: 12, padding: 15, gap: 11 }, failedCard: { borderColor: '#6d2c3a' }, confirmedCard: { borderColor: '#226a57' }, + notice: { backgroundColor: '#10233a', borderWidth: 1, borderColor: '#275382', borderRadius: 12, padding: 15 }, noticeTitle: { color: '#72b7ff', fontWeight: '800', marginBottom: 6 }, + title: { color: '#f2f6fb', fontWeight: '800', fontSize: 14 }, sectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 2 }, sectionTitle: { color: '#f2f6fb', fontWeight: '800', fontSize: 17 }, + help: { color: '#8d99ad', fontSize: 11, lineHeight: 17 }, row: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', gap: 10 }, actionRow: { flexDirection: 'row', gap: 9 }, + badge: { color: '#ff788c', fontSize: 9, fontWeight: '800' }, online: { color: '#24ce88' }, status: { color: '#72b7ff', fontSize: 10, fontWeight: '800' }, preparedStatus: { color: '#f4be4f' }, pendingStatus: { color: '#72b7ff' }, successStatus: { color: '#24ce88' }, failedStatus: { color: '#ff788c' }, + mono: { color: '#8ca0bd', fontSize: 9, fontFamily: 'monospace' }, value: { color: '#f3f7fc', fontWeight: '800', fontSize: 12 }, input: { backgroundColor: '#081120', borderWidth: 1, borderColor: '#26354e', borderRadius: 9, padding: 12, color: '#f1f5fa' }, + primary: { backgroundColor: '#5ca9ff', borderRadius: 9, padding: 13, alignItems: 'center' }, primaryAction: { flex: 1, backgroundColor: '#5ca9ff', borderRadius: 9, padding: 11, alignItems: 'center' }, primaryText: { color: '#07111f', fontWeight: '800', fontSize: 12 }, secondary: { flex: 1, borderWidth: 1, borderColor: '#315277', borderRadius: 9, padding: 11, alignItems: 'center' }, secondaryText: { color: '#82bcfa', fontWeight: '700', fontSize: 11 }, danger: { flex: 1, borderWidth: 1, borderColor: '#623141', borderRadius: 9, padding: 11, alignItems: 'center' }, dangerText: { color: '#ff8798', fontWeight: '700', fontSize: 11 }, disabled: { opacity: 0.45 }, setupNotice: { backgroundColor: '#2a2415', borderWidth: 1, borderColor: '#665326', borderRadius: 8, padding: 10, gap: 4 }, + divider: { height: 1, backgroundColor: '#223149' }, progressTrack: { height: 7, borderRadius: 5, backgroundColor: '#192640', overflow: 'hidden' }, progressFill: { height: '100%', borderRadius: 5, backgroundColor: '#5ca9ff' }, proof: { backgroundColor: '#0a2034', borderRadius: 8, padding: 10, gap: 4 }, proofTitle: { color: '#57a8f5', fontSize: 10, fontWeight: '700', textTransform: 'capitalize' }, link: { color: '#66adf8', fontWeight: '700', fontSize: 12 }, + activity: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderBottomWidth: 1, borderBottomColor: '#1a2740', paddingVertical: 9 }, activityTitle: { color: '#dfe7f3', textTransform: 'capitalize', fontSize: 11 }, activityAmount: { color: '#64adff', fontWeight: '700', fontSize: 11 }, error: { color: '#ff788c', fontSize: 11, lineHeight: 17 }, success: { color: '#24ce88', fontSize: 11, lineHeight: 17 }, + confirmationBanner: { borderRadius: 9, borderWidth: 1, padding: 11, gap: 4 }, confirmationSuccess: { backgroundColor: '#0d2925', borderColor: '#226a57' }, confirmationFailed: { backgroundColor: '#2a151c', borderColor: '#6d2c3a' }, confirmationPrepared: { backgroundColor: '#2a2415', borderColor: '#665326' }, confirmationPending: { backgroundColor: '#10233a', borderColor: '#275382' }, confirmationTitle: { fontSize: 11, fontWeight: '800' }, confirmationAmount: { color: '#f1f6fb', fontSize: 16, fontWeight: '900' }, + verifiedBalance: { backgroundColor: '#0a2034', borderWidth: 1, borderColor: '#275382', borderRadius: 9, padding: 11, gap: 5 }, verifiedLabel: { color: '#61b1ff', fontSize: 9, fontWeight: '900' }, fundingBadge: { color: '#8d99ad', fontSize: 8, fontWeight: '900' }, fundingBadgeActive: { color: '#35d394' }, balanceAmount: { color: '#f4f8fc', fontSize: 20, fontWeight: '900' }, contributionProof: { backgroundColor: '#0d2925', borderWidth: 1, borderColor: '#226a57', borderRadius: 9, padding: 11, gap: 4 }, confirmedProofTitle: { color: '#38d695', fontSize: 11, fontWeight: '800' }, proofLink: { color: '#5ee0aa', fontSize: 10, fontWeight: '700', marginTop: 2 }, +}); diff --git a/src/components/navigation/app-sidebar.tsx b/src/components/navigation/app-sidebar.tsx index 9b28058..a9fd337 100644 --- a/src/components/navigation/app-sidebar.tsx +++ b/src/components/navigation/app-sidebar.tsx @@ -6,7 +6,7 @@ type AppSidebarProps = { onClose: () => void; }; -const menuItems: Array<{ label: string; href: Href; icon: string }> = [ +const menuItems: { label: string; href: Href; icon: string }[] = [ { label: 'Dashboard', href: '/', icon: '⌘' }, { label: 'Expenses', href: '/expenses', icon: '▧' }, { label: 'Budgets', href: '/budgets', icon: '◔' }, diff --git a/src/hooks/use-color-scheme.web.ts b/src/hooks/use-color-scheme.web.ts index 7eb1c1b..45995d8 100644 --- a/src/hooks/use-color-scheme.web.ts +++ b/src/hooks/use-color-scheme.web.ts @@ -1,15 +1,13 @@ -import { useEffect, useState } from 'react'; +import { useSyncExternalStore } from 'react'; import { useColorScheme as useRNColorScheme } from 'react-native'; +const subscribe = () => () => {}; + /** * To support static rendering, this value needs to be re-calculated on the client side for web */ export function useColorScheme() { - const [hasHydrated, setHasHydrated] = useState(false); - - useEffect(() => { - setHasHydrated(true); - }, []); + const hasHydrated = useSyncExternalStore(subscribe, () => true, () => false); const colorScheme = useRNColorScheme(); diff --git a/src/lib/api.ts b/src/lib/api.ts index f2cd889..bc9171d 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -49,6 +49,94 @@ export type ApiSavingsGoal = { transactionHash?: string; }; +export type StellarNetworkStatus = { + network: 'testnet'; + passphrase: string; + protocolVersion: number; + latestLedger: number; + horizonUrl: string; + rpcUrl: string; + vaultContractId: string | null; + xlmSacId: string; + sep7: { + callbackEnabled: boolean; + requestSigningEnabled: boolean; + requestSigningPublicKey: string | null; + originDomain: string | null; + }; +}; + +export type StellarPortfolio = { + address: string; + sequence: string; + balances: { asset: string; issuer?: string; balance: string; assetType: string }[]; + subentryCount: number; + lastModifiedLedger: number; + explorerUrl: string; + linked?: boolean; + signingMode?: 'external-wallet'; + secretsStored?: false; +}; + +export type StellarSigningRequest = { + idempotencyKey: string; + kind: 'classic' | 'soroban'; + action: string; + unsignedXdr: string; + status: 'prepared' | 'submitted' | 'pending' | 'success' | 'failed'; + createdAt: string; + network: 'testnet'; + networkPassphrase: string; + signingUrl: string; + fee?: string; + hash: string; + source: string; + error?: string; + callbackUrl: string | null; + explorerUrl: string; +}; + +export type StellarTransactionSubmission = { + kind: 'classic' | 'soroban'; + status: 'submitted' | 'pending' | 'success'; + hash: string; + ledger?: number; + latestLedger?: number; + explorerUrl: string; +}; + +export type StellarVaultGoal = { + id: string; + owner: string; + asset: string; + targetAmount: string; + targetDate: string | null; + balance: string; + status: 'Active' | 'Completed' | 'Cancelled' | string; +}; + +export type StellarVaultEvent = { + id: string; + ledger: number; + ledgerClosedAt?: string; + txHash: string; + contractId: string; + type: string; + goalId: string | null; + topics: unknown[]; + value: unknown; + successful: boolean; + explorerUrl: string; +}; + +export type StellarVaultGoalsResponse = { + owner: string; + goals: StellarVaultGoal[]; + events: StellarVaultEvent[]; + ledgerVerified: boolean; + contractId: string; +}; + export function getApiBaseUrl(): string { if (process.env.EXPO_PUBLIC_API_URL) { return process.env.EXPO_PUBLIC_API_URL; @@ -111,6 +199,19 @@ export async function fetchCategories(): Promise { return response.json() as Promise; } +async function apiError(response: Response, path: string) { + let detail = ''; + try { + const body = await response.json() as { message?: string | string[]; error?: string }; + detail = Array.isArray(body.message) ? body.message.join(', ') : body.message ?? body.error ?? ''; + } catch { + // Some upstream/proxy failures do not return JSON. + } + return new Error( + `SAVE API request failed: ${path} (HTTP ${response.status})${detail ? ` — ${detail}` : ''}`, + ); +} + async function postJson(path: string, payload: unknown): Promise { const url = `${getApiBaseUrl()}${path}`; const response = await fetch(url, { @@ -118,7 +219,7 @@ async function postJson(path: string, payload: unknown): Promise { headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); - if (!response.ok) throw new Error(`SAVE API request failed: ${url} (HTTP ${response.status})`); + if (!response.ok) throw await apiError(response, path); return response.json() as Promise; } @@ -179,6 +280,63 @@ export function deleteSavingsGoal(id: string) { return mutateJson<{ deleted: boolean }>(`/savings-goals/${id}`, 'DELETE'); } +async function getJson(path: string): Promise { + const response = await fetch(`${getApiBaseUrl()}${path}`); + if (!response.ok) throw await apiError(response, path); + return response.json() as Promise; +} + +export function fetchStellarNetwork() { + return getJson('/stellar/network'); +} + +export function linkStellarAccount(address: string) { + return postJson('/stellar/accounts/link', { address }); +} + +export function fetchStellarPortfolio(address: string) { + return getJson(`/stellar/accounts/${encodeURIComponent(address)}`); +} + +export function fetchStellarPayments(address: string) { + return getJson<{ id: string; type: string; from?: string; to?: string; amount?: string; asset?: string; transactionHash: string; createdAt: string; explorerUrl: string }[]>(`/stellar/accounts/${encodeURIComponent(address)}/payments?limit=10`); +} + +export function prepareStellarPayment(payload: { source: string; destination: string; amount: string; memo?: string; idempotencyKey: string }) { + return postJson('/stellar/payments/prepare', payload); +} + +export function prepareVaultInvocation(payload: { + source: string; + action: 'create_goal' | 'contribute' | 'complete_goal' | 'withdraw' | 'cancel_goal'; + idempotencyKey: string; + owner?: string; + contributor?: string; + assetContractId?: string; + goalId?: string; + targetAmount?: string; + targetDate?: string; + amount?: string; +}) { + return postJson('/stellar/vault/prepare', payload); +} + +export function fetchVaultGoals(owner: string) { + return getJson(`/stellar/vault/goals/${encodeURIComponent(owner)}`); +} + +export function fetchStellarSigningRequest(idempotencyKey: string) { + return getJson(`/stellar/signing-requests/${encodeURIComponent(idempotencyKey)}`); +} + +export function submitStellarTransaction(payload: { + signedXdr: string; + kind: 'classic' | 'soroban'; + idempotencyKey: string; +}) { + return postJson('/stellar/transactions/submit', payload); +} + export async function createTransaction(payload: Omit): Promise { const url = `${getApiBaseUrl()}/transactions`; const response = await fetch(url, { diff --git a/src/lib/wallet-connect.native.ts b/src/lib/wallet-connect.native.ts new file mode 100644 index 0000000..7f88ed3 --- /dev/null +++ b/src/lib/wallet-connect.native.ts @@ -0,0 +1,161 @@ +import '@walletconnect/react-native-compat'; + +import { SignClient } from '@walletconnect/sign-client'; +import type { SessionTypes } from '@walletconnect/types'; + +const TESTNET_CHAIN = 'stellar:testnet'; +const REQUIRED_METHOD = 'stellar_signXDR'; +const FREIGHTER_DEEP_LINK = 'freighterwallet://wc?uri='; +const DEFAULT_METADATA_URL = 'https://github.com/FWDP/save-project'; +const DEFAULT_METADATA_ICON = 'https://raw.githubusercontent.com/FWDP/save-project/main/assets/images/icon.png'; + +export type StellarWalletConnectSession = { + topic: string; + address: string; + walletName: string; +}; + +export type StellarWalletConnectPairing = { + uri: string; + freighterDeepLink: string; + approval: () => Promise; +}; + +let clientPromise: ReturnType | undefined; +const sessionListeners = new Set<(reason: string) => void>(); + +export function walletConnectConfiguration() { + const projectId = process.env.EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID?.trim() ?? ''; + const configuredMetadataUrl = process.env.EXPO_PUBLIC_WALLETCONNECT_METADATA_URL?.trim() ?? ''; + const hasValidMetadataUrl = /^https:\/\//.test(configuredMetadataUrl); + return { + configured: Boolean(projectId), + projectId, + metadataUrl: hasValidMetadataUrl ? configuredMetadataUrl : DEFAULT_METADATA_URL, + usingDefaultMetadata: !hasValidMetadataUrl, + }; +} + +function accountFromSession(session: SessionTypes.Struct) { + const namespace = session.namespaces.stellar; + const account = namespace?.accounts.find((value) => value.startsWith(`${TESTNET_CHAIN}:`)); + const address = account?.split(':')[2]; + if (!address) throw new Error('Freighter did not approve a Stellar Testnet account.'); + if (!namespace.methods.includes(REQUIRED_METHOD)) { + throw new Error('The connected wallet did not approve Stellar XDR signing.'); + } + return { + topic: session.topic, + address, + walletName: session.peer.metadata.name || 'Freighter Mobile', + }; +} + +async function getClient() { + const config = walletConnectConfiguration(); + if (!config.configured) { + throw new Error( + 'WalletConnect setup is incomplete. Add EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID, then restart Expo.', + ); + } + clientPromise ??= SignClient.init({ + projectId: config.projectId, + metadata: { + name: 'SAVE Finance', + description: 'Non-custodial Stellar Testnet savings goals', + url: config.metadataUrl, + icons: config.usingDefaultMetadata + ? [DEFAULT_METADATA_ICON] + : [`${config.metadataUrl.replace(/\/$/, '')}/favicon.ico`], + redirect: { native: 'saveproject://stellar' }, + }, + }).then((client) => { + client.on('session_delete', () => sessionListeners.forEach((listener) => listener('Freighter disconnected the WalletConnect session.'))); + client.on('session_expire', () => sessionListeners.forEach((listener) => listener('The Freighter WalletConnect session expired. Reconnect to continue.'))); + client.on('session_event', ({ params }) => { + if (params.event.name === 'accountsChanged') { + sessionListeners.forEach((listener) => listener('Freighter changed accounts. Reconnect the matching Testnet account.')); + } + }); + client.on('proposal_expire', () => undefined); + return client; + }); + return clientPromise; +} + +export function subscribeStellarWalletSession(listener: (reason: string) => void) { + sessionListeners.add(listener); + return () => sessionListeners.delete(listener); +} + +export async function restoreStellarWalletSession() { + const config = walletConnectConfiguration(); + if (!config.configured) return null; + const client = await getClient(); + const session = client.session + .getAll() + .find((item) => item.expiry * 1000 > Date.now() && item.namespaces.stellar); + if (!session) return null; + try { + return accountFromSession(session); + } catch { + return null; + } +} + +export async function createStellarWalletPairing(): Promise { + const client = await getClient(); + const { uri, approval } = await client.connect({ + requiredNamespaces: { + stellar: { + chains: [TESTNET_CHAIN], + methods: [REQUIRED_METHOD], + events: ['accountsChanged'], + }, + }, + }); + if (!uri) throw new Error('WalletConnect did not create a pairing URI.'); + return { + uri, + freighterDeepLink: `${FREIGHTER_DEEP_LINK}${encodeURIComponent(uri)}`, + approval: async () => accountFromSession(await approval()), + }; +} + +export async function signStellarXdr( + session: StellarWalletConnectSession, + unsignedXdr: string, + expectedAddress: string, +) { + if (session.address !== expectedAddress) { + throw new Error('The linked SAVE account does not match the connected Freighter account.'); + } + const client = await getClient(); + const activeSession = client.session.get(session.topic); + const activeAccount = accountFromSession(activeSession); + if (activeAccount.address !== expectedAddress) { + throw new Error('Freighter changed accounts. Reconnect the matching Testnet account.'); + } + const result = await client.request<{ signedXDR: string; signer?: string }>({ + topic: session.topic, + chainId: TESTNET_CHAIN, + request: { + method: REQUIRED_METHOD, + params: { xdr: unsignedXdr }, + }, + }); + if (!result?.signedXDR) throw new Error('Freighter returned no signed transaction XDR.'); + if (result.signer && result.signer !== expectedAddress) { + throw new Error('Freighter signed with a different account than the linked SAVE account.'); + } + return result.signedXDR; +} + +export async function disconnectStellarWallet(session: StellarWalletConnectSession) { + const client = await getClient(); + if (!client.session.keys.includes(session.topic)) return; + await client.disconnect({ + topic: session.topic, + reason: { code: 6000, message: 'User disconnected SAVE Finance' }, + }); +} diff --git a/src/lib/wallet-connect.ts b/src/lib/wallet-connect.ts new file mode 100644 index 0000000..0b083b3 --- /dev/null +++ b/src/lib/wallet-connect.ts @@ -0,0 +1,37 @@ +export type StellarWalletConnectSession = { + topic: string; + address: string; + walletName: string; +}; + +export type StellarWalletConnectPairing = { + uri: string; + freighterDeepLink: string; + approval: () => Promise; +}; + +export function walletConnectConfiguration() { + return { configured: false, projectId: '', metadataUrl: '', usingDefaultMetadata: true }; +} + +export async function restoreStellarWalletSession(): Promise { + return null; +} + +export async function createStellarWalletPairing(): Promise { + throw new Error('Freighter Mobile WalletConnect is available in the Android and iOS app.'); +} + +export async function signStellarXdr( + _session: StellarWalletConnectSession, + _unsignedXdr: string, + _expectedAddress: string, +): Promise { + throw new Error('Freighter Mobile WalletConnect is available in the Android and iOS app.'); +} + +export async function disconnectStellarWallet(_session: StellarWalletConnectSession) {} + +export function subscribeStellarWalletSession(_listener: (reason: string) => void) { + return () => {}; +} diff --git a/src/lib/wallet-connect.web.ts b/src/lib/wallet-connect.web.ts new file mode 100644 index 0000000..e59cae2 --- /dev/null +++ b/src/lib/wallet-connect.web.ts @@ -0,0 +1,33 @@ +export type StellarWalletConnectSession = { + topic: string; + address: string; + walletName: string; +}; + +export type StellarWalletConnectPairing = { + uri: string; + freighterDeepLink: string; + approval: () => Promise; +}; + +export function walletConnectConfiguration() { + return { configured: false, projectId: '', metadataUrl: '', usingDefaultMetadata: true }; +} + +export async function restoreStellarWalletSession(): Promise { + return null; +} + +export async function createStellarWalletPairing(): Promise { + throw new Error('Freighter Mobile WalletConnect is available in the Android and iOS app.'); +} + +export async function signStellarXdr() { + throw new Error('Freighter Mobile WalletConnect is available in the Android and iOS app.'); +} + +export async function disconnectStellarWallet() {} + +export function subscribeStellarWalletSession(_listener: (reason: string) => void) { + return () => {}; +} From 321b24b0ece689a2db04f9e03ff98e4258abe8dc Mon Sep 17 00:00:00 2001 From: Peter Joshua Brion Date: Mon, 31 Aug 2026 11:46:29 +0800 Subject: [PATCH 4/5] fix(stellar): restore vault connectivity and wallet pairing --- backend/android/.gitignore | 19 + backend/android/app/build.gradle | 182 + backend/android/app/debug.keystore | Bin 0 -> 2257 bytes backend/android/app/proguard-rules.pro | 14 + .../android/app/src/debug/AndroidManifest.xml | 7 + .../src/debugOptimized/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 32 + .../pjpbrionfwdpeers/saveapi/MainActivity.kt | 61 + .../saveapi/MainApplication.kt | 45 + .../res/drawable-hdpi/splashscreen_logo.png | Bin 0 -> 20754 bytes .../res/drawable-mdpi/splashscreen_logo.png | Bin 0 -> 12863 bytes .../res/drawable-xhdpi/splashscreen_logo.png | Bin 0 -> 29081 bytes .../res/drawable-xxhdpi/splashscreen_logo.png | Bin 0 -> 47123 bytes .../drawable-xxxhdpi/splashscreen_logo.png | Bin 0 -> 66529 bytes .../res/drawable/ic_launcher_background.xml | 6 + .../res/drawable/rn_edit_text_material.xml | 37 + .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 3056 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 5024 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 2096 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 2858 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 4569 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 7098 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 6464 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 10676 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 9250 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 15523 bytes .../app/src/main/res/values/colors.xml | 4 + .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/styles.xml | 11 + backend/android/build.gradle | 24 + backend/android/gradle.properties | 63 + .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 46175 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + backend/android/gradlew | 248 + backend/android/gradlew.bat | 98 + backend/android/settings.gradle | 39 + backend/app.json | 5 + backend/package-lock.json | 9080 +++++++++++++---- backend/package.json | 5 +- backend/src/app.module.ts | 4 + backend/tsconfig.json | 11 +- src/app/stellar.tsx | 2 +- src/lib/wallet-connect.native.ts | 2 +- 43 files changed, 8131 insertions(+), 1885 deletions(-) create mode 100644 backend/android/.gitignore create mode 100644 backend/android/app/build.gradle create mode 100644 backend/android/app/debug.keystore create mode 100644 backend/android/app/proguard-rules.pro create mode 100644 backend/android/app/src/debug/AndroidManifest.xml create mode 100644 backend/android/app/src/debugOptimized/AndroidManifest.xml create mode 100644 backend/android/app/src/main/AndroidManifest.xml create mode 100644 backend/android/app/src/main/java/com/pjpbrionfwdpeers/saveapi/MainActivity.kt create mode 100644 backend/android/app/src/main/java/com/pjpbrionfwdpeers/saveapi/MainApplication.kt create mode 100644 backend/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png create mode 100644 backend/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png create mode 100644 backend/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png create mode 100644 backend/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png create mode 100644 backend/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png create mode 100644 backend/android/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 backend/android/app/src/main/res/drawable/rn_edit_text_material.xml create mode 100644 backend/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 backend/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 backend/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 backend/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 backend/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 backend/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 backend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 backend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 backend/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 backend/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 backend/android/app/src/main/res/values/colors.xml create mode 100644 backend/android/app/src/main/res/values/strings.xml create mode 100644 backend/android/app/src/main/res/values/styles.xml create mode 100644 backend/android/build.gradle create mode 100644 backend/android/gradle.properties create mode 100644 backend/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 backend/android/gradle/wrapper/gradle-wrapper.properties create mode 100755 backend/android/gradlew create mode 100644 backend/android/gradlew.bat create mode 100644 backend/android/settings.gradle create mode 100644 backend/app.json diff --git a/backend/android/.gitignore b/backend/android/.gitignore new file mode 100644 index 0000000..1ea9b64 --- /dev/null +++ b/backend/android/.gitignore @@ -0,0 +1,19 @@ +# OSX +# +.DS_Store + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ + +# generated inline modules +app/src/main/java/inline/ + +# Bundle artifacts +*.jsbundle diff --git a/backend/android/app/build.gradle b/backend/android/app/build.gradle new file mode 100644 index 0000000..f2ae924 --- /dev/null +++ b/backend/android/app/build.gradle @@ -0,0 +1,182 @@ +apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: "com.facebook.react" + +def projectRoot = rootDir.getAbsoluteFile().getParentFile().getAbsolutePath() + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim()) + reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() + hermesCommand = new File(["node", "--print", "require.resolve('hermes-compiler/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/hermesc/%OS-BIN%/hermesc" + codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile() + + enableBundleCompression = (findProperty('android.enableBundleCompression') ?: false).toBoolean() + // Use Expo CLI to bundle the app, this ensures the Metro config + // works correctly with Expo projects. + cliFile = new File(["node", "--print", "require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })"].execute(null, rootDir).text.trim()) + bundleCommand = "export:embed" + + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '../..' + // root = file("../../") + // The folder where the react-native NPM package is. Default is ../../node_modules/react-native + // reactNativeDir = file("../../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen + // codegenDir = file("../../node_modules/@react-native/codegen") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] + + /* Autolinking */ + autolinkLibrariesWithApp() +} + +/** + * Set this to true in release builds to optimize the app using [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization). + */ +def enableMinifyInReleaseBuilds = (findProperty('android.enableMinifyInReleaseBuilds') ?: false).toBoolean() + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' + +android { + ndkVersion rootProject.ext.ndkVersion + + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion + + namespace 'com.pjpbrionfwdpeers.saveapi' + defaultConfig { + applicationId 'com.pjpbrionfwdpeers.saveapi' + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0.0" + + buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\"" + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + def enableShrinkResources = findProperty('android.enableShrinkResourcesInReleaseBuilds') ?: 'false' + shrinkResources enableShrinkResources.toBoolean() + minifyEnabled enableMinifyInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + def enablePngCrunchInRelease = findProperty('android.enablePngCrunchInReleaseBuilds') ?: 'true' + crunchPngs enablePngCrunchInRelease.toBoolean() + } + } + packagingOptions { + jniLibs { + def enableLegacyPackaging = findProperty('expo.useLegacyPackaging') ?: 'false' + useLegacyPackaging enableLegacyPackaging.toBoolean() + } + } + androidResources { + ignoreAssetsPattern '!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~' + } +} + +// Apply static values from `gradle.properties` to the `android.packagingOptions` +// Accepts values in comma delimited lists, example: +// android.packagingOptions.pickFirsts=/LICENSE,**/picasa.ini +["pickFirsts", "excludes", "merges", "doNotStrip"].each { prop -> + // Split option: 'foo,bar' -> ['foo', 'bar'] + def options = (findProperty("android.packagingOptions.$prop") ?: "").split(","); + // Trim all elements in place. + for (i in 0.. 0) { + println "android.packagingOptions.$prop += $options ($options.length)" + // Ex: android.packagingOptions.pickFirsts += '**/SCCS/**' + options.each { + android.packagingOptions[prop] += it + } + } +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + + def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true"; + def isWebpEnabled = (findProperty('expo.webp.enabled') ?: "") == "true"; + def isWebpAnimatedEnabled = (findProperty('expo.webp.animated') ?: "") == "true"; + + if (isGifEnabled) { + // For animated gif support + implementation("com.facebook.fresco:animated-gif:${expoLibs.versions.fresco.get()}") + } + + if (isWebpEnabled) { + // For webp support + implementation("com.facebook.fresco:webpsupport:${expoLibs.versions.fresco.get()}") + if (isWebpAnimatedEnabled) { + // Animated webp support + implementation("com.facebook.fresco:animated-webp:${expoLibs.versions.fresco.get()}") + } + } + + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } +} diff --git a/backend/android/app/debug.keystore b/backend/android/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..364e105ed39fbfd62001429a68140672b06ec0de GIT binary patch literal 2257 zcmchYXEfYt8;7T1^dLH$VOTZ%2NOdOH5j5LYLtZ0q7x-V8_6gU5)#7dkq{HTmsfNq zB3ZqcAxeY^G10@?efK?Q&)M(qInVv!xjx+IKEL}p*K@LYvIzo#AZG>st5|P)KF1_Z;y){W{<7K{nl!CPuE z_^(!C(Ol0n8 zK13*rzAtW>(wULKPRYLd7G18F8#1P`V*9`(Poj26eOXYyBVZPno~Cvvhx7vPjAuZo zF?VD!zB~QG(!zbw#qsxT8%BSpqMZ4f70ZPn-3y$L8{EVbbN9$H`B&Z1quk9tgp5FM zuxp3pJ0b8u|3+#5bkJ4SRnCF2l7#DyLYXYY8*?OuAwK4E6J{0N=O3QNVzQ$L#FKkR zi-c@&!nDvezOV$i$Lr}iF$XEcwnybQ6WZrMKuw8gCL^U#D;q3t&HpTbqyD%vG=TeDlzCT~MXUPC|Leb-Uk+ z=vnMd(|>ld?Fh>V8poP;q;;nc@en$|rnP0ytzD&fFkCeUE^kG9Kx4wUh!!rpjwKDP zyw_e|a^x_w3E zP}}@$g>*LLJ4i0`Gx)qltL}@;mDv}D*xR^oeWcWdPkW@Uu)B^X&4W1$p6}ze!zudJ zyiLg@uggoMIArBr*27EZV7djDg@W1MaL+rcZ-lrANJQ%%>u8)ZMWU@R2qtnmG(acP z0d_^!t>}5W zpT`*2NR+0+SpTHb+6Js4b;%LJB;B_-ChhnU5py}iJtku*hm5F0!iql8Hrpcy1aYbT z1*dKC5ua6pMX@@iONI?Hpr%h;&YaXp9n!ND7-=a%BD7v&g zOO41M6EbE24mJ#S$Ui0-brR5ML%@|ndz^)YLMMV1atna{Fw<;TF@>d&F|!Z>8eg>>hkFrV)W+uv=`^F9^e zzzM2*oOjT9%gLoub%(R57p-`TXFe#oh1_{&N-YN z<}artH|m=d8TQuKSWE)Z%puU|g|^^NFwC#N=@dPhasyYjoy(fdEVfKR@cXKHZV-`06HsP`|Ftx;8(YD$fFXumLWbGnu$GMqRncXYY9mwz9$ap zQtfZB^_BeNYITh^hA7+(XNFox5WMeG_LtJ%*Q}$8VKDI_p8^pqX)}NMb`0e|wgF7D zuQACY_Ua<1ri{;Jwt@_1sW9zzdgnyh_O#8y+C;LcZq6=4e^cs6KvmK@$vVpKFGbQ= z$)Eux5C|Fx;Gtmv9^#Y-g@7Rt7*eLp5n!gJmn7&B_L$G?NCN`AP>cXQEz}%F%K;vUs{+l4Q{}eWW;ATe2 zqvXzxoIDy(u;F2q1JH7Sf;{jy_j})F+cKlIOmNfjBGHoG^CN zM|Ho&&X|L-36f}Q-obEACz`sI%2f&k>z5c$2TyTSj~vmO)BW~+N^kt`Jt@R|s!){H ze1_eCrlNaPkJQhL$WG&iRvF*YG=gXd1IyYQ9ew|iYn7r~g!wOnw;@n42>enAxBv*A zEmV*N#sxdicyNM=A4|yaOC5MByts}s_Hpfj|y<6G=o=!3S@eIFKDdpR7|FY>L&Wat&oW&cm&X~ z5Bt>Fcq(fgnvlvLSYg&o6>&fY`ODg4`V^lWWD=%oJ#Kbad2u~! zLECFS*??>|vDsNR&pH=Ze0Eo`sC_G`OjoEKVHY|wmwlX&(XBE<@sx3Hd^gtd-fNwUHsylg06p`U2y_={u}Bc + + + + + diff --git a/backend/android/app/src/debugOptimized/AndroidManifest.xml b/backend/android/app/src/debugOptimized/AndroidManifest.xml new file mode 100644 index 0000000..3ec2507 --- /dev/null +++ b/backend/android/app/src/debugOptimized/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/backend/android/app/src/main/AndroidManifest.xml b/backend/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..b006a48 --- /dev/null +++ b/backend/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/backend/android/app/src/main/java/com/pjpbrionfwdpeers/saveapi/MainActivity.kt b/backend/android/app/src/main/java/com/pjpbrionfwdpeers/saveapi/MainActivity.kt new file mode 100644 index 0000000..0ac3371 --- /dev/null +++ b/backend/android/app/src/main/java/com/pjpbrionfwdpeers/saveapi/MainActivity.kt @@ -0,0 +1,61 @@ +package com.pjpbrionfwdpeers.saveapi + +import android.os.Build +import android.os.Bundle + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +import expo.modules.ReactActivityDelegateWrapper + +class MainActivity : ReactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + // Set the theme to AppTheme BEFORE onCreate to support + // coloring the background, status bar, and navigation bar. + // This is required for expo-splash-screen. + setTheme(R.style.AppTheme); + super.onCreate(null) + } + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "main" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate { + return ReactActivityDelegateWrapper( + this, + BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, + object : DefaultReactActivityDelegate( + this, + mainComponentName, + fabricEnabled + ){}) + } + + /** + * Align the back button behavior with Android S + * where moving root activities to background instead of finishing activities. + * @see onBackPressed + */ + override fun invokeDefaultOnBackPressed() { + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + if (!moveTaskToBack(false)) { + // For non-root activities, use the default implementation to finish them. + super.invokeDefaultOnBackPressed() + } + return + } + + // Use the default back button implementation on Android S + // because it's doing more than [Activity.moveTaskToBack] in fact. + super.invokeDefaultOnBackPressed() + } +} diff --git a/backend/android/app/src/main/java/com/pjpbrionfwdpeers/saveapi/MainApplication.kt b/backend/android/app/src/main/java/com/pjpbrionfwdpeers/saveapi/MainApplication.kt new file mode 100644 index 0000000..82a3159 --- /dev/null +++ b/backend/android/app/src/main/java/com/pjpbrionfwdpeers/saveapi/MainApplication.kt @@ -0,0 +1,45 @@ +package com.pjpbrionfwdpeers.saveapi + +import android.app.Application +import android.content.res.Configuration + +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative +import com.facebook.react.ReactPackage +import com.facebook.react.ReactHost +import com.facebook.react.common.ReleaseLevel +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint + +import expo.modules.ApplicationLifecycleDispatcher +import expo.modules.ExpoReactHostFactory + +class MainApplication : Application(), ReactApplication { + + override val reactHost: ReactHost by lazy { + ExpoReactHostFactory.getDefaultReactHost( + context = applicationContext, + packageList = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + } + ) + } + + override fun onCreate() { + super.onCreate() + DefaultNewArchitectureEntryPoint.releaseLevel = try { + ReleaseLevel.valueOf(BuildConfig.REACT_NATIVE_RELEASE_LEVEL.uppercase()) + } catch (e: IllegalArgumentException) { + ReleaseLevel.STABLE + } + loadReactNative(this) + ApplicationLifecycleDispatcher.onApplicationCreate(this) + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig) + } +} diff --git a/backend/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png b/backend/android/app/src/main/res/drawable-hdpi/splashscreen_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..31df827b18bba369596d713b3ed5f554c432c5db GIT binary patch literal 20754 zcmeEuWmuGL8>S*6A~7gk5{i^`2?)~NNOyNiN=P?|lz_AYBGMrtAOeF(OAAU05)uN^ zu-EwR{@&eR`)7~C`964unR%W&uIsFOqSaJn@o*?`E?v5WCodxr-JlZUOM3KBE zl)$Fbe=dVf7iKF?fqvqu-T!~$|K*Sn#3hOf*_0a|WoUaZ_dT6y;OhGF1*dFdsYet2 zbDhJ4tyQr~_A)A-x%KpqqW)Cm?ZD6Rl$!phJKa&&LjV6v{vWJiOS*G2E30tr;<}=L z|6i0+Wai`)e@z^z@$YvlTr9OQ`_$A_V*S*`242C0Ui1{OWveiJlsJ{FYEUVqq#0n| zWFeWbvwHe>1KGaI+qEE6W!fOx>s;pR@f5ThH48PX@vy z==P7-D~7)eyz*5=j@ae+tr5H)vC|*xNiP1ix_UQ@+I;IrOYK|DVig`vPB{@8O;xdg zFzx;M$lG5{<2u$W+9GTN{_o2Hi9}RT@2<$(F_xe1Q+)#iZ_TUZ8b64)7I!sWhZAgJhzrX&GdH*4zP`RU!rmk$+76TTPUcmD)YR9Jb<*_1%Jl6V z%;%Bjv0M?Zf)avM>Zb%<726^&Gc$F5y7#0g-2ExY=Qv$dQ4y)cDCy$Dp}-7pnHY|6 z>LcrznW56DFt%_ilM2-}THp$}47lzrc*D@k z-C5X}77z~#5`%ZK)gh6n%`mU}JXWgH|LGGoadhXe%}s{XwY#ZnKieLcj=h;EEz&M6 z(JzyM5!p42+rcI4GTQOEcXk$P*cRCDlT-SL99fHliJ_~Fn8qi>{We)2?=*eNs=)kd z9(&#ubN2KUXEwk)JU-s@_~hi}%a?gIHMi)#MZ>k5!t(9uk&o$mAz$1a-F=HCD}FaO zrPpeFTwAG3TQiL~udpz*yqx#@_wSwN)GRbxAFJ6m^C#W^EWvvtZrvg%X?c3!p1wen zu&BmTrpaER$wZ`_ucn67xZdq{9m^?Mspv5;#o`1L5|+=EW7~!&tJgG{*pih{W4BaA z#BFTuNr?Pn3-fv8-=d--tr9JIGTaPH?lKqv1?J6E zxhHR>3X&tX+S*VH3nEvp1W*aOehlj{3r7&p-k_u5)j#*jcf$ zyHfQ0*9d5qGHmeO(+j$;VqA`hh#;e&(3q+F@S(3OHhpsP&DW6;RVJcOq&VT9t-DiJ z$W^k16m4v-sXp9)eLb=RhfY5w9C82it_Zu~Vch;c&e<9H!cOf1skU}niPpH!-mq*R z&!9;D=7RY6*jN{9#fLbq2!r>|8Cz`^;$7x$8YRyD3e4OYW+H=&GmSUC)L)?zJ-vq! zd`Y5~;s%|5)OwTu`O!*>0`c)NR&@7B%+rSQjv2$8Cr!zckvV+zPOOiHWl}Wa5)$4H z538^3Hy!=yBn%$69oSJYPPNkW!D zF&V`d!dPU3PK&XPm)94Oy`csnw*}AI@foD8N4u%o!;8~hGK<6WldZv+eY!6AN+V{5)Zb#vu&zdl!@9W?{4Q z(-na+hD4E&af+P_O@*qUi$L^$TK%n@IsLvuvrK!38A(PnP*pYmC%x?h?0O7|4KEUj z4UK)j>>8WddsLgW>69zRb^7s*jdu7{lP);{fAcVi7Q{3ZxP*k>%E-z#`tBAr`X33W z_AFJh#YUKN%CQR!)Hw+B|LmQ8%OGpa`%EIr=rj7UE7E$j{9<)$@C{ZynZ?VD#{OTn zX<`>g%A-b6vzAYuXvN3HZJ!;?daRE-ac8h8FjFk-gsuIG@>uRWf$}t&$`&>$4WrG4 z^_blSy262((T79XIL7JZ zvMX6xd?X}kP=4vN`sq8J^9ao&eRH~tbB#^y?ZAP5 zO_JMQ&T<)=BB#sEMUjQN*fMpGj=n=*l}}D2LRguh6aTFi%ZJ^8=CBSo^Qs2(SdEy* zM&<;XfGH&WXp-ybo{72kSSQGvj}haK6$`&z^9%TJt@f$WtoQUZp~ ztsaS}+35AAR}Xe+T3TSsetO@~@Q7ddb7!aKM(zH-XSqq+z}_CN!qs1EYwGpX1@8q4 z4}*xN`|6!we6zEe{r8)S*-ctM{rN*3=SEKPrP5}QMo36#l6kG1K{mm4f9-Kmk@f28 zY9Zat=$p9TUWxd|Oqc}4KcanxXuEcUF7VpE-}hHSo)P)^gvdISz{7ypm7J&F04_0k z$>pofO}n%q)pVijaz{&P;NivpndL^Qm1&n~m!jP4zqnDw?a1AE!APU}2I{rQAOoVZ zl5H9a1Tjvyn!-+nZ5dQZOKv^?S$~fyBAi~9)U~CmZv5v8cc-r3x^?Td1~a-WBO@YZ zZDGR#JopiCkn$k#)H9?#Pa^814<7II%Q8ob2j4n+5h022a#pw=1|(0Ih}nOduUzof zE**m+O*%F+gJEP8(79-I=jQhr&NYR(z3E~mfZ5Hssu@LVWymK z*m}9steDIApm=GYodw_$*pS`6-Qj7pD46heVqJ@cI4v!Wi6r)2MS97Ek)yDsMoBFW zmJ^iZwiLNLkLiHKx~y1<`7FywxsU-dn9%a<@2yJ{B05`TmFBm9n}8@07unMxULV zNpg`2#mzlGg%0@uK(Ljov8P9M6+u@p->sld01>Q#*Yq7!UI`9dyY2so zdn(pSj~9k(4MuHwvZ|1g2!}bWfq)GjZ^zy~2smbIoOx-kSf>xzJ+)BQlMPMLZUB2{$Sz@R21R`g9i!+i{9k79bahMI}Jmh`%?j7fY2R$g6 z?3^4?iF`z>+#LmW0hKCU?Vz)DVe73Q5ADs(F_1(D$r>>_CIP95qQ@_7Ym?FA&n{2| zqvnu6Eo?85|6C%b>nw8O4lqNfRejVs$Hs8 zdKdq;Xx~|Vb@iv>+(7H&V{R67Kh0UGs^oN_Cp36?FjFH%Pq?X3ON%68U|@)gi&HDn zI$Vh5n3{PvGCiF*o{2SG-}4itr?3BbHs~VZ!INLUsVc>dx#;&j+FjvdRAC}2pv$8E zIaxnL&Y1YUWjNZA2q2$^#m&4B$(Jwo&wOR^|in^(dy*<)p3WI79wQ0RISQLMMmDw1JF70@k| z!U(B?EKBaLmgVI?McM`e6)k^beE&|_Jf=m=i4$XE`W&woLp9=~DmGtUv1!!d&Y-8+ zT3G7gQBqcR6Qh3M9wsr5U%vh|ude95K*zmY{}9BqG(#spx~J7scU7}dhzwf54oA=G zNtYYdkD!YyMMcY>t!0Px7Y+3EtgWna;J!2lA0E5{E*Ha32%ia`Kju);()Z;H1}kgt zA&lYF2Gh|gwdmoTB>GN$_s4WzLNDJHp@42tO>fxhPfk}KDig(cpN*~Z!v~o=H@l#W zCogs<=BF$KG7;f?IN4-QRyiPyM{UEpEGjDZ*q#eC4m`2~fM{e_=6m!rUC_r>OjA?f zjdtlFeG*fN7ROfW({HdTT*a7>f`O-GBO?Mk()8+S={gy?xw28#c44*>NR9bkj(hUR zuZKm&E^Zr>4l)k?XRd(c0a^h9Z}_Uen3dI=Wjnf1_WsA6R0X>8Tv*x$E-m70Bmfym z(4E@>>I&b3qxNKFDflN694i2fn$9ZEnsCtE=uhtx=B z7ZxxEMNd)y5XCqx`_kA9whp2q6m@h6TJ_6NdwX~uOP}fXe-$Pcq)41zq-bo+w&jYQ zttKw*zJD{Ze%RFH_eP6qASdAV;O?X|6hT<^Bi3$imuH96(hg=XE)DJ?7T$k_j|})b zHT&68W*b=8i+=pC)6=Ds)^+;*Xr%OdBmjt#fA}Zv;Ag#AF0J|WN!Sasv0dh{=&#p$ zF%xNThj*BLT@?kG^txosKEi2yWTY@6@*1#-IZCR&ohh3j$*5TchE5kwKEA7%O0T}oC(-;#HVhRD&8t&eB{ zEubqw3bH{uZ&P#^mZoA#)I+IOY-pYul&Ttxq_ zZ)mU;JzCKS!*IGNMg#W$;w4fd}`x@QQ!~#c^RA)JJR_1%HWsjDU2Xze%c^zv= zO+=JLgD6cza@3NOXQ9{PNt|*pdys~(>I4>zT@4ja(SWMAS?t%6uukD0{0vneN@g*M zpJtU`SEOH7U8OGV5U8&2phyKBZsx)9mUg}!5Cbqy89o&tQlF&_) zrbT>oqY@b`)Kg%7J0=8Ias!j7-Sqj1yhFT|o?t@gif?Uoz{y`)kduHI{TN#CdwQZJ zNM+{C?$V$tkzX0pwSb1!4i3^5dYQjpsCbv^z6}>fLJt<8d zHZ-8J;-@9*hC1X@H|MUoQV-z-cV$OsOO^F#l301A$P&AvYf3wg`bqex*cE5b2=UMQwpJ8m(D!OPiPwJU!TaT>I>H&}q`q zk(EXXFCZcHvZhHd>}mY%Pd7MN>U%(r0&XkA9L^OXVU__9Nr970YvvlTWV#`k{AFZ% z0+Uql2=M< z^LCkE&ee#CkH-@kBTt!Q<$wkh7R;(h?N_mxD{#S59Ji%-DT=3PNo8U}C($hWKB zsf%CF#AGE|Rg@un6Q#pOLPoV=XPt+4q`4o`PEqPlOz+y{CDQb)U2$;A3{D1j({M+d`UOczE+#}(+% zk%+d6mZ!JPeSAK?D<{D<03qRUE;KQIQP43xI{G>Zsm)H;;`RM0n_SkgLk`=pLxR?m zO<}BSHHRdmq=Np3s*c4xHa|4cSOO@}zyK3mCQcOts=FHyp-!p-`Ty*%9bV9DRN3x- zZx`U??DL)th(ugO%R~irxKTO(cm)~@sD5-LH1XRL$Cy(7_qVje6&bC6rh1o-3@c`!Mdsm8mfc{Uh zPn4fY(INoQK}+fIT-VjUR3(gw5#uTt#(}8B#-ulF{(Ecs=g~^8jrB5rYkodeZqWGy ziBn+;y7Q|Oo_a?23sVZ9#K_1*OtGgbgi{JQXXvs;xcD72#>U==`rcI^3JbiQG`6e3 zZIOhMlG5=SlBlpy&%TZVPk~thiIcNJ*V$G;xL|_jqaa0W|J;4=3);pMe$L9y`N{2} z*<5wUo|WPUetX0z5*rd#FO@~b;w#$3I;Lv2EaJ?BMUH2=7o-&A>zBFDeGDv2F&FlSeq`;+8ChY-o&mxFVZ01svnD5*<;8hGO7Go{ zG$qFF+4H{w_0Z_AT>G14U#9>+?eE7xp@mu(E)!+41FO0efSmvCE)OUpEcN15x~~n( z(JT;l*hE>0A$#QHclSoB934$)-w15oQTqsq{Lfxw)YOmRHHXJ1JZoD)7ZP-x6|ewr z07PnPN*K?Ku&?_PeB}gh`XgCKqet#@74OBYoYtOvNe){5jvE{wKKAw9_Xl>myCMdA z+skL8N>;hWxLBN7x zI+>Wi4y1@CrzwQ2;SyZZ%<8!Vof^}h-9fP`K#|MV zcu3wfD=46kb#!j8uLEz|bUi!152c)l3}oTv=GdK`hp#o{^~ZJxFOuHRipsMK$VdhS z$prlAx%c6Ct(4bcwlx5a!(hSUfnvqS!_zS|gpfD{aNmtoOed$H=t@`dhV`KrE)i_X z8RBA5_$l~GVnJO|Dk!q$hK&-UVv0;e$kNhCQ%)HZleni$^*%YWLf`w1VxE#&Gz133 z{QOx_qRk5Y30>6yOzMY^XLjG79o*QUAGVDHk;puzt3ZJC3WfaC*=6T9K{pKkgi z@Z=6sBNga`7E6DHn^9zZJdUEG_ve-3mzhoCRSimh6nY0@w=hnKpJ+mqgTk z504v5?$o?M3uyxO2(K_@?j5ZJ=}1Zz9x5OUV!9VMti?{ZuK@KjcXfRU!d7698&z8R zmRgxJuzqqXD&CAfV_>o7z0j|sq})MnB!k|Dg#DkHks(r3Q8%r|ITYFaEXX~ z`u2?xJ+&WB{}7^;m-zF;?v=x}QpMLJM!ZkFyfQ$=L9=ikSTCaov$@u`OtO;R-eRSt zrSL3$m`qeNyYUAQusTSi!_;681H7fI(#4%cp@gEPLcZI&yT9OQJ&bVlqMF8^_b`eq zDamTs#HwgJ#{ukMkS6o^=sd~Bl z`es0DtY~f~=nhW4r@H7%)7%f9K>zV^rdjMbKf3wK#<|rKI;^{f|uI#?Y#-ut; z(CI%p0$}m^;UbmTIfa9RB2nyB|9Wb3=(6b7xHtAWzfdXG)6@GjF*4E%<+fj;c!Z6u zZ$YuRnVBROJD<>L>q{ytBe+zK*TX|17|AVkb#=A$9VmcseGKjo#&X-=HNnss z)LlFj8G!Pa(b4Mr3$c+^Y_Zulfw%2+kxspLc~w$ENoHZIrht|m+OMtX8W~v$Ja9E_ z17(Sq3EALbBTsH&tIcFdS>L&M-4o=wP}`>z!+%LgNQe#K(~@Lqw0TztvW55dt+xC7 z`=9sY*BHDjFaNVz9K?`C-M-R<@8O~OO3+Pd|KOm;VDI3-W1*94dASHZ*Zji3?9b!J z#vXgc8nSoK%;2`d$_99Yr|h?s6q&j%bVx$7$s{#B5>;;<2ZG>&fuSMil`B_x9o+xW z=c`3wS>X0qVwCYUi#HlBgByXC?$Ej@zXE(BRd4mA6I<^BEHOvN6f~9TwXA+6e83D- z11hI9OX^25$xx?h|K0xA1@dQSXa5jIbSEc@_FI-rZCzvI1F*4xfkxFE9b0WOC)Kj=Eul+T?6b)W7i(l*O`FihNW{Zl82~4UQUV~HC+`c-p zmDHawKRx*d5v@xl;`3bFZF^3fo-h{bVk=b8k>XhkfvE09qFBY4`(Rzov<75Z1F|=b zLwCus(h06c`d4qX@WF;0aw z{?#6zMkH!o8wxW3+wb24lvGrzDPi6y>L=^_Q(1NF#zF2Lg|}<1tGijy0y}{lg}|4E zjls&8tulgZfm^3fZPIASttzr3DC`svke!-J4?-{?j876dq{cqM+Md6LZm_W}aiNAx zr|Gn{6~LJF`qmzLjXAyd(7sLxMV2`{HYN?){^U)3sHU{v(q(GPguOS1rZPHpDs+gI zSx9tN*Vek;fA|1AKx3nlK?p%gVPG>cnezujK$ZnseJ?!a9WLr=aFqYu#@nJ%B$LKC|Fmto5yB6J` zHKt@_kcatM8gn~>2klA~X+2qAHa?CMalhUPiZJ50Jj1uI%gc;AJ~Nd_ z;|kES`x`vh({RE+9e$e6Grwj8C?hzS&j08X_ZmLcocR9X;#9x;lYByo{Q~XNLDGHVn)lppdE>J zPrWu0R3SEDNkw<-jg-wz=f~_7i@PEgwi-G*nNNvhOQZh2CUhz>ET1bKvj>bSo$M(5 zZnC{8cWqVQy5{Ohj{SikXnQCMI1r(`M4iU^1Z<*G5C}+Iw(w z`%R%0+NFfCo%0s!TVO7-){}+WYElfR)sDmNXGyafhKq8P$meVY zV@d^W;s!suWWq8g-z<;RID~?}k{e`QEJbhT4;^5CzdHYVnw2_qX1lU~>+FS~b@@Hv8ufj__URDVhrEEM?4@T431O zIgv{le2uCn!k&z|4@~Qwd*i2;f?+0Mq;}~%j61k~wgMSS5&C5j75ZgWn()*COFAoW z@2;UgSkH9dUdYtm?XBJ>UnI}eDjjRk;ia%zVeG%jsq20)R@xhg>3Y0_ZIQ%fa(^(9 zqzp8c*)dK0clgT6AwbfL0~%0g&`sP3;9_%vo+5+!LULyV1s z!z^w-sJGg&7Jq223BTOH=AKj`7u-B6D=TW(uxpDA&FMpUeR5(KM-T6Vx>%)qt;@V! zFro0!gd0mDAG_7BC4!5+f9Tt%>JVslZzcqeR2_w-=#wD4G6vF{^o^&>8TSbD2p58_ zZB20KXe>zrmQ>G07MP}0r^FMMOI(LQ8AfaIZj zBQA9CQxcG>x+MvITlo8jJrU}^7=OAIAm!q68}I0pH|TsfYauF;Thi!c>_kYIsug6jBUT_`3Af5{AnE8@-}Q zx~#0no5Z;Kj#oOs*dqE@Qr=Eb`>(NQ65&VU9x$c%ZV*|B060c-vIu?%C@8ayw_k8> zq$nW!T43$v%PZJ{DOSSpEg5}@CFJ$CPQ&kPc~LFk@Cx50s@|EZR~F4J{@&NOROLjO z>omQQg5Ch;RWA$VVGri63;nm|8p{hOZ{lLvY10$xl&>#LPfl`fJcoo)>!Xk6US8V6 z)_;yZ;9#;r5q{$BU8M=eyJ)u?*!#S_)ggzF^7`+NSI7bLesZINqSB>Q*A(sIQS(J* zs>X&OVR4R?NZU@J%bYNGy$Sra8clHG%oNMC?^485WP&AA?*yfhU^oZXKXaGZl-E#- z0=k+cYL+=K@Swm6W=S>o^(BNl0~*q|@O2O#F=4;cmuSUgFZiBn)-}nC&=iv+zY4XR zV&`h${ClUXp(L%QoUgz9^vop02_HqtbX5XS>cD@i&5D-cA;rL58$JErB?}Gn$Lzzi zEvM=HL7M`r)K;SLLxR)vVTkyRe{a=g&gEb41bx;{8zOs-@^`*|@ig*MVC0Dch6p|B zt?eyM|O$4c6 zaMQA@U1mkWgoE8Y!p_DT2AzKyO*4xja|dXN$RI>K7T)G+*F&iJ|7tV^kXVqR4NOdm z^-8pEn$VhZfo!1yU?oLC+P|gcia%rrMSiuOA5(%9y_2d?3aWz_z$f0|XW<+fN?+e; zl!Og>8ew5!;r?57FV1GGy6p$IGdMi2LV&pyRyQC+Ro#KWXIsV z2UR3!-POrp#B4)cf;}Cnm#{d`nyy$>SSb0gTp|JgAgd!l#sG&XGpWatDP1w*evZwg zJQ(hM{rv#iBOoKgP4E_?Wyw9b;L&7(dfKvaXK*q1%g+};(O;A2tPtX2;epcd0w=QL zU!#JG$kz@`>PfWc89i<5yi3Oy(tf#yHn$T=% zX=-Y2yzZuX8aFj%=bxdJc7v3CI}dUzsy&v~hhUk4iFIq^bx8^H!j4K8$uvGoCK%|^ zG8Tu9(=z|?TuaNtnf39q=@`cNxFt^1P+r~g-`~t$FUB)>b_k&{g0T6Ke|L9RglQQ) z#1hQXlHegjp#xi1rO9)hA5uSYTyb$rw&TC2HDm6h$c~Tw{y{r!#$+>#!jONU#E@OK zsv&NW3}pB0z0VAZoMK|36(H0F>~!g%+^F=k7X|&{$2-Z){x@#;()cbBdS$NcsG@~- ze#IIEu~GVQ=m9`DGLMH(wV6WNL_t>PDhY;AhwqFeQvU9 z0tByMj+@cdRr6rx%a^`<^~%zs15IHFDWYCI1Fj81bf>0ZgO_a{dw20-t;yr0k9|6N;!BQ2HY~?rLgcA`3W-i z|jU4c7Yv%I65Ulrw{~Z+CeD;3h*6PlS+<= z^qrfK4_iPR1E4rWb(wEqL4xPmKamC^iFf)lv$6_{i&d*24M7b_G&G?EY{=($9g{8a za9&n28Q?_trvh_D2nNmu9AulP|JvAC8p;>r=JULTE@qt1e=hZm^bHQy7{LE{{8_T& z;e370y0EMGiFagB% zl}5k)q8{t+Q6qpi4FM-Y9Buw#@H(&L)zuIGz!g5ohE~E_rF>m!b#;$axuQCna~Wo)N8*AKsSJP=Gu#@-%+kQ*%}P^{8|7MnRy z+pxYMjVujrsv`Zcw2e)%IW$SgnxZp0p}K4+XZPJ@<&lYWb;pdXEHiU+j(&Zx0N;Bf zz_n9C2X}458dx*pSnDUfq98(?iA({tv6B=R>j>hL#LaQznYZpGnCVs4KDh>#8i?Kr zg+3?0lc8Y<%($2U8ru5cadTn}7w@NmOK7iOLbWS^6Jw2U?@&GxY zJ&<&mYO5AS#Q+j@WAGp?u|3LRVt6)L+5i`)vRF4$+xx_^ERlhG$Vqe^c{T4~))s_21u5Ck$JT>+alS9<8lk-kEEc92p*F*G1MlPK79E@k5BL zt^3z6OpOxU+VM9d`V1M4(%<*?-YF@~w9m}2k&r07(Wd6*=Qj&%4Qp+UJX|e~to(iH z(>&k8!O8H@P)I}s$tgv*8>f&^m|;2bJr#e5Cu!IG_+dQqEt8ZD?ZM_tUca)|smjsRFZY+3@!O zg7xt_n5{7g3~&5sq2xnzYd^n0DM?Ap{{H(uIaYR7OwIzzr0dM8K`Gg_eK^8JQl}?a3r1g&9;DA$&JjaYsoCrICkVi)?Jo83(uf?AC*D>qFl4`iIP?#+(9@?+VuXq>5_pP@)EE{_ zU_dosW1dFI6zaAGUh&%cfnNdA#mk%=Ns(48$oSEwDnt#gbo6qgOzqd0CGr_Z+1S`j zyAyuX`lVqF^KfV2f>CY4nC?KzrhwER9vKO}Z%{vH%&_M-N3N;xlxkjL$xf>+?ztM!^ab;-O7<0yWsG+`2DR zR$f z+#z>EL(jnfXMn#s`D+C9ix158n|fD}L{T}#kM>yqZU%J6#p6-3$usi&`u&?v7fav4 zajJT_Z-4|h?e&N+=p;>-;TRG$@~^9}OnWvQ+rjA|0aNPd(Dby!iyquHnuiqKo8Oyp zqXNS*hAXyD&Z@1I<>I*Bz=whG3>lU*$)``7Q+lP{j7a$)`(o(DB`AokpAA5bh1h~k zu@L2H1kc(z^jbV1vvB>Nmx&@fJR`vfe)jB_4ilmUvdSl1qM{*9S}d_3VzH$Yh#p=F z4Q+Yj;OO|G+52f+6h;|4itL@Gb8%`1ts_q5K0n zdR=w^l|%Z4;O7(-@j(Cq(GrC*?Ba9q-J6SdG_gsEG0~;<2&)%aQgWS|+V|h^HI%o1 zk|5tZZY+;g=n_XR+V3h z-w+b^4eF>d5mg%UJ5FB8RfQ0u+WSg1RDYI$c*R8c4br5Z+WY}GDqFmFCT%pmKzQ=B z-ae92(=5@dbT%T^5XIulZDv5B4WUibE9^A=9paGisR+3#gcl zIvER#8%<5+&y3^C%UNw59fQXyJOkSZdMph|%o;&I+?^8_1G*E>g>~bG$IZlU7|T$M z;jJf!+jKl4Gl@-4gkr(iyOEZpfkTfanoHoR?|@z@yDM#B>rHv7^G)mnxfeGb#=-lJ zr?9|eW|at9;J%S*9XUpGF$Aq?ii zq7SKaxCOR&_3*b(?(#_eyJWTMFc)fzyGMvvq}!?nY3(=`&2y!qDmhg5Z8IOAQPWfp zDp~U?-V}{DBi}-}(k|2fbSH-Sz)K5W)EfT!B1QTQ;boA+&d(2ADnFZE4U>ouk*=qf z(V2LBg+SPS>G`uf@isZ6{#BZl-6L9h^iQmBG)nUHyEsk*DSIsSPXlkqap~ggJB;e4 zeRR7t!G|DZLc+z&?b;2)2V#|Gj8pLK_}oO1wX+~oBw&SVxT)F11#4jBszQeSYAl?A zGn^p)aEA~U^40S70u^R)UWzXIb{utu{30asYWXx9?chkB2~<}ax4X(+4x<4;3To|JAI29v$eIw_THS~DbbRt?DRB()wY`vyA6K(6lqxyrh|hTP}71J1>Yzlt0Coa24SFx%V%@~ z&NG~17c+@kEDX8}g81+^sOVeWa1m+KaE5m1Tc+%HD32SHJ0$+1xzB!G$OZo*_-x7T z`aK4ud)OKn!F+Jkt=;_=A(gNfQ38+4^0GB<8ZRH8+gA_o*^Ja^6*%n4iMuvo# zl$HD6fGWZD^A8oIs<8;$-J2l*i4lxtTc!>w+-0r1>Ak_f64hvrL*W=uVp3Az=+#g< zT>ONE;X+v~*17NA2MQuIsXIIBqk3sF{L=~L~K*P?skhY%PG>z4qY7S zX%fG{DV@rjjEszZA3tJa1k<8-Z6$ml;!GV!D(JZe&h3CbhzDF#BaOWa@fKy~R0S+n z(~bx{I0Hv|d~*Avr_m^KgghgMeW5R-h6$eC69eM32)}^FCC-vc$Oc=y?c(weUmH>= zY0pyCSW^4qDFyD5DCRla+FnAxe~Jd}aUoHZu>@fHawFlLrJg%$)l>Yh#DdffC%P1D z?d?B-I2uz@;szA9fE|HNn?10&HdgU-yvzU)(BJ@BDCn`dQ0OS3c>%5&1@qX<-JJ+> zV9Y=XD{sQv9PN_c$uf#;x~EzM$3&(f*+A<@4t;?+L#Y6HH{|Gu{@-Ule2Nbp1(UE{ z_I5zj6TdQYa&m4T8TzD8+S{rmACRnq$D;YjtG0v~gI<%?bwNTL@#Y(QedQb&LMV3$n{q+MK; zdjH#)&#y`R;;0H`Z= zo!#`wlSwuSBPJpl_KAd@oqLDVvnumYHsI=gKrjNn%YXj&y(SsCFJSvCfU!MMWB^vK zFfGFC6&aJ;6##&;hDi{@jcB6Fqobd;q4Eyi6}F@kCC@&_(gM7w{akHNDP}2u*4`Hu1M$3Vm3sMrF!K< zZ8MJiMOQaO><6+>ZXWqZnkLO|MRGX|jd@;$QxGVH-IFskZX=471`E}*p&UA6o{H3S z1uM*08d0iF*cr-qzA}M7{pilkc6(kPo=`Zch_9ME@De!Jj!)^Fj*^OK2p2I#y9wr9 z$zm}pK7x-!7e4Hky!dA_deqT77E@Db|nmPXAp?v+18BuXg(BdNVzBhTI#DcjnrZxlp54*f~S%N!*6v!r2% zu7k=44CJzi|KyEswL2b=}K-BEcN41IJz=rGS8Q zcMl&vJUm*trrXT#{AnJmod>!;|8zv=)D*Y#%ppDxk7|Bh9unCFDN~p{H3hQ=ygk-9(ZpmF1i0k5CT$rB9y3E-1-p~c@~<~Ny9+|s6$nr z>)J#(SC0TgsWbJ_)2PxTuov_I_%=R>SzcxWR=_QCiVcm#1t+|CLGT7Fm%z4JVD#4` zCE;jXr4uEXBF_Mog3*tQk8d6rNCU3%%Pdy(Pd9GdfYS*>-vAPI0=cUCjU``9xoxn# z66>>POO^DQ;=|eBXp|lkC9~k<+(!JbJGyFzDC3;2|9QBh z;_-LG*OJ?*ASEPFW+IOxMjlX%0p3h)<|s6RFz=vd1?T5i8qd&!j~$3sDx zWl5NGmmctNe!e;d1;q|-`wR17@v2{!UP3$X=lIm=jP^ z6>A?U)?~bCmvV8K*gyH+MZmaNHjyS{eZoaSbT&a~!V|ExO~UQ1u)&pEaD8|MIv-bd zd!ldU&cWJ9lB<<)h|hHNqCP*{a_;$=V>(i#>|?aB)6lu-#`XfDFCg+l*y$2Xb7Nx{ zj1C+xc?_JmYvEN!P7YDo{Uvuj013C?xI-ll`1q!-u3FGsMjs@EMn@CA65NT_O}kp4 zBOdyT7>XoF2_dCA742IDbY!^sj3kP4J;{1dHm`#6)45K9A6W&E*b!_{J`~yN))qhu z>>QDdh()dVSr-NbHdxfpW?ed}*-lLw%45UBZ-T}R(Lm;O(!9F6fP6BPSlt_8&_CIm zlX!X>B|S35Gq1v2gNcOBKqdC$dV!8ST!`?KU$oA%t#A^bnO8to9k^kB9Rai-NP$L; zNl6Wjk4Mzk^Rp4Mv7{;#0R_-y1DE_GeCYrQ$rreF*fR7a?v4B+KHG&=PHl(&6oGBG zp;#ozgr|^!V+QfXT{yNwhq%f-UliEVQu^DoE`dIgsqh zI){6pNJbf7yIL>-p5|OA0lvBE++|SU*5bI}jN#$mX-eQcSbO?_=HYPh1F1qc7&Rf# zbvU;#LA8|P&cGaAFL<;^5iUXJf4q9VZ;+Hz*nm^l9QV1(itD^YI?U%Y3t;J8_ zy)P83;0%$v0Q?0~<1$42FhH!3sz}Bdb|^~u^mL2*5qmm>k3~nLvGomVe2$;c6sraW zOXOeDhk)&6^v|oS^gzxKgrm^^^2+WrY_%NF066jc&Ksp24Y_GcZaYvBSW2{51J8eXKu|yQBZS$MR9FJ`xVO?kE8u^e-F+o@HvNT5heMn*{cO+sIGHtqrt*1WaCT(^-N?HNLZJrG zhcv;T`JVa^bteQkN?}TsCSeV;{Mb(IPj+kcbH$;Ea5y-P0o z9EXyDK^7ZE%S$e-mX;QXmpX%7@M6$=PVc8XIeZPoWZQ)iNXl$C5oH=UQl*CUNgquv zj>*AZ1o?pzl{ZlDw6seNUoVk{jzRu+i|6+yJl&wszy*F&QW=mFoxMC=uWl39K4*Gc zf-WA8_VK`5ULIyC7GENq2FDamb-ICQB@!S6VCyQOIDC->tVA`I2XHpeBT9w=1kXe? z*cYn;DbM+P(_KwX)g*;F`rIvq2yjzyyLfrSTu%?VV3*TZ4AK5Ul<~o>McUWJI83xk zG#W~?r9A^CqVHhI?K|qfKjsNXt|yy3W9=LqlBExM;66aOdEz~rtoBB|V3;IKLfI#c z3(LZy!@587In~2sG=aJoyx&5iqwQ8V zMI#{<1^LFIuU|t1hDS$J#@@Y~tQWZgeM?Bll7iyXpZUnh`GXVjrN`Y-yn3 zqiSl$(G)f|j;kT)f({PTWhhvQQ&3VS^;#)AIIsezVnY7w(J;M`As(6)qlM#(+eeNg zqeQ8XXyY8~jkYnMQ~I3x;Ff4%T*Lq1@J~O&do8{f0bhagXFzx>Z+Ug3_;8}_JbZPP zd}L-O1ci#4Bc~5B<%AQ_cXTzFQY;-e_=}2jUn(Hk^jUd%c_E@U#Va5nFZclq56>a5 z4t0B85FgHyaR~^-!YKi;@XP>6Bxr`uZVAN4t3$5E);XcD@j-$#+@XZ-BZ5IqU;UEapNzp5V&Mt+?0XjRZza3W0L8f%p&(;&y&tvB;UY0Jxuyz4hpHgizsZ!YQsNtqexZY78Z7Z zZ@2(kox;OI8crmUS>&Z$Evu_y%eDO-I{wYJtgHSCz!F`y0uAOY`!P5=iP2s1(teC^ zqD(@nePskYQWB;^f-#vN4p&Xq;~|N1=x7Tr#6zP3lcQ+KaN*#R0vk!k4eawQ)8Pyr zn=0R3ZOl*-XlqP|E+M415W`yqkEEoQ#Brpgq-b9MZ+{eTgOfsvK1SSAEcyiona7cMFjQ(A1fg*AnpX2d0zL?+}4U{8?98$a#N}Dl0q8d4l7RB}IQ1 zR2E~e^>J^I+!<2bhbJeoE1Ck&us~Ufkubw)G{iUdJUbTaTkbcow6wfr@ISUKr!oBQ zuCM;U5k*dZ`F|~-BTOcI2ab9HN1^td19tF%Q|c8n4fV2s*%G)R>0v3bTD_Pd5~s=p z>QI10LZhNrT)gFEBE?!cpGi<~BDM5z6cYCSxU~{y+sKrB4d1Kqi0CD3eCv du;4#SWrH8f?l+Sc0?#^R@O1TaS?83{1OS!}Ir0Di literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png b/backend/android/app/src/main/res/drawable-mdpi/splashscreen_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ef243aab6c07672628b98d8eb239605edfb97c5c GIT binary patch literal 12863 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 F{}05A4LSe- literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png b/backend/android/app/src/main/res/drawable-xhdpi/splashscreen_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e9d5474519c701b4b518f2f0a24d7d8742e93416 GIT binary patch literal 29081 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≠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 PMTS3g4RtcK&inljbZB-$ literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png b/backend/android/app/src/main/res/drawable-xxhdpi/splashscreen_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d61da15d2410dd60355d0d9ca34bb2aa741267f0 GIT binary patch literal 47123 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 literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png b/backend/android/app/src/main/res/drawable-xxxhdpi/splashscreen_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4aeed11d00badbb02d5b40a3d24fcf97dbabbd5a GIT binary patch literal 66529 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

^;WArDFIvK1}FmU%q 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 N_G%kxm1)=q{|~x=+3WxS literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/drawable/ic_launcher_background.xml b/backend/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..883b2a0 --- /dev/null +++ b/backend/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/backend/android/app/src/main/res/drawable/rn_edit_text_material.xml b/backend/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000..5c25e72 --- /dev/null +++ b/backend/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + diff --git a/backend/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/backend/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..a2f5908281d070150700378b64a84c7db1f97aa1 GIT binary patch literal 3056 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 axPAxe%7rDusX+w*00006jj zwslyNbxW4-gAj;v!J{u#G1>?8h`uw{1?o<0nB+tYjKOW@kQM}bUbgE7^CRD4K zgurXDRXWsX-Q$uVZ0o5KpKdOl5?!YGV|1Cict&~YiG*r%TU43m2Hf99&})mPEvepe z0_$L1e8*kL@h2~YPCajw6Kkw%Bh1Pp)6B|t06|1rR3xRYjBxjSEUmZk@7wX+2&-~! z!V&EdUw!o7hqZI=T4a)^N1D|a=2scW6oZU|Q=}_)gz4pu#43{muRW1cW2WC&m-ik? zskL0dHaVZ5X4PN*v4ZEAB9m;^6r-#eJH?TnU#SN&MO`Aj%)ybFYE+Pf8Vg^T3ybTl zu50EU=3Q60vA7xg@YQ$UKD-7(jf%}8gWS$_9%)wD1O2xB!_VxzcJdN!_qQ9j8#o^Kb$2+XTKxM8p>Ve{O8LcI(e2O zeg{tPSvIFaM+_Ivk&^FEk!WiV^;s?v8fmLglKG<7EO3ezShZ_0J-`(fM;C#i5~B@w zzx;4Hu{-SKq1{ftxbjc(dX3rj46zWzu02-kR>tAoFYDaylWMJ`>FO2QR%cfi+*^9A z54;@nFhVJEQ{88Q7n&mUvLn33icX`a355bQ=TDRS4Uud|cnpZ?a5X|cXgeBhYN7btgj zfrwP+iKdz4?L7PUDFA_HqCI~GMy`trF@g!KZ#+y6U%p5#-nm5{bUh>vhr^77p~ zq~UTK6@uhDVAQcL4g#8p-`vS4CnD9M_USvfi(M-;7nXjlk)~pr>zOI`{;$VXt;?VTNcCePv4 zgZm`^)VCx8{D=H2c!%Y*Sj3qbx z3Bcvv7qRAl|BGZCts{+>FZrE;#w(Yo2zD#>s3a*Bm!6{}vF_;i)6sl_+)pUj?b%BL!T1ELx|Q*Gi=7{Z_>n0I(uv>N^kh|~nJfab z-B6Q6i-x>YYa_42Hv&m>NNuPj31wOaHZ2`_8f~BtbXc@`9CZpHzaE@9sme%_D-HH! z_+C&VZ5tjE65?}X&u-D4AHRJ|7M{hR!}PYPpANP?7wnur`Z(&LFwzUmDz}m6%m#_` zN1ihq8f|zZ&zTL92M2b-hMpPyjp;j(qwgP9x)qI?EZx@<$g#>i7(MC}@*J1VGXm6J ztz1=RK@?%Qz^vmWNydd0K7oyrXw`TLb`z;fP6eV|NZ@9kKH zIyMqzZ9Y_)PZnC#UgW6&o7RiGXSCtSQvnrvJ07P9WCuE5TE27za*L6r1qX7pIDFiP znSaHYJF8sl^n0|3j!i{?fD%?fpQ8-}VX4%STy1t@8)G-8??Fy}j}~2_iJ79Y<9BW~ z!~)T{3Y|lwcVD5s4z^GP5M=~t`V?*Wng7gTvC9%p>ErZpM)pQVx57>AIcf1j4QFg^w>YYB%MypIj2syoXw9$K!N8%s=iPIw!LE-+6v6*Rm zvCqdN&kwI+@pEX0FTb&P)ujD9Td-sLBVV=A$;?RiFOROnT^LC^+PZR*u<3yl z7b%>viF-e48L=c`4Yhgb^U=+w7snP$R-gzx379%&q-0#fsMgvQlo>14~`1YOv{?^ z*^VYyiSJO8fE65P0FORgqSz#mi#9@40VO@TaPOT7pJq3WTK9*n;Niogu+4zte1FUa zyN7rIFbaQxeK{^RC3Iu@_J~ii&CvyWn^W}4wpexHwV9>GKO$zR3a&*L9&AgL=QfA$ z+G-YMq;1D{;N38`jTdN}Pw77sDCR|$2s+->;9gh-ObE_muwxq>sEpX)ywtgCHKIATY}p&%F4bRV>R9rYpeWbT(xnE7}?(HDXFgNDdC^@gUdK& zk=MolYT3>rpR*$Ell2!`c zjrIZftl&PUxlH2EgV+3VfQy&FjhL&5*Zg&R8xrSx?WgB?YuLO-JDaP3jr*I~qiywy z`-52AwB_6L#X ztms{{yRkRfQLbsb#Ov%`)acN(OCewI3Ex__xed17hg#g4c1blx?sK}UQg%PM@N;5d zsg{y6(|`H1Xfbz@5x{1688tu7TGkzFEBhOPDdFK(H_NQIFf|(>)ltFd!WdnkrY&mp z0y@5yU2;u1_enx%+U9tyY-LNWrd4^Wi?x<^r`QbaLBngWL`HzX@G550 zrdyNjhPTknrrJn#jT0WD0Z)WJRi&3FKJ#Sa&|883%QxM-?S%4niK{~k81<(c11sLk|!_7%s zH>c$`*nP-wA8Dx-K(HE~JG_@Yxxa;J+2yr+*iVlh;2Eiw?e`D1vu6*qY1+XTe8RVu z?RV%L|Mk!wO}j^S)p4H%?G37StD0Rx{_Y00%3a+V^SyOkfV@ZuFlEc;vR9r-D>cYU&plUkXL|M%1AYBQ3DI;;hF%_X@m*cTQAMZ4+FO74@AQB{A*_HtoXT@}l=8awaa7{RHC>07s?E%G{iSeRbh z?h#NM)bP`z`zdp5lij!N*df;4+sgz&U_JEr?N9#1{+UG3^11oQUOvU4W%tD1Cie3; z4zcz0SIrK-PG0(mp9gTYr(4ngx;ieH{NLq{* z;Pd=vS6KZYPV?DLbo^)~2dTpiKVBOh?|v2XNA)li)4V6B6PA!iq#XV5eO{{vL%OmU z0z3ZE2kcEkZ`kK(g^#s)#&#Zn5zw!R93cW^4+g0D=ydf&j4o_ti<@2WbzC>{(QhCL z(=%Zb;Ax8U=sdec9pkk|cW)1Ko;gK{-575HsDZ!w@WOQ^Up)GGorc38cGxe<$8O!6 zmQ`=@;TG{FjWq(s0eBn5I~vVgoE}un8+#YuR$Asq?lobvVAO-`SBs3!&;QEKT>gZ0T)jG^Foo~J2YkV&mi-axlvC}-(J4S2 z;opuO)+FIV#}&4;wwisb>{XU+FJ~tyK7UaG@ZD^C1^brazu7Xkh5Od}&P)GufW=u# zMxOwfWJ3a^MZha>9OmQ)@!Y;v*4@+dg~s~NQ;q@hV~l>lw`P)d`4XF9rE?aEFe(JV zI>11}Ny%^CkO=VN>wCV?P!-?VdT3vWe4zBLV*?6XPqsC%n93bQXvydh0Mo+tXHO4^ zxQ{x0?CG{fmToCyYny7>*-tNh;Sh9=THLzkS~lBiV9)IKa^C~_p8MVZWAUb)Btjt< zVZ;l7?_KnLHelj>)M1|Q_%pk5b?Bod_&86o-#36xIEag%b+8JqlDy@B^*YS*1; zGYT`@5nPgt)S^6Ap@b160C4d9do0iE;wYdn_Tr(vY{MS!ja!t*Z7G=Vz-=j5Z⁣ zwiG+x#%j}{0gU~J8;<|!B1@-XaB@{KORFwrYg_8rOv({b0EO#DbeQRm;B6_9=mXGf z-x|VL{zd`)#@yN}HkCSJbjbNlE|zL3Wm9Q8HY`sV)}3%pgN>cL^67{Z;PPL(*wT8N zUjXU{@|*hvm}({wsAC=x0^ok0%UAz0;sogW{B!nDqk|JJ5x~4NfTDgP49^zeu`csl?5mY@JdQdISc zFs!E{^grmkLnUk9 zny~m)1vws@5BFI<-0Tuo2JWX(0v`W|t(wg;s--L47WTvTMz-8l#TL^=OJNRS2?_Qj z3AKT+gvbyBi#H*-tJ%tWD|>EV3wy|8qxfzS!5RW;Jpl5*zo&^UBU=fG#2}UvRyNkK zA06Dy9;K1ca@r2T>yThYgI!ont$(G{6q#2QT+00r_x0(b)gsE`lBB?2gr55gq^D3Fi&p%E(p9>U%bv zkg1Jco(RbyTX7FDHOnl7-O@ zI$AaIl?9NJKPm(WiBP`1-#CB1QzU>&hKm)fpa5DKE{2$X0hGz-0uZ?cyTk(YC!Y&| zL=1VrNERSA5NA2jq7FACfX4JfPyj5XXl1yv0>~s;eF7L2$>&oMqeTFT2m$y7FlkON z_yurD1yIOvA;5C6016pyxBznGUt0kJ&k5r#;&>Jow`r)sp9R~PmK~lz$3xH%LT*1U zJdOyABZ3!FvNoR*vN$5ykHS8f`jA4zV+|L}i1C4`B2c{R0;UdYxaU|H)2avz@ z=mEYc|2S<+(B2Tj+FkX+2D+yFI!k9lWMA61DJ{)e;lum$(;O87?vGJJe!KtK04+N_ zI*P~t@dUb>9Xh{dbyl{-ZQ(UMgz7$|QfL5XSPkskt^NgctYC#;4WcZB1@%@wy@2t3 z2z0DI7&%b$*Aw~abe?GxE`ez@+6hOh-6*8fHRV{1os$EL@}uUZeG4h1&Be`98q*7j z=3-v+lhIjfWVo12!<>%V^a6lTgW3+_#W6n|p*~==zOH7z$0{LSZk(Tpd7EaD04hnA zL;#fxS0aD{`5^&D`}>0Uq?byDD-l2=!wm_bLcUl4gc(% za1p|itVANvFF>hghAS07Im1;IK;|b*W)}VDyI;BIp2=K*yu2a)j?B|f<44NI$NbmJ z#dE0>jI$fMr&@>4kN8MLFb4&2O9fEKaQg%(QO$4_1rVQywG^CmBLh#}_7gKW3vd?| z2?1^&KWq8}8I^_S0|)MowU_pw$q@nl@Nkn$z>BQq_KA^9yaR`(R3u{{Ig;cwt z@AJ^{ODQCm^neroM9nKNUAXi9RCK`OsP_LuR0PUR(YZCCX5dNF6VzcoK&=b^r`W?ltt|*F zpkoae%ZT{C1h~EcFui~b7fF`vb<<~j_VquuUA$}QqIKYELPp#;{u?q8Dz}WAG-(3; zjrm$i%7UbyZMM(Y{>!uJ#vNB?R~B{6Htp=>e*<{fQQ5W7V(1coCWlOON!MzZxhum| ztZBQpGR z;~#ur^&PockKdV{Q6R>o`Pl{0x!DEbpZ7y9Y;*ZvE!*gU`V1W3znva{f=?WO5I&>B z&hw6}tjECtaghm5z|C#%M;Yf_*pI^};h}Vl=^r9EN=tVDj86D;C$jIJ?K7VP+00000NkvXXu0mjf D5i!M* literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/backend/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..459ca609d3ae0d3943ab44cdc27feef9256dc6d7 GIT binary patch literal 7098 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 literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/backend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..8ca12fe024be86e868d14e91120a6902f8e88ac6 GIT binary patch literal 6464 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 B0*L?s literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/backend/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..8e19b410a1b15ff180f3dacac19395fe3046cdec GIT binary patch literal 10676 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 literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/backend/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..4c19a13c239cb67b8a2134ddd5f325db1d2d5bee GIT binary patch literal 15523 zcmZu&byQSev_3Py&@gnDfPjP`DLFJqiULXtibx~fLnvK>bPOP+(%nO&(%r2fA>H-( zz4z~1>*iYL?tRWZ_k8=?-?=ADTT_`3j}{LAK&YyspmTRd|F`47?v6Thw%7njTB|C^ zKKGc}$-p)u@1g1$=G5ziQhGf`pecnFHQK@{)H)R`NQF;K%92o17K-93yUfN21$b29 zQwz1oFs@r6GO|&!sP_4*_5J}y@1EmX38MLHp9O5Oe0Nc6{^^wzO4l(d z;mtZ_YZu`gPyE@_DZic*_^gGkxh<(}XliiFNpj1&`$dYO3scX$PHr^OPt}D-`w9aR z4}a$o1nmaz>bV)|i2j5($CXJ<=V0%{^_5JXJ2~-Q=5u(R41}kRaj^33P50Hg*ot1f z?w;RDqu}t{QQ%88FhO3t>0-Sy@ck7!K1c53XC+HJeY@B0BH+W}BTA1!ueRG49Clr? z+R!2Jlc`n)zZ?XWaZO0BnqvRN#k{$*;dYA4UO&o_-b>h3>@8fgSjOUsv0wVwlxy0h z{E1|}P_3K!kMbGZt_qQIF~jd+Km4P8D0dwO{+jQ1;}@_Weti;`V}a_?BkaNJA?PXD zNGH$uRwng<4o9{nk4gW z3E-`-*MB=(J%0*&SA1UclA>pLfP4H?eSsQV$G$t!uXTEio7TY9E35&?0M-ERfX4he z{_Hb&AE`T%j8hIZEp@yBVycpvW2!bHrfxbuu6>_i<^9@?ak)9gHU*#bS~}$sGY*Fi z=%P&i3aH%N`b;I~s8{&6uGo$>-`ukQ<8ri(6aH6p_F`Fhdi6HuacwfQn10HVL7Om1 z4aZpjatkbgjp$L5Mceab#G#C)Hr{^W|TJX~?B3@2buj0;kfuNTf4c3*Au~O^aj=W2$j^4okeCxh#lwexN@eam-u4dNz zN2NIuIM4566{T&^k%4ftShcPk#=im-zXm>QWqH^0>A@?MqlDZCZ@8Wi*@tvhn5p<} zRwFm@gz|WZp91S5Z{}tB^e9|FBg(~Ik+?&_53J6ye_QQOSJ*846~H%s#LD}|O9v9H z1fLrrgoPo_&bs}eqEr}2en3iqAcP^>YsKiez$5-6m6(#3ZZ$@M5Ck=_Vv`QA>1A*v z3w-nJ_;5Nc(0_%`kG91#sotIlhO!*5#|yg+Gx{V;0ty`*=Y9=jCh$l*=fE(~t}%R# zc}iNpO)OZX`P=leQY^?^DF1w%FJh>Dkp}-o5Ig|2!6^E>|W|zc~W7gF;MtxX7 zV~UjQNsUC$EYXpN?~o{83D2c*0~7;Tm~%FRTAnnt3ln{?DcLZ=NsBY|JxwUA-6K3V zP&#|9t#a}Q4{Sg{6v-OmjJBkCh>m)8vLNm4lStMUT$)FZeJG05A)px&o3H)5oAl9= z31@?HyCriHcCDnt628BFN+T;U69Wl#itfvqIDBydMvOJO0Zl?go$cfG5>TK75CMj3 zakLaH3=&J0e}Xmqlav$S0>E@_Yo_V~3SiiXrw)$&!XhrHCDQ%P1BHPusuKr0LthAB zg)mDrLy>2*yevMMOQe6fZ|)%PEb!lC^*9yaX9UMy7-v!fSICssTR|wML0Ic2BhKAq z3I1X~ z7^_!M&;6Z9?br3#HU_&kfJ~%botXQkC1v<}ZZxN5q-T)|Sb2cW3WYUBbDZ`TH{!*^ zrmAeRM+(QI>D+?}guZ+dH*X)@^!O|oL69&Avbtw2^M3HP(+2kV{O$^3BN1RLfrC8nwz7=VhBR%>!;7WR<~;34B_j3A{>^@e@H+Q! zL=UNr1(JvKAQLKT0b}EMn|QUWtY>!>8-t@fVj_&`~gGd{_aPy5W>0u5L$zrsU^rBO=i$`#Xd*>kh)lPf}A znNXSEl`+HlhXtylgS9(#N02A=zVV?#OF?)Gr>(HszVa+1*2VG@qYttJuXaBlzP`Pb zX)ueu?s&}R>xI#^*r4gR?tMFi!_eeKlIM5g)Nk)Y^h=ZCR**xY>$E5knctRrq!zw? zX{2|hwR9LXTY1)pTlKg7U4_ej{dcj2{!+1sZ6<@9^?mn)=37V)DIAvS(}S`IgFO!6 zn({?nYw`Z-@jvt@!q|5z?TI3(dx^1szSn%azAwp>N#fk^kt|=MejKtacAs@Rdku#zT>9$s z=m7ek)`=O7hO2n+2Uj$QUs&2EIqycF{(L9Y#^IyxXA%R@ z&j`VAprIV~d!pH-7~zA+bjwVn3kOB3;rlg{nr&wHV12N}g^i>Upls~=z`VX>9HQ#= zTu&luVb@_Lkz63&&^_M!6(-2^0?GCAX9XKp{O={pd|AlIMGriX6s_Jy8_q9|{5jLc zxd1aj_ucE7Vcti#$r!s~w~W=XpaLQ}#mX`apR7^n9-d3?O+adJYr*L;{c)x@REewM@vZN0njS3iE$88KHPWAkWt((OUMherUnPm?i&8@!9E@ zUW^$%CpdruZR0ohzUq-XQ$KEIB8Sjgs1+wKSUH&Y;=ee%E&O$X18{&979d~K2uJW` zd*8awHCXb;Q>4z$B|sPNv+Zd__f6&@KmS+L`z3H1x+x|Xs7-N-iw|1C=QiJdU)f~z z{vO4hpP`0MyqmwIHN=l?jSq>OKG6CEC#O`*blP`?>)CUWj5j1cB>%6N7;`kfZ1iQV zam~SDB?{uyp^=vF_u|=8xn3S)L;wF8ZRZV{bezM-EH;MC91JQZ{KcZZ$IWJUy?SJGeGUWm6PeuO8-K2|hD~p;Ls~9Y-4lE+?|bF)XaNKUNX(K7 zBQk0Z{n>hrH-CA`bTr$6z0n@Cn9EL$XZ3=X7NopjcI=;z<(X7-oEmK}BId=PxX*!b7Q6oL@ufd%eEPc`_la(}WkT zKe?-YJWn^6b$^{dhdJZ)I!Kn6c}iw%o5mLDyvM7qJZbkGG?zLU;M|W;Wis|A;SuY3{_X53`+>9g^B%O4b{;^t$^;{oKHbo*CY%u91 zp#2d8Pg=I0&UX{qwr=y=o_^BLdk=KYH$=Z8+k|p8V5`ph~3b^{^NnL4m_+4zx( zeoTt@f<$DmsB1}o%R1Hx`ToPuBl+P6cb-?uF{1!z-2WvdR4+vJ*SYTic5@gwnzu%e zD!HF^X=$ha^#1hi*@~^nDL!HQ;MC&e+6=onaJgm-J-+|>PpmU=SIe?EQE5vJiqziw z*K=Z%bWZz_we!qiFqE`I?#$yozNxIE7Ei;csv>++r*?)0bozFpF&oLh94u z-2c2L`5BarP7l>87|f)vxaT*9(!Q`2xBMZ&^JVj-|1)Tg!6OW=lk=w zLwVlr!*<(l*L$a?ox3+%!~UIj3Ej@KD;W>1E_c)1szDi93BC;0K?drOQ>@$yi|DtT zSir}!Yx>znf&b0KS;Lk7VKPDF@e>(qQr0%SNcGQd(p9StjqJ`QSW&c{ggF?5{d22w zlkX%JTUq`;(3WSH+)WHl%qlF)iNG_?}K?ZM3cS7#u5v zZ!apx4Apv=PWsn}eD%MI#=KA)OlNy0)l@~D^1;NC5k@|OPW3wt>WNYDN+8~+gM%E! z$ z`Olr0;eytiK&~O*ps%KV?2vq+DhuRh*!6Ilzu>A;iMe9 zI?zug9nT9CI_o)O}KF_I_U z_Cswu{)3pCYgw{eOt#E?UCqBwkAugSl>5 zX?G=Ci(Lo+r3suuJezyQyDvw*<1b{rx*&ZaY2HlJ>k{Qc%IZeU43pQXw4mh!4I5>l zZ@4$uxaPY#!*IhL4Hctn#!n#S+SiPcZP_PTd5fXf1exhFi5zf3kl`UcW2RUk)F2oF z_ogN`{03PiseQR;fa#{Uy;jeNlJ0Sle`~;ZYhLjkuy>a^!Z_nR~`$&F?NVuIE3HX;i zD82snwlwPb`7yE)ZA_Ndmq5zuSO1{{1}(d9u4#!Fl_|eOuxKBwOfQ*tG`VjCV$-WF zxi0c&+w}Z)rqz{%f46@`ADPdGm#x)+zpT+gyfDi;_P zR{#Ta`Mzd=putKO@5lQJO*aNy(i?}Ltwy^Z;69f|eqi#UCI1$vL!+(#mi?dK`OL$! z3jQnx$_$+Li2<__CL@Wuk4^J7-!n3j2I4N8e#=qpir+iEQcrn3`B4yNOd1BBLEni<(tdRWE>m0I^ zt(^*Td+S3}$5rOzXy=MW>%#MN_qy%5St!>HrGZ~Fq1WKw-&kv@2TrCcPCPzY%2aO- zN?7@+$4?&qA|uv{QHuV)O9haZpG7Jx2f%D)7J@oWTxJ#E_YSq_6qT1tomOD?02(1otT{Hk8{?g(944>h4f% zOJ8tzjecV{x2uWde&6oAP)*({ zFkW0Q%gdI*9@W)oKO65DgP<3F_BIKvRXLAR?Z61&0g2TR6mEZ7OZK?dP7zukdg?s_tNZeuOsh^e1Tmdlz5rIg?LcK|%aQ1FsSDv#W0EnHd z9M)p;gAL_R~Z5cojTdwy+qDsd6R01Vtxmq&FhfPz{wxmB$${zW~z@{Ro_ zK#y5^KqIp!#@or>GD`c+aZ(PV1=`Eo1?a55p6a*WepFgxvmp!^2518YEU-;{F}fLr zD~)=S0m=+px3TUN8-El}Xb}{2ET*_i3-|WlY@V7vr6#&cOr*+oS9?GF?@)K6op>>o z4af0@%KwaLr`{3P&)474<3rDMsd!IM-bepWfhfuMmJt}#0%PgDSx*q(s0m%ZFgWTj zwwvH%2!(i9{RHX~FVUB5qHvF{+ZF}+(bZVPG1)a*Ph>KV;cYNK^aB@R#dS~&`^60V zn2Z24Y{{djzK33}t@q%!v5k)u7jAXB_H{#4Ut2 z1}0j5$RXcTyfazqL9=^Qe%GL`G)=!lirv7AgVRf^=XyEM&kiOe_%JD!O?sXK&hrDo zF}m9B68im!oGshuZluy2H#T$`XPZQu@zf;(nBCZB-cjQ&w*p@Tm_$pe^MTN3EauI) zJG&G^H-4S|1OCd#@A6jO+IcAXG#5M-d9E!^YNmV7Z(=F^?8bfrYf&mLMnRd_22&Q} z2*msbLsrI!XPeOK@|V?n>`kNC`8eSFmekELLr|!-wQRltxZnuRedup<7VflowJ+gC z)F}P6lUSsh^B41?=~0*68YA6z63lKG`W$@{GV!cC2FCl0s<7yz6!3JWoBbUDTgpg% z4VNUk%xblMy7PjLF2We*3XY7K*N(*9Yx!_M zjU$&JXLiNxaTzoa&k@NSbzbLJTn$6bu6SPWYx)Zc1Li~Lqj($GuWsA#;zg85eH{yx zz3IIOea3A4QFGmJCfn7N_d$8a77j+T^W}Sr%0XdVLFf&zJ$s^D5Vrc!iV&GXyb5*A z6mG8d*6EDN7a;=dgVjYI--~4@Fe{{fcJ4B|;_Qg~&%6#?I(?X_$S4rDw{=>=8iZS=M^I#EF!m zXn%K_xXWwmm7R40LKXPo6ZzNZfN1-$S6RuVU=JlC|3#Xjo-%ebJvvC4n%IM)Q8NDh zGXd)L;ay_JMozc^mU*Uifnp=#+if>LD*O9MV#@wB1l``z|tlu(7PJqS6rm)0@ zJzP50{0Vpa`_?92oB;*i(?i225a6tZgT+9Dg?vTh)N4OKA~(c8{$8-ZKz=mb@$4IT9g8>;k11WIT+Y=%Z})`y#OJ zK-~rlEy!T%0h!Qo+jjPF2RQz2Z^B;dbvYg2JS`+@D~OWH{2-EEs^BdnuJskh>CKeT z1b;%8dU6QU%i@z?^6Q-{XESe^qRiw`ka+k!d-{c%&lXM}vCX^T=|?|;t6r?N*h-W4 z?o4Hy%BWqW+5=+md#5^8|49zjM zon_Do@rhzZ4XAb}-m|bMH$Vg<;^Bo6A8cfhUQ>|wFk~j(`>1NgD3sTg)He1pWrUj9WZ8R(Wn5Rr zhc&dXvv_m%HrwwHo9l_))NgdVUff%d&@4^$Pc=MDZdZ^xHL$KX^ z7W1{3UJ%>9v$W{Y3>vBvflE-soDj8{`>#F|8Z$EF%lN$NylORTn5JsI4mTMHWd*%- z2sD(RO(H-&i8&Ge)5i12slI5VekYCZ)s8rv&_)194;vKY2m8DIC2{4<&xTM3HHxwT zd(42n)gCJ$O4I|8sJq07#0U7Yk7PjPK&bMdy-5b)OdhSsBo^|IB_H43@&F@tpdJR0 z#~)=UJdP|=)O{0(rVZnjbTtwHV^}&kfLJQP@R6rda;K;O>9J9bnW$BgbzOZ8aO{D8 zPuJ%=Nqg~rdzk-IW0ZC5I%cc;ek5~=lDXl4?gMOQQ!KE5Aq$9qeGFM6jFP;Xy6)%N zjg{q(E6fnF02P3L*tutbHRR-gyYK3g^y9H?GMtIs;ojG zY~3*C>qD)(8jz}89w|xfb7L`^d>AG#%D-uq=qz}(o9kzzrx0LSBX90ykr*5oM+YmoTRWe+Cj6aq^xnWRymLmE>krCpoC9K%2LT0aK0Y< zt@kUUrrj1WL9rmBB8B;WXqg-BztOiUZX-!`*a&-75+!WZ!R0OPiZz?w`Of4q#+(;m z`${Ea6GnTCY3`V2R8w*}knf)*`RA@(8k{Lp4VP;<+ z9O_z0_{3=HcVi z5)&QGEB_&$)mu@)(Z8zuw#>Gc6C>^O-FUZEo;TO1@$>-xu%`v`tMS3V-8R1pb5w&zP%&rAP2*5h z$k{jqReFXCJhJ?-{x(2j5gH_zQ>;#Ec*@bUqF0u}XB09+U-K}+jQd>)k#AOkr6M8x zHyhrfJ`99@Vzr_B@*p@`DxeJ#`jimavZ9ZV%v{mO0!%9$TY(f%_}BU~3R%QxmSdD1 z2Bp45R0C=8qtx-~+oULrzCMHMof!&H<~~>BhOu9t%ti7ERzy&MfeFI`yIK^$C)AW3 zNQRoy0G}{Z0U#b~iYF^Jc^xOlG#4#C=;O>}m0(@{S^B2chkhuBA^ur)c`E;iGC9@z z7%fqif|WXh26-3;GTi8YpXUOSVWuR&C%jb}s5V4o;X~?V>XaR)8gBIQvmh3-xs)|E z8CExUnh>Ngjb^6YLgG<K?>j`V4Zp4G4%h8vUG^ouv)P!AnMkAWurg1zX2{E)hFp5ex ziBTDWLl+>ihx>1Um{+p<{v-zS?fx&Ioeu#9;aON_P4|J-J)gPF2-0?yt=+nHsn^1G z2bM#YbR1hHRbR9Or49U3T&x=1c0%dKX4HI!55MQv`3gt5ENVMAhhgEp@kG2k+qT|<5K~u`9G7x z?eB%b2B#mq)&K}m$lwDv|MU~=Y(D2jO{j*Box$GUn=$90z6O^7F?7pn=P;{r4C8qa zv1n*5N7uIvTn`8$>}(74>Oqk=E7){#pHUFd5XRJ5ObMhqODTa}=V0;+a(7JZR-4<3 zBTvsqRwLh?*ZF)JWsWOkEq7*XMQ!G3Rmkdh7ZbM#v1~?jt((e2y}u}Ky>1qa&Y7m@ zveIzH@?5Gexr79*?sbZGkVS;s1U<7D(%~7HjAmzj$aDYv_FGl5JX@LW8>w=HCDl6W z%?rsr0)bErYJ5G1v&zjr{8=lW)ZYcstgZAuL}!0~8HAcgOm@nJ9cvOOtL@)Fpl2Dr z8876Lt<|1eF88Jx#C*XyGI)C5z_o!Os!t=Xy0$Kj^4fG1pb@16%g z+<)zJ1n1QO78g#$3yHj+(Smv`HW5y_-PP{h2A1UXMG-c%hMvHLbF6t}G>KA)H# z`AWL~>8JUT(iq7;zJr!Aj)AS+n{mRbA3aM+Gj}b#PhHdTM_NkwQm330EC9waM$=slPfxR1vmr!vf~t_M?a%`@`&tdE}ipY-p#Q#zhLK zd9eFC;PjIEAKLkRkO94{rTuNFqKbNUGtaNZRRbax9;|%2WbnGu!44#64RriY5u0O} z05G^e&JB?Wb*8^g)aM`yt|}~QJkKCipFNeyex~P~SFPVEafD(73rncKmm)m~&`O*YUyY9z7tO%ec7z@wWcoOr-ebP z1k+|y?d{>1jLC=s4B2tEhiTtu->WVJno&%%6bG46KuU9D`GEN!C!9chM>zd=cl0+- z^k>4rpkq7_iWGHtBvy$Q`dja2;1ZdYmF6cANU6{v>l1=fSKRpsTRonp@alC%p{bhU z>g+(%-)&_nDQ~#bq5;xo^06RggA&uH4RMVb6wt;oQI+`m_zt>SiI5hXkfEnn6@ZNk zh9KUr1jtt6lBg$O#TAoTRvwUtWeMP3EjnGoRPQppiNF(sX%|Q4@kIjas|WZWXSENO zfF#2yOb;%XO*LeOoAwlf{u7_39$x(w3xT~)2BNJ2l5u4n3a0NkNLT4yT);7fA?1Vt zCz*`hbw-doYa09E!05zcfOT0EOORY``E@D z5{v%@F~&|UfNt@>vrj66W5f>jy+G_8&VB9D0*>N!7_Nr=-x6N?A)M8>1~q(X34sXp zpA%@w&c};L7u*G3;(Qe=LFL}NbTF$|aX#A%P(h`-N=ZRxCvlG$>Klv}jo0MS|UR8qKq-1FokBJmrbTJjQ!k#Is0tY+0c)m4Gp80YzYD zEGXd~ihaihk;?xUknXNH?rssjzaF+l6?HnDQjVP$i=q}{lp_WbOTKKg}HPKW)2sW`L#NvgmaY0^b2Ldk|t{P6{L{>ym;Xgao1PrudBgEMRFb^ zkPJ6v0h^tJ>K@;maHk_|6Z>yFzq@YvDOeO6Ob_?P4Ey>kHiJv`Wlh_MX4fBY36f%^ zV#2t;$Rg&}!Kwifm z;TVZXMxw3~$--{&A8-6vnUZ#s4`Z-zQ#+y7UI8#Hgsc|ompLUc zqlAG!Ti>t{JzYF^5pM925*PUWUvDuYDGKhC4FMx45c`L#V7%V+88@|khLj|V=J9Un zJEcP5qVCzR6p{FK!nIY~TXo)tJ!{>CG;~&u;EPlnNrwJ=5)ke@hJosN!siM$8b2mM zmc&weo-rY{n1+%c`c<{AT3i zjF{p253Ul-)s5A+!8Dp7?viXAdH1+qlY%mK5pp?{pS1t!3qmmDOq2TnoV`F3<>(XK z1=gfH39N_~8O+~({MZX~+QHyB>vtgwK0@uqGkX^eaf$UFHiO#>LB*7@=c0o6`0muj zmH00_F#p)s3E*$A-zP+p2bvXARTg3)Lxh`tf~9X>7!Z^kHV`uE%V9+BiBG=mxj*)M zr%3rn=)>GR`{#zmwD)$3ToLMx++uqsCx(+50Uk*5QJp2c6msxLD&P-y{c|XK6zZl3 z_Fgu8kp|gKVWv`GS!c56FWPO)ZrCCtYh#*yp-ssus)ot>_~UB zyGfjTjz#fXod{^KEQK1~@jN|;SZw5OgH#0wK78Oe4#vV3*|&XPQU z$r~5u8ziT0<#ICrX^<1){mvtaqT9OqlW?wiSu4X#rOC(0uL{Ownb%i1F_G&d>=l51 zx!FEO4_LK+)W^N6UF+fAccyyp{t)TE`;vF@1irbNjcXF8b?yFh zl5UEB>@;wO`~gMF!QB;h<``+f(lxAb_8B$;&vT7)(bXG(7x_5f%AZ5;h#3WjHisX{ zLTSguapAADXMwWZ&jsD0+K!+8#*6z7-(T+QUk>(~!Q|0&!d)PgEw8F6RK;LkB;!HXg79$+l*KU&-fRF|$o+kR4mJ36k9p&>*uS~RhCV+*Y$3U-k%~M)jxCFW zl9;bQ-fx4HPy)*(bhrKL!81M6*@6p5W?z*W`jb;@JKMFwmic{gQPv*) z?I{Fh)y)}(-6uh^I52xKo!LRZV0c*1X)Z(g+GVFN{2n%vD*@&IkVI{R_0;M28M z8vu?M+xVF-&<{l@1g{PA#hnyAq(gudz4WKSFL5YOr3q!|qrxa7z~F~rEJ29VQKgNe z1*L^m9&acg2p7&`u&V%oY|AKF(Xpv=)wf&j#n|;2UYEaUIHLJuTQw$SbrNn+)38PlfV^0<6s>)|hT#IAAS*T)_^_q@I} z0S%tV-HrXOjzkvW!YSbDjdH=g;=4A@whsDB zI8^aX6n=|ab(?!Ay!)CxH(wC(iX~Q@%FEx>C{Hmp98f2ku$Bsw%lk6v50(U@; zu68Z9U&za}O#-Mv^+!V=eyj6S)5oS{My`1MVs)nlnYl_$xU^QId1_jMf7&K8ij)jQ zJ|+~@l)xpV%~Y{P()$`+nBihkjE|3t3t8PoKU3wZ_Eg%0P<>%(A@oW#*8i$X!nfG& z;&&2ZIKlD~*Gff+p3A7QB!}Ei>RGhUUz^UoEpeJ{`2ov>wH!O@1$VW>A#D#{i2z9l z{d)FK9OYxRY#(6NUMO=q^5Ve7R|72%f}ZDlsm0BN&LzyaSHurXV4p5HGf7|Z)}8)g z5J#S6h{-+_U0m$k#+|N{6_8MYactWzWb+1~ea8wX3zX<@O0>pU*q($J{=R&7)P&jg z6Kb)o=HAnC_MP;cIeBq}{gG^0CZzOUJZ|7C-VjE}!?*UtKTcwwF33v^BYC&}Rq)C* zpAJ07-!{`flYX1@n;ZK-=x4)!o(%(1UqulVmes(D z^`_HNfM#umEYy~=zh$9&+?8$4!l(4rr?d#8hS4iks@9w%E4l`BKmhUtvsm1X-mKC3 z>4(u4yS45OgZIOQ;EQ6s`sjNelo!~mLe7gS69TW2WnFwEKcAwioq2mLXV<9CIa#(0`sQpl>vwW`A$D?!2%nt*HEb;Ga=o?92 zHAOICmXHEQ%Cc{m2>dLjPU1J}^w7zilFIxy9nG(OZbYPtW?3KJyv@A7|1A*NiD_v! zTLC}%E4kI*d?$lQBRL==MPsD#FyN0ZSr`;aeQ4C6a2INH9klU~_gCH;G2%8R4EuHb z44Ej^6301>?c06FP3X~xyP{77p`-3td;HKAGf4mZw1qRd6Z^^L#?qaiAKv~px)*jAV^re~beps9m{kJzb6n(oS8uCt#Lnjofg;Rl z=apY)JsV;^dVkzCW)jDrii_WTT`3iKri(xmCC1^AO}Vqt-1B*wwIlBAmE1AmdRtMc zD!fB@mtwHPHyV-^VIVU??*~*{olz-Ub)NCX941BDj_CKZ+QYQ?+``tyhy_7WFXF}_ z?~CVO#LsDYD!&}cph22{PZ*TK?$K^u`E7%{^na89Rm%!jSZs7vI-D zL1POD!1cu56G)*p1gui3-i^JZPX3tI*_Fq&JRwbz*#8LUSiMRWjuu`zD|uk;+X&d@ zuxF5C2{Zp#O?GtOB+R2~tF>MDI(}%p-W=M>1tEY}8E=b_l*WbOO zY9tCPgL3vMEqz)_eWeqmN{qobq_4)XdXJSe6Hj;Eie0??2ZZ?p;*_K8@(&v~1evu- zxQCA2YYvv@qhzamqdi`?{Z{c*7$arCdz4-4G(`O5It%y&8>d{#Y9Vax^FZ99ZK zUdIPpkNhp8uP3T+W4lhvUIYaoY##y6KtxBFoj3&5^@Q(^{677%C#3YJh$p-Ee2M6F ztJAoQv1N0L!|N8XBD(eAYcB#gRaIX7T8U5xXbx~cJSon~YnC zaJYE%zOj9y?E==_B$*9NiAm{~)2Z}t1$$l?qOYct5Ep5HvqFKvuSE7A5YF$K@2>UE zbQOdTNzjD#zS(L>wa2$K-WK!Pc%pY^8To58;^JaXZ}F30wuYl;WWs~rCoo&vrEtUh zTBLMU??yx1#;-weCPZyOJ%Yeb?14z+OXW0L_E+<)(q=;xz74U-Q~R~n*oC;MxyrJo(74r$y2t;x`D~{nhUw`N{Bbc zo`l5kb`Yy;L=&@MTQ~Ml_%V%){mCIj4WC}5q=A_ACx2^by!4w1rVX6H0ifayJsw;; z=+}5kjC?RG*q)^FA;udd?fK$7vU1x>y0w;A-)YbE%l$J%nRRjAIlrItFPgQvJ7Ytb z%HSFnjF2||X&L_g-Q>1{(mholW_-EJmSzsO%*VVVB4)#OAv<(kOIx2H!f)I9#e_Nyjdb$&*1KN^gM}yFIhi%%BWB}7Ke0M{0WY>CxJQUuL<9GW$I>S z8~;QmE{^wS?I`=DyV^l+MozMPWLoFz=uSLu99tiVHdCN>7jRs~vd13`&Gey!!7_+< z6o@25%!eN~+Eki#7iq@#{Hxl7pF0^`N;~p~#tc6HXJP0g5xvK|AuLSwNHVI2_Y-!& z4hemc%vOM5!ySDypyEGe=lAeFbIp`w8FIUcTqUwens>sTIV-jDhrcKGX7XHFXyazb z^DO8=ZgefY6R6&+)c1_i*WoenjtR5@_JU#Ph;4M8fpmznxE9R`=r@-#_y zkD?Muq|*gg7f*BQeI|Np#}Q|NXLJHM6GE{;SJn8ce`V1Gehym~{8c+M<2~=HcCRuk z-v&$8dc8YG+tK}NYVhwdm1iZ&A#r+T<>Ez88)Eq9j+G5h5D(_u{WQdUTOs+QbA(=? z{F6n6UV8D2*lvb)0vDrca$729KG$xO2aH$jWoWl0drlmefYsTswh)`GjMtmR=vEkJ zN$aTp_@@KL%KQ-VDB2ppbZK@X`6cJA5n`g>sbCTvU_xdid!{9gWA|>Mfs6rtHx6s` z_wMt*FgUTBZ@I2C62&zbs?pPvK9TpatkXzqDqe4YTr^nnQg8gWxjKt*s&eOMEp!Qc zG~PT`>xg76Xqh^dKI-Eu#K*VnvEf9qT{L0yNpVj)eVD#kQzGgVRbTB!5nWY=?t!cggiEGBAcWM2xNtW&9 zZB_6RZ}|a87CuEYRYCRJ`Sg+_gBK$_J@*zoWcJJw>eBw?G9WY(Jw~qN|A3MBR^~jm?>k5oGv7z+0jWOox(co@%nya|* zE-2peyX)#@svgwwDMPJ89dT=iO>}@wtNR@NUQ|cJZ};sX(w2uWP4AE5)@A ziJgy_TIZ+T&vG&xPh@Jmt!OJ|zA6C0ZxfF2 z7>aIZqecbmM$lyvDMwg2?Ipo9b)-WL6K_7(X_rmJgdd$-Qc^ywEw4SThChz6*_yu= z{v~a4V|RJtH-GThc2C0Z|JHPl{II-!?B~7cWnRz&dgP*UqoY!iCo&i-xeM}kl?ID* zKTX`w+;z0+MCdGcl{N?xb|tYb%Id=k++k_@(V%bTS&n09`0{S0)|>IH_F;V@_zrxS-dKDDc7+i`nHN8J z;38w69lzAS*WWa+dnVvk(0-KD3%*)TerLH zSCc}Tjc-mR5|1HAL$C1}oue|Qp&M!hmyDUcg)Cz>GXPEyeYf}+s48kIl*pL{{treP BIP(Ai literal 0 HcmV?d00001 diff --git a/backend/android/app/src/main/res/values/colors.xml b/backend/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..65f3b84 --- /dev/null +++ b/backend/android/app/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + #FFFFFF + #023c69 + \ No newline at end of file diff --git a/backend/android/app/src/main/res/values/strings.xml b/backend/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..67a915e --- /dev/null +++ b/backend/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + save-api + \ No newline at end of file diff --git a/backend/android/app/src/main/res/values/styles.xml b/backend/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..b42877d --- /dev/null +++ b/backend/android/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/backend/android/build.gradle b/backend/android/build.gradle new file mode 100644 index 0000000..0554dd1 --- /dev/null +++ b/backend/android/build.gradle @@ -0,0 +1,24 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath('com.android.tools.build:gradle') + classpath('com.facebook.react:react-native-gradle-plugin') + classpath('org.jetbrains.kotlin:kotlin-gradle-plugin') + } +} + +allprojects { + repositories { + google() + mavenCentral() + maven { url 'https://www.jitpack.io' } + } +} + +apply plugin: "expo-root-project" +apply plugin: "com.facebook.react.rootproject" diff --git a/backend/android/gradle.properties b/backend/android/gradle.properties new file mode 100644 index 0000000..a16c21f --- /dev/null +++ b/backend/android/gradle.properties @@ -0,0 +1,63 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true + +# Enable AAPT2 PNG crunching +android.enablePngCrunchInReleaseBuilds=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=true + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true + +# Use this property to enable edge-to-edge display support. +# This allows your app to draw behind system bars for an immersive UI. +# Note: Only works with ReactActivity and should not be used with custom Activity. +edgeToEdgeEnabled=true + +# Enable GIF support in React Native images (~200 B increase) +expo.gif.enabled=true +# Enable webp support in React Native images (~85 KB increase) +expo.webp.enabled=true +# Enable animated webp support (~3.4 MB increase) +# Disabled by default because iOS doesn't support animated webp +expo.webp.animated=false + +# Enable network inspector +EX_DEV_CLIENT_NETWORK_INSPECTOR=true + +# Use legacy packaging to compress native libraries in the resulting APK. +expo.useLegacyPackaging=false + +expo.inlineModules.watchedDirectories=[] \ No newline at end of file diff --git a/backend/android/gradle/wrapper/gradle-wrapper.jar b/backend/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..61285a659d17295f1de7c53e24fdf13ad755c379 GIT binary patch literal 46175 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

pVX@HRij*jw$g4?}Pn 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 literal 0 HcmV?d00001 diff --git a/backend/android/gradle/wrapper/gradle-wrapper.properties b/backend/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..37f78a6 --- /dev/null +++ b/backend/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/backend/android/gradlew b/backend/android/gradlew new file mode 100755 index 0000000..adff685 --- /dev/null +++ b/backend/android/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/backend/android/gradlew.bat b/backend/android/gradlew.bat new file mode 100644 index 0000000..39baf4d --- /dev/null +++ b/backend/android/gradlew.bat @@ -0,0 +1,98 @@ +@REM Copyright (c) Meta Platforms, Inc. and affiliates. +@REM +@REM This source code is licensed under the MIT license found in the +@REM LICENSE file in the root directory of this source tree. + +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/backend/android/settings.gradle b/backend/android/settings.gradle new file mode 100644 index 0000000..f6c84c4 --- /dev/null +++ b/backend/android/settings.gradle @@ -0,0 +1,39 @@ +pluginManagement { + def reactNativeGradlePlugin = new File( + providers.exec { + workingDir(rootDir) + commandLine("node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })") + }.standardOutput.asText.get().trim() + ).getParentFile().absolutePath + includeBuild(reactNativeGradlePlugin) + + def expoPluginsPath = new File( + providers.exec { + workingDir(rootDir) + commandLine("node", "--print", "require.resolve('expo-modules-autolinking/package.json', { paths: [require.resolve('expo/package.json')] })") + }.standardOutput.asText.get().trim(), + "../android/expo-gradle-plugin" + ).absolutePath + includeBuild(expoPluginsPath) +} + +plugins { + id("com.facebook.react.settings") + id("expo-autolinking-settings") +} + +extensions.configure(com.facebook.react.ReactSettingsExtension) { ex -> + if (System.getenv('EXPO_USE_COMMUNITY_AUTOLINKING') == '1') { + ex.autolinkLibrariesFromCommand() + } else { + ex.autolinkLibrariesFromCommand(expoAutolinking.rnConfigCommand) + } +} +expoAutolinking.useExpoModules() + +rootProject.name = 'save-api' + +expoAutolinking.useExpoVersionCatalog() + +include ':app' +includeBuild(expoAutolinking.reactNativeGradlePlugin) diff --git a/backend/app.json b/backend/app.json new file mode 100644 index 0000000..f0bf5f4 --- /dev/null +++ b/backend/app.json @@ -0,0 +1,5 @@ +{ + "android": { + "package": "com.pjpbrionfwdpeers.saveapi" + } +} diff --git a/backend/package-lock.json b/backend/package-lock.json index 6c3e59a..027f6c7 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -18,7 +18,10 @@ "bullmq": "^5.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", + "expo": "~57.0.18", "mongoose": "^8.8.0", + "react": "19.2.3", + "react-native": "0.86.3", "redis": "^5.0.0", "reflect-metadata": "^0.2.1", "rxjs": "^7.0.0", @@ -158,7 +161,6 @@ "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", @@ -169,2620 +171,5978 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-identifier": { + "node_modules/@babel/compat-data": { "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", - "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", - "dev": true, + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@borewit/text-codec": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", - "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", - "license": "MIT", + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "node_modules/@exodus/bytes": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", - "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@noble/hashes": "^1.8.0 || ^2.0.0" - }, - "peerDependenciesMeta": { - "@noble/hashes": { - "optional": true - } + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@inquirer/ansi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", - "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", - "dev": true, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@inquirer/checkbox": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", - "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", - "dev": true, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", - "dev": true, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", + "semver": "^6.3.1" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@babel/core": "^7.0.0" } }, - "node_modules/@inquirer/core": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", - "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", - "dev": true, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" + "@babel/helper-annotate-as-pure": "^7.29.7", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@babel/core": "^7.0.0" } }, - "node_modules/@inquirer/editor": { - "version": "4.2.23", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", - "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", - "dev": true, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/external-editor": "^1.0.3", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.11" }, "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@inquirer/expand": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", - "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", - "dev": true, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", - "dev": true, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "license": "MIT", "dependencies": { - "chardet": "^2.1.1", - "iconv-lite": "^0.7.0" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/node": ">=18" + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "dev": true, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "license": "MIT", "engines": { - "node": ">=18" + "node": ">=6.9.0" } }, - "node_modules/@inquirer/input": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", - "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", - "dev": true, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@babel/core": "^7.0.0" } }, - "node_modules/@inquirer/number": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", - "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", - "dev": true, + "node_modules/@babel/helper-replace-supers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@babel/core": "^7.0.0" } }, - "node_modules/@inquirer/password": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", - "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", - "dev": true, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", - "dev": true, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@inquirer/rawlist": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", - "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", - "dev": true, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" }, - "peerDependencies": { - "@types/node": ">=18" + "bin": { + "parser": "bin/babel-parser.js" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@inquirer/search": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", - "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", - "dev": true, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.7.tgz", + "integrity": "sha512-EtU0Hi3GvrTqD56xKmZvV/uCXK2ZbwVNPNLAquVItcAZpUhkXwWlo3Fmj0c2LxgSf2I8IDULeAepwNP1OefLXg==", "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-decorators": "^7.29.7" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@inquirer/select": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", - "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", - "dev": true, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.29.7.tgz", + "integrity": "sha512-p+G5BNXDcy3bOXplhY4HybQ1GxH3i2Tppmdm/3epyRu2VgJJZuUlZ61MqRTg582Q7ZLBdP7fePYvsumSEkMxcQ==", "license": "MIT", "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@inquirer/type": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", - "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", - "dev": true, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.29.7.tgz", + "integrity": "sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@ioredis/commands": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz", - "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==", - "license": "MIT" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.29.7.tgz", + "integrity": "sha512-foag0BB37ROhdeIX9O8G0jX7hw0UekJc04cHMrYLOnrErsnBKqJGHJ8eDRpoCFZBvEPPygmmtw4qyU97qa4oOw==", "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.29.7.tgz", + "integrity": "sha512-ajMX6QPcyomotqwpzhkYGxcK2i/us0rs1Qo9QvUpa+Fca0FTmqrzKrctoIYLMxcOhGZldGT/BAVkRGTWBiR8gQ==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@lukeed/csprng": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", - "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@microsoft/tsdoc": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz", - "integrity": "sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==", - "license": "MIT" - }, - "node_modules/@mongodb-js/saslprep": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.13.tgz", - "integrity": "sha512-E3Sv4eCYAlKYUTx8S3ioQcDUscOif+8zZ5OnW1IzJ+Tt+EO+ke8mn+Y3FX6N1H79picwbdOavVOb1jPi2EOyrg==", + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "license": "MIT", "dependencies": { - "sparse-bitfield": "^3.0.3" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz", - "integrity": "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz", - "integrity": "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz", - "integrity": "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz", - "integrity": "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz", - "integrity": "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz", - "integrity": "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@nestjs/cli": { - "version": "11.0.24", - "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-11.0.24.tgz", - "integrity": "sha512-aIHxQLSYtXShifA3zwWIeznEsZnNa3Iz2QRykFj+sl9IcbERBHr5nH87FRgywM+He3NxoF5WazHfR8FsmVeWxw==", - "dev": true, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.2.27", - "@angular-devkit/schematics": "19.2.27", - "@angular-devkit/schematics-cli": "19.2.27", - "@inquirer/prompts": "7.10.1", - "@nestjs/schematics": "^11.0.1", - "ansis": "4.2.0", - "chokidar": "4.0.3", - "cli-table3": "0.6.5", - "commander": "4.1.1", - "fork-ts-checker-webpack-plugin": "9.1.0", - "glob": "13.0.6", - "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.106.2", - "webpack-node-externals": "3.0.0" - }, - "bin": { - "nest": "bin/nest.js" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": ">= 20.11" + "node": ">=6.9.0" }, "peerDependencies": { - "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 || ^0.8.0", - "@swc/core": "^1.3.62" - }, - "peerDependenciesMeta": { - "@swc/cli": { - "optional": true - }, - "@swc/core": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/common": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.2.1.tgz", - "integrity": "sha512-SEgtP+M9DqNhQkgJIlJ3oTp3gemo/8owySovzMGmJj2kcfIH1G6QP45AAb8dE4a3IpVicpUvdDAy7Syk7ebjBw==", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "license": "MIT", "dependencies": { - "file-type": "21.3.4", - "iterare": "1.2.1", - "load-esm": "1.0.3", - "tslib": "2.8.1", - "uid": "2.0.2" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "class-transformer": ">=0.4.1", - "class-validator": ">=0.13.2", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/config": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-4.0.4.tgz", - "integrity": "sha512-CJPjNitr0bAufSEnRe2N+JbnVmMmDoo6hvKCPzXgZoGwJSmp/dZPk9f/RMbuD/+Q1ZJPjwsRpq0vxna++Knwow==", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "license": "MIT", "dependencies": { - "dotenv": "17.4.1", - "dotenv-expand": "12.0.3", - "lodash": "4.18.1" + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@nestjs/common": "^10.0.0 || ^11.0.0", - "rxjs": "^7.1.0" + "@babel/core": "^7.12.0" } }, - "node_modules/@nestjs/core": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.2.1.tgz", - "integrity": "sha512-M5PWFU8NdRTgX9Po49d7TQKg7f5t8GAVUa/Esy4tmaMWcKugTzg3ZzpJfD3LEPMuRHjfs6+8pQYgtuP2uz3rDw==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "license": "MIT", "dependencies": { - "fast-safe-stringify": "2.1.1", - "iterare": "1.2.1", - "path-to-regexp": "8.4.2", - "tslib": "2.8.1", - "uid": "2.0.2" + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" }, "engines": { - "node": ">= 20" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "node": ">=6.9.0" }, "peerDependencies": { - "@nestjs/common": "^11.0.0", - "@nestjs/microservices": "^11.0.0", - "@nestjs/platform-express": "^11.0.0", - "@nestjs/websockets": "^11.0.0", - "reflect-metadata": "^0.1.12 || ^0.2.0", - "rxjs": "^7.1.0" - }, - "peerDependenciesMeta": { - "@nestjs/microservices": { - "optional": true - }, - "@nestjs/platform-express": { - "optional": true - }, - "@nestjs/websockets": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/mapped-types": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.1.1.tgz", - "integrity": "sha512-SCCoMEJ6jdeI5h/N+KCVF1+pmg/hmEkNA5nHTS8Gvww7T/LCl4o1gFLinw2iQ60w7slFkszHcGLKGdazVI4F8A==", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "license": "MIT", - "peerDependencies": { - "@nestjs/common": "^10.0.0 || ^11.0.0", - "class-transformer": "^0.4.0 || ^0.5.0", - "class-validator": "^0.13.0 || ^0.14.0 || ^0.15.0", - "reflect-metadata": "^0.1.12 || ^0.2.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" }, - "peerDependenciesMeta": { - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/mongoose": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/@nestjs/mongoose/-/mongoose-11.0.4.tgz", - "integrity": "sha512-LUOlUeSOfbjdIu22QwOmczv2CzJQr9LUBo2mOfbXrGCu2svpr5Hiu71zBFrb/9UC+H8BjGMKbBOq1nEbMF6ZJA==", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { - "@nestjs/common": "^10.0.0 || ^11.0.0", - "@nestjs/core": "^10.0.0 || ^11.0.0", - "mongoose": "^7.0.0 || ^8.0.0 || ^9.0.0", - "rxjs": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/platform-express": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.2.1.tgz", - "integrity": "sha512-lbaVW94s1u8AJfgmBtdMPi16MEuFBiLrnflUIA9tZ9e5eoUsGTN7XXXRjU5kTTLgjnTCM53qgBXXGmTqmyfoQA==", + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.29.7.tgz", + "integrity": "sha512-wRHeUjUjCZnMHmiO5bRgjFLcoEh7JyTdByOW11ahhwNa4V0bmeGEaIvt51yq0zQp2yWIpqfxXXPyUP6GFJZHOQ==", "license": "MIT", "dependencies": { - "cors": "2.8.6", - "express": "5.2.1", - "multer": "2.2.0", - "path-to-regexp": "8.4.2", - "tslib": "2.8.1" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-flow": "^7.29.7" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nest" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@nestjs/common": "^11.0.0", - "@nestjs/core": "^11.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/schematics": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-11.1.0.tgz", - "integrity": "sha512-lVxGZ46tcdItFMoXr6vyKWlnOsm1SZm/GUqAEDvy2RL4Q4O+3bkziAhrO7Y8JLssFUUvNFEGqAizI52WAxhjDw==", - "dev": true, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.2.24", - "@angular-devkit/schematics": "19.2.24", - "comment-json": "5.0.0", - "jsonc-parser": "3.3.1", - "pluralize": "8.0.0" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, - "peerDependencies": { - "prettier": "^3.0.0", - "typescript": ">=4.8.2" + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "prettier": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { - "version": "19.2.24", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.24.tgz", - "integrity": "sha512-Kd49warf6U/EyWe5BszF/eebN3zQ3bk7tgfEljAw8q/rX95UUtriJubWvp6pgzHfzBA4jwq8f+QiNZB8eBEXPA==", - "dev": true, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "license": "MIT", "dependencies": { - "ajv": "8.18.0", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.4", - "rxjs": "7.8.1", - "source-map": "0.7.4" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">=6.9.0" }, "peerDependencies": { - "chokidar": "^4.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { - "version": "19.2.24", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.24.tgz", - "integrity": "sha512-lnw+ZM1Io+cJAkReC0NPDjqObL8NtKzKIkdgEEKC8CUmkhurYhedbicN8Y8NYHgG1uLd2GozW3+/QqPRZaN+Lw==", - "dev": true, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "license": "MIT", "dependencies": { - "@angular-devkit/core": "19.2.24", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.17", - "ora": "5.4.1", - "rxjs": "7.8.1" + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@nestjs/schematics/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nestjs/swagger": { - "version": "11.4.7", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.4.7.tgz", - "integrity": "sha512-QyDYnmfP4IRucgmtQxMqzgRBdWtjFoDp8eFvvgf92+3wdLCL+Q0xOFO1948j/ntW/Wi7qT2dyck6ka8ADzPWQQ==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "0.16.0", - "@nestjs/mapped-types": "2.1.1", - "js-yaml": "5.3.0", - "lodash": "4.18.1", - "path-to-regexp": "8.4.2", - "swagger-ui-dist": "5.32.13" + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" }, - "peerDependencies": { - "@fastify/static": "^8.0.0 || ^9.0.0 || ^10.0.0", - "@nestjs/common": "^11.0.1", - "@nestjs/core": "^11.0.1", - "class-transformer": "*", - "class-validator": "*", - "reflect-metadata": "^0.1.12 || ^0.2.0" + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "@fastify/static": { - "optional": true - }, - "class-transformer": { - "optional": true - }, - "class-validator": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@noble/ed25519": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-3.2.0.tgz", - "integrity": "sha512-criDgRlnUA09hchYrTy/JUWPIEap5rZxQe6wDWzRx51oWWpDRcUpuNzlgPxDJaOK6AsW9c0wKcj3rKRv6t+bPQ==", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@noble/hashes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz", - "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, "engines": { - "node": ">= 20.19.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@redis/bloom": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.12.1.tgz", - "integrity": "sha512-PUUfv+ms7jgPSBVoo/DN4AkPHj4D5TZSd6SbJX7egzBplkYUcKmHRE8RKia7UtZ8bSQbLguLvxVO+asKtQfZWA==", + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 18.19.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@redis/client": "^5.12.1" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@redis/client": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-5.12.1.tgz", - "integrity": "sha512-7aPGWeqA3uFm43o19umzdl16CEjK/JQGtSXVPevplTaOU3VJA/rseBC1QvYUz9lLDIMBimc4SW/zrW4S89BaCA==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "license": "MIT", "dependencies": { - "cluster-key-slot": "1.1.2" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { - "node": ">= 18.19.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@node-rs/xxhash": "^1.1.0", - "@opentelemetry/api": ">=1 <2" - }, - "peerDependenciesMeta": { - "@node-rs/xxhash": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@redis/client/node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "license": "Apache-2.0", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@redis/json": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-5.12.1.tgz", - "integrity": "sha512-eOze75esLve4vfqDel7aMX08CNaiLLQS2fV8mpRN9NxPe1rVR4vQyYiW/OgtGUysF6QOr9ANhfxABKNOJfXdKg==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 18.19.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@redis/client": "^5.12.1" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@redis/search": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-5.12.1.tgz", - "integrity": "sha512-ItlxbxC9cKI6IU1TLWoczwJCRb6TdmkEpWv05UrPawqaAnWGRu3rcIqsc5vN483T2fSociuyV1UkWIL5I4//2w==", + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 18.19.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@redis/client": "^5.12.1" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@redis/time-series": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.12.1.tgz", - "integrity": "sha512-c6JL6E3EcZJuNqKFz+KM+l9l5mpcQiKvTwgA3blt5glWJ8hjDk0yeHN3beE/MpqYIQ8UEX44ItQzgkE/gCBELQ==", + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.29.7.tgz", + "integrity": "sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==", "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">= 18.19.0" + "node": ">=6.9.0" }, "peerDependencies": { - "@redis/client": "^5.12.1" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@scarf/scarf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", - "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", - "hasInstallScript": true, - "license": "Apache-2.0" - }, - "node_modules/@stellar/js-xdr": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-5.0.0.tgz", - "integrity": "sha512-HBDNKnxr+ecdaEmbZ0mcKkirOF8tXXEbWSw34P3wT40Tn3g+u+cCH17xAWZymzscq8cojHB8340pR8QNVaD32w==", - "license": "Apache-2.0", + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.29.7.tgz", + "integrity": "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/types": "^7.29.7" + }, "engines": { - "node": ">=22.0.0", - "pnpm": ">=10.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@stellar/stellar-sdk": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-17.0.1.tgz", - "integrity": "sha512-fsHHbzJ14N5Ttq5Qpz4AX0ytmPSLCzcy4XC3uIgSQz0cBkEgv0Zb4KE6tWEd3nDQUk/1qP8ZX9cRonIaUXO3Sw==", - "license": "Apache-2.0", + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.29.7.tgz", + "integrity": "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==", + "license": "MIT", "dependencies": { - "@exodus/bytes": "^1.15.1", - "@noble/ed25519": "^3.1.0", - "@noble/hashes": "^2.2.0", - "@stellar/js-xdr": "^5.0.0", - "@types/json-schema": "^7.0.15", - "axios": "1.18.0", - "bignumber.js": "^11.1.4", - "commander": "^14.0.3", - "eventsource": "^4.1.0", - "feaxios": "^0.0.23", - "smol-toml": "^1.6.1", - "uint8array-extras": "^1.5.0" - }, - "bin": { - "stellar-js": "bin/stellar-js" + "@babel/plugin-transform-react-jsx": "^7.29.7" }, "engines": { - "node": ">=22.12.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@stellar/stellar-sdk/node_modules/commander": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", - "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.29.7.tgz", + "integrity": "sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==", "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, "engines": { - "node": ">=20" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@tokenizer/inflate": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", - "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.7.tgz", + "integrity": "sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q==", "license": "MIT", "dependencies": { - "debug": "^4.4.3", - "token-types": "^6.1.1" + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "license": "MIT" - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.13.tgz", - "integrity": "sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz", + "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-syntax-typescript": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, + "node_modules/@babel/preset-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.29.7.tgz", + "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==", "license": "MIT", "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-syntax-jsx": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-typescript": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "license": "MIT", "dependencies": { - "@types/node": "*" + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", "license": "MIT", "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "license": "MIT", "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", - "dev": true, - "license": "MIT" + "node_modules/@borewit/text-codec": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", + "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } }, - "node_modules/@types/express": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", - "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^5.0.0", - "@types/serve-static": "^2" + "optional": true, + "engines": { + "node": ">=0.1.90" } }, - "node_modules/@types/express-serve-static-core": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.3.tgz", - "integrity": "sha512-dPfW8NFiOF4wOHc7+N/QSxlY9cfSsenewGbAz8C8U/MULPd/YZ27LvJUIlzaXie7e6Ove9YunJGgC9tbHD2cKw==", + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT" + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } }, - "node_modules/@types/node": { - "version": "22.20.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", - "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", - "dev": true, + "node_modules/@expo/code-signing-certificates": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@expo/code-signing-certificates/-/code-signing-certificates-0.0.6.tgz", + "integrity": "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "node-forge": "^1.3.3" } }, - "node_modules/@types/qs": { - "version": "6.15.1", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", - "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", - "dev": true, - "license": "MIT" + "node_modules/@expo/config": { + "version": "57.0.9", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-57.0.9.tgz", + "integrity": "sha512-dmzlKraIFxa7wLwV6K7WzI8jp6QZpW6Mc5mGjLimJUFjzh4uQdYaT3m3plEutM5yxBoBEwqzks7l+I/ljCbxAQ==", + "license": "MIT", + "dependencies": { + "@expo/config-plugins": "~57.0.9", + "@expo/config-types": "^57.0.2", + "@expo/json-file": "^11.0.1", + "@expo/require-utils": "^57.0.5", + "deepmerge": "^4.3.1", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "resolve-workspace-root": "^2.0.0", + "semver": "^7.6.0", + "slugify": "^1.3.4" + } }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true, + "node_modules/@expo/config-plugins": { + "version": "57.0.9", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-57.0.9.tgz", + "integrity": "sha512-hHgfL1avkCdEvDSw7IwlKwRYYNgcxzbNNMIk6W6lTkJpY0MajinAfeJUS0J+wPCsjUfGbVqOJM+XhPaO5ulUxg==", + "license": "MIT", + "dependencies": { + "@expo/config-types": "^57.0.2", + "@expo/json-file": "~11.0.1", + "@expo/plist": "^0.8.1", + "@expo/require-utils": "^57.0.5", + "@expo/sdk-runtime-versions": "^1.0.0", + "chalk": "^4.1.2", + "debug": "^4.3.5", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "semver": "^7.5.4", + "slugify": "^1.6.6", + "xcode": "^3.0.1", + "xml2js": "0.6.0" + } + }, + "node_modules/@expo/config-types": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-57.0.2.tgz", + "integrity": "sha512-ewW08OonrcRIsRKIlFvvcmmafE5zemb1ocu3HkNwtVPyRtj2w42pZCAkMIROYpcVBaPnc3mDT9UZDzwXWC3i6g==", "license": "MIT" }, - "node_modules/@types/send": { + "node_modules/@expo/devcert": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", - "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", - "dev": true, + "resolved": "https://registry.npmjs.org/@expo/devcert/-/devcert-1.2.1.tgz", + "integrity": "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA==", "license": "MIT", "dependencies": { - "@types/node": "*" + "@expo/sudo-prompt": "^9.3.1", + "debug": "^3.1.0" } }, - "node_modules/@types/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", - "dev": true, + "node_modules/@expo/devcert/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "license": "MIT", "dependencies": { - "@types/http-errors": "*", - "@types/node": "*" + "ms": "^2.1.1" } }, - "node_modules/@types/validator": { - "version": "13.15.10", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", - "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", - "license": "MIT" + "node_modules/@expo/devtools": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/@expo/devtools/-/devtools-57.0.1.tgz", + "integrity": "sha512-GyUf+wFNkbttaX0jR7MZa9bm77U0IrLg6d2AjpxdyoXw/w4abHoXG0oFufwLMgP9zLTd5+Ct4X/ffNUTnlzZgg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-native": { + "optional": true + } + } }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "node_modules/@expo/env": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.4.3.tgz", + "integrity": "sha512-M1NXeZCA1mkMkYOyIe7PlyRX0/jqFtMoJgyblnlq/vpCRfmueFT7RnGSQG8uEFDF5WHOFGijAQ3fogPh3/n5Ng==", + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "debug": "^4.3.4", + "getenv": "^2.0.0" + }, + "engines": { + "node": ">=20.12.0" + } + }, + "node_modules/@expo/expo-modules-macros-plugin": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@expo/expo-modules-macros-plugin/-/expo-modules-macros-plugin-0.6.1.tgz", + "integrity": "sha512-cpsLZE4rqkc1Y3eZTkxB98jrqY1YXgetmtxFt8q89jBRmk3quRuk1BZo+VcnCSObZardjg99r1k5xijEMONFGA==", "license": "MIT" }, - "node_modules/@types/whatwg-url": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", - "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "node_modules/@expo/fingerprint": { + "version": "0.20.11", + "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.20.11.tgz", + "integrity": "sha512-GC43EcjQwzpzNZISqmhvjKdi+6FTfxnC9ZxOeg6osCkYXJz94j107l0QpPLipg62khD5HAA5G5cUhevffbRC4w==", "license": "MIT", "dependencies": { - "@types/webidl-conversions": "*" + "@expo/env": "^2.4.3", + "@expo/spawn-async": "^1.8.0", + "arg": "^5.0.2", + "chalk": "^4.1.2", + "debug": "^4.3.4", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "ignore": "^5.3.1", + "minimatch": "^10.2.2", + "resolve-from": "^5.0.0", + "semver": "^7.6.0" + }, + "bin": { + "fingerprint": "bin/cli.js" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, + "node_modules/@expo/fingerprint/node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/@expo/fingerprint/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@expo/fingerprint/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@expo/fingerprint/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@expo/fingerprint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@expo/image-utils": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.11.5.tgz", + "integrity": "sha512-KPQBTpmpAfy/Vu9y4wPW808/qtZxjYmyJg8cm2QCPAupp+qEWA3b5zmk0ulOwQ9OgeHxuCPgUqWgkwHFo7UsrQ==", + "license": "MIT", + "dependencies": { + "@expo/require-utils": "^57.0.5", + "@expo/spawn-async": "^1.8.0", + "chalk": "^4.0.0", + "getenv": "^2.0.0", + "jimp-compact": "0.16.1", + "parse-png": "^2.1.0", + "semver": "^7.6.0" + } + }, + "node_modules/@expo/inline-modules": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@expo/inline-modules/-/inline-modules-0.1.7.tgz", + "integrity": "sha512-Bz/khd1gIJqDkje7t5ejD5e9jFbm4xEJzWSwRKadRo6gruepbw1xJ3Eb+e58OS8fY1ZNQYjzZbspnuph67sN0g==", + "license": "MIT", + "dependencies": { + "@expo/config-plugins": "~57.0.9" + } + }, + "node_modules/@expo/json-file": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-11.0.1.tgz", + "integrity": "sha512-zxHWj4MKKMAL29ZQSY/Fssx4Thluk40JmuGNaeS078wy/NhlFhnVi+rHHunulE3xJAJ0CM73m8VK2+GkF9eRwQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.20.0", + "json5": "^2.2.3" + } + }, + "node_modules/@expo/local-build-cache-provider": { + "version": "57.0.8", + "resolved": "https://registry.npmjs.org/@expo/local-build-cache-provider/-/local-build-cache-provider-57.0.8.tgz", + "integrity": "sha512-SEdE0pAQrr90bRh3MNR0ZuwoIBw390cYdFgbn7Vk0Mtm9EHaBfP7kYj+2hXnXZJgOEm3/JMtfoD3rV7rWA9FGg==", + "license": "MIT", + "dependencies": { + "@expo/config": "~57.0.9", + "chalk": "^4.1.2" + } + }, + "node_modules/@expo/metro": { + "version": "56.0.2", + "resolved": "https://registry.npmjs.org/@expo/metro/-/metro-56.0.2.tgz", + "integrity": "sha512-Ld5AeYMCCDa8bLeWhfuLbZFFjlV3f6ORqyPz2glGh6RltIngMuLf9BTC2yvHFjkKuGxL5SynijmA8xmNNWn5iA==", + "license": "MIT", + "dependencies": { + "metro": "0.84.5", + "metro-babel-transformer": "0.84.5", + "metro-cache": "0.84.5", + "metro-cache-key": "0.84.5", + "metro-config": "0.84.5", + "metro-core": "0.84.5", + "metro-file-map": "0.84.5", + "metro-minify-terser": "0.84.5", + "metro-resolver": "0.84.5", + "metro-runtime": "0.84.5", + "metro-source-map": "0.84.5", + "metro-symbolicate": "0.84.5", + "metro-transform-plugins": "0.84.5", + "metro-transform-worker": "0.84.5" + } + }, + "node_modules/@expo/metro-file-map": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/@expo/metro-file-map/-/metro-file-map-57.0.2.tgz", + "integrity": "sha512-tb50nSIWwKpRufSkGuivOK0FbUxv1Uwqptb0SzFTk0bkmYmcy3gIwnCbOHTfmrQDVndRhPEiu2SYgh9Z0PCvGg==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "fb-watchman": "^2.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "node_modules/@expo/metro-file-map/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@expo/metro-file-map/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@expo/osascript": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.7.1.tgz", + "integrity": "sha512-Zn03EX6In7ts2lPUW2ESUSkEhEWQN1qqsiXjadtZMJOuZRkMiAg1ZQHuvz9DjByDWNJ2pBwAGyrts9lj9k389g==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/package-manager": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.13.1.tgz", + "integrity": "sha512-y/K+CaYYpZpNGZhSX4HyLT/vyIunFjNfyoxNysPBCefeLKI/VCx6f9LNPzrxayr3rCYO5bl9O8H+HRQK265Nkg==", + "license": "MIT", + "dependencies": { + "@expo/json-file": "^11.0.1", + "@expo/spawn-async": "^1.8.0", + "chalk": "^4.0.0", + "npm-package-arg": "^11.0.0", + "ora": "^3.4.0", + "resolve-workspace-root": "^2.0.0" + } + }, + "node_modules/@expo/package-manager/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@expo/package-manager/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@expo/package-manager/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/@expo/package-manager/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@expo/package-manager/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "license": "MIT", + "dependencies": { + "chalk": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "license": "MIT", + "dependencies": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@expo/package-manager/node_modules/ora/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "license": "MIT", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/package-manager/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/@expo/package-manager/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@expo/package-manager/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@expo/plist": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.8.1.tgz", + "integrity": "sha512-3gTReGIUm0oRaMClsAJYxBnVPCl6fVpsl8HS+DTVxDhW4GyVyxg9E/Znm3BvcHtUJ51RJJI14pC1wvrNilCRHw==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + } + }, + "node_modules/@expo/prebuild-config": { + "version": "57.0.15", + "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-57.0.15.tgz", + "integrity": "sha512-xTbWHroj0PDmlbqvmU+zF9ZZxveJkiuyiPoeRJYRGruFHebRAWnoTdw5S7d/UCzDBI8ropGGu9g2eb2nMxtvAw==", + "license": "MIT", + "dependencies": { + "@expo/config": "~57.0.9", + "@expo/config-plugins": "~57.0.9", + "@expo/config-types": "^57.0.2", + "@expo/image-utils": "^0.11.5", + "@expo/json-file": "^11.0.1", + "@react-native/normalize-colors": "0.86.3", + "debug": "^4.3.1", + "expo-modules-autolinking": "~57.0.12", + "resolve-from": "^5.0.0", + "semver": "^7.6.0" + } + }, + "node_modules/@expo/prebuild-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@expo/require-utils": { + "version": "57.0.5", + "resolved": "https://registry.npmjs.org/@expo/require-utils/-/require-utils-57.0.5.tgz", + "integrity": "sha512-kTAXj9lDFEIPMsbAOGCGbjBbMF0oi7CqkYM79KOX0DDD9wSwXmlKL1z2h8OwsrBf7mbOo2DjlRvZu4BEjrIxGw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.20.0", + "@babel/core": "^7.25.2", + "@babel/plugin-transform-modules-commonjs": "^7.24.8" + }, + "peerDependencies": { + "typescript": "^5.0.0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@expo/schema-utils": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/@expo/schema-utils/-/schema-utils-57.0.2.tgz", + "integrity": "sha512-fMu/jyN0l1Wzv7XkeWR4IYCx1M8ryui3FdBNGrWwbRgJ7EhxXxK8E2jxP2W3pbgUwUY0V3hG8+GyfCZwny+Lxw==", + "license": "MIT" + }, + "node_modules/@expo/sdk-runtime-versions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz", + "integrity": "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ==", + "license": "MIT" + }, + "node_modules/@expo/spawn-async": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@expo/spawn-async/-/spawn-async-1.8.0.tgz", + "integrity": "sha512-eb9xxd/LbuEGSdua4NumCu/McVB9EM+F/JxB9pWgnERw4HQ9XyTNH1KapG6oqLWR8TuRK2LQfzJlmNi94CVobw==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@expo/sudo-prompt": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@expo/sudo-prompt/-/sudo-prompt-9.3.2.tgz", + "integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==", + "license": "MIT" + }, + "node_modules/@expo/xcpretty": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/@expo/xcpretty/-/xcpretty-4.4.4.tgz", + "integrity": "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/code-frame": "^7.20.0", + "chalk": "^4.1.0", + "js-yaml": "^4.1.0" + }, + "bin": { + "excpretty": "build/cli.js" + } + }, + "node_modules/@expo/xcpretty/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", + "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.23", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", + "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/external-editor": "^1.0.3", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", + "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", + "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", + "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", + "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", + "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.3.2", + "@inquirer/confirm": "^5.1.21", + "@inquirer/editor": "^4.2.23", + "@inquirer/expand": "^4.0.23", + "@inquirer/input": "^4.3.1", + "@inquirer/number": "^3.0.23", + "@inquirer/password": "^4.0.23", + "@inquirer/rawlist": "^4.1.11", + "@inquirer/search": "^3.2.2", + "@inquirer/select": "^4.4.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", + "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", + "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", + "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@ioredis/commands": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz", + "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==", + "license": "MIT" + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@microsoft/tsdoc": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.16.0.tgz", + "integrity": "sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==", + "license": "MIT" + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.13.tgz", + "integrity": "sha512-E3Sv4eCYAlKYUTx8S3ioQcDUscOif+8zZ5OnW1IzJ+Tt+EO+ke8mn+Y3FX6N1H79picwbdOavVOb1jPi2EOyrg==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz", + "integrity": "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz", + "integrity": "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz", + "integrity": "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz", + "integrity": "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz", + "integrity": "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz", + "integrity": "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@nestjs/cli": { + "version": "11.0.24", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-11.0.24.tgz", + "integrity": "sha512-aIHxQLSYtXShifA3zwWIeznEsZnNa3Iz2QRykFj+sl9IcbERBHr5nH87FRgywM+He3NxoF5WazHfR8FsmVeWxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.27", + "@angular-devkit/schematics": "19.2.27", + "@angular-devkit/schematics-cli": "19.2.27", + "@inquirer/prompts": "7.10.1", + "@nestjs/schematics": "^11.0.1", + "ansis": "4.2.0", + "chokidar": "4.0.3", + "cli-table3": "0.6.5", + "commander": "4.1.1", + "fork-ts-checker-webpack-plugin": "9.1.0", + "glob": "13.0.6", + "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.106.2", + "webpack-node-externals": "3.0.0" + }, + "bin": { + "nest": "bin/nest.js" + }, + "engines": { + "node": ">= 20.11" + }, + "peerDependencies": { + "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0 || ^0.8.0", + "@swc/core": "^1.3.62" + }, + "peerDependenciesMeta": { + "@swc/cli": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nestjs/common": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.2.1.tgz", + "integrity": "sha512-SEgtP+M9DqNhQkgJIlJ3oTp3gemo/8owySovzMGmJj2kcfIH1G6QP45AAb8dE4a3IpVicpUvdDAy7Syk7ebjBw==", + "license": "MIT", + "dependencies": { + "file-type": "21.3.4", + "iterare": "1.2.1", + "load-esm": "1.0.3", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": ">=0.4.1", + "class-validator": ">=0.13.2", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/config": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-4.0.4.tgz", + "integrity": "sha512-CJPjNitr0bAufSEnRe2N+JbnVmMmDoo6hvKCPzXgZoGwJSmp/dZPk9f/RMbuD/+Q1ZJPjwsRpq0vxna++Knwow==", + "license": "MIT", + "dependencies": { + "dotenv": "17.4.1", + "dotenv-expand": "12.0.3", + "lodash": "4.18.1" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "rxjs": "^7.1.0" + } + }, + "node_modules/@nestjs/core": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.2.1.tgz", + "integrity": "sha512-M5PWFU8NdRTgX9Po49d7TQKg7f5t8GAVUa/Esy4tmaMWcKugTzg3ZzpJfD3LEPMuRHjfs6+8pQYgtuP2uz3rDw==", + "license": "MIT", + "dependencies": { + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "8.4.2", + "tslib": "2.8.1", + "uid": "2.0.2" + }, + "engines": { + "node": ">= 20" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0", + "@nestjs/websockets": "^11.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "node_modules/@nestjs/mapped-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.1.1.tgz", + "integrity": "sha512-SCCoMEJ6jdeI5h/N+KCVF1+pmg/hmEkNA5nHTS8Gvww7T/LCl4o1gFLinw2iQ60w7slFkszHcGLKGdazVI4F8A==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "class-transformer": "^0.4.0 || ^0.5.0", + "class-validator": "^0.13.0 || ^0.14.0 || ^0.15.0", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/mongoose": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@nestjs/mongoose/-/mongoose-11.0.4.tgz", + "integrity": "sha512-LUOlUeSOfbjdIu22QwOmczv2CzJQr9LUBo2mOfbXrGCu2svpr5Hiu71zBFrb/9UC+H8BjGMKbBOq1nEbMF6ZJA==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "@nestjs/core": "^10.0.0 || ^11.0.0", + "mongoose": "^7.0.0 || ^8.0.0 || ^9.0.0", + "rxjs": "^7.0.0" + } + }, + "node_modules/@nestjs/platform-express": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-11.2.1.tgz", + "integrity": "sha512-lbaVW94s1u8AJfgmBtdMPi16MEuFBiLrnflUIA9tZ9e5eoUsGTN7XXXRjU5kTTLgjnTCM53qgBXXGmTqmyfoQA==", + "license": "MIT", + "dependencies": { + "cors": "2.8.6", + "express": "5.2.1", + "multer": "2.2.0", + "path-to-regexp": "8.4.2", + "tslib": "2.8.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0" + } + }, + "node_modules/@nestjs/schematics": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-11.1.0.tgz", + "integrity": "sha512-lVxGZ46tcdItFMoXr6vyKWlnOsm1SZm/GUqAEDvy2RL4Q4O+3bkziAhrO7Y8JLssFUUvNFEGqAizI52WAxhjDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.24", + "@angular-devkit/schematics": "19.2.24", + "comment-json": "5.0.0", + "jsonc-parser": "3.3.1", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "prettier": "^3.0.0", + "typescript": ">=4.8.2" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/@nestjs/schematics/node_modules/@angular-devkit/core": { + "version": "19.2.24", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.24.tgz", + "integrity": "sha512-Kd49warf6U/EyWe5BszF/eebN3zQ3bk7tgfEljAw8q/rX95UUtriJubWvp6pgzHfzBA4jwq8f+QiNZB8eBEXPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.18.0", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.4", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@nestjs/schematics/node_modules/@angular-devkit/schematics": { + "version": "19.2.24", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.2.24.tgz", + "integrity": "sha512-lnw+ZM1Io+cJAkReC0NPDjqObL8NtKzKIkdgEEKC8CUmkhurYhedbicN8Y8NYHgG1uLd2GozW3+/QqPRZaN+Lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "19.2.24", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.17", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@nestjs/schematics/node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/@nestjs/swagger": { + "version": "11.4.7", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.4.7.tgz", + "integrity": "sha512-QyDYnmfP4IRucgmtQxMqzgRBdWtjFoDp8eFvvgf92+3wdLCL+Q0xOFO1948j/ntW/Wi7qT2dyck6ka8ADzPWQQ==", + "license": "MIT", + "dependencies": { + "@microsoft/tsdoc": "0.16.0", + "@nestjs/mapped-types": "2.1.1", + "js-yaml": "5.3.0", + "lodash": "4.18.1", + "path-to-regexp": "8.4.2", + "swagger-ui-dist": "5.32.13" + }, + "peerDependencies": { + "@fastify/static": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/common": "^11.0.1", + "@nestjs/core": "^11.0.1", + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0" + }, + "peerDependenciesMeta": { + "@fastify/static": { + "optional": true + }, + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@noble/ed25519": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-3.2.0.tgz", + "integrity": "sha512-criDgRlnUA09hchYrTy/JUWPIEap5rZxQe6wDWzRx51oWWpDRcUpuNzlgPxDJaOK6AsW9c0wKcj3rKRv6t+bPQ==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.4.0.tgz", + "integrity": "sha512-X5XaVWZIBCT7HHZGm5I7ZQXDwLG+bGXuSrMQAW+7Zvl87h1kmc1ZB1VSRJcpUfoUrGQp4Fkoxm5kZ+Ms+aW+eA==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.86.3.tgz", + "integrity": "sha512-TDhgCZA4wjJg84d5A9swiOQYPIWSKEEVdg9IwMFZDupQzW/F3QoLUrfAJOcalgqTDA9/buTB8awhE3Whwg6u9Q==", + "license": "MIT", + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.86.3.tgz", + "integrity": "sha512-O6Xza4JBGPIU8J7YbKTyBoYL4thpy8jMW/oaLDWdAyOwYHKIjK47pAL5HUEbOe2bWz2PEKjbYRF2ApkJv1ottQ==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.0", + "@react-native/codegen": "0.86.3" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.86.3.tgz", + "integrity": "sha512-Ux4jHi0fh+bdtVEcL0gaPLbY56V+SvFUDl/8sRAE1jdb4k+o7fT/4Nc29yz4X+qfjstkSqObQTMBGhdzxH9JvA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/parser": "^7.29.0", + "hermes-parser": "0.36.0", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "tinyglobby": "^0.2.15", + "yargs": "^17.6.2" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/codegen/node_modules/hermes-estree": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.36.0.tgz", + "integrity": "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w==", + "license": "MIT" + }, + "node_modules/@react-native/codegen/node_modules/hermes-parser": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.36.0.tgz", + "integrity": "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.36.0" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.86.3.tgz", + "integrity": "sha512-qSDL9LQc5mZSZPNczT95WU9YQuPzxBklgON9vLhhqfI0yWIwKInqFx88dQ/uiEXBtf0yossthaQIqA4Ml6bF6g==", + "license": "MIT", + "dependencies": { + "@react-native/dev-middleware": "0.86.3", + "debug": "^4.4.0", + "invariant": "^2.2.4", + "metro": "^0.84.3", + "metro-config": "^0.84.3", + "metro-core": "^0.84.3", + "semver": "^7.1.3" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + }, + "peerDependencies": { + "@react-native-community/cli": "*", + "@react-native/metro-config": "0.86.3" + }, + "peerDependenciesMeta": { + "@react-native-community/cli": { + "optional": true + }, + "@react-native/metro-config": { + "optional": true + } + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.86.3.tgz", + "integrity": "sha512-TQmeofQ0PcuylhhlleOeuzHYZfbrgm3gayXzowqUEzgRisTm1D40/J3ggqs7XkQi5HP5ZA3n8dHmKL9vIzPcsw==", + "license": "BSD-3-Clause", + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/@react-native/debugger-shell": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-shell/-/debugger-shell-0.86.3.tgz", + "integrity": "sha512-O4ds+J7xZfxkbih9T+cAGegBdvKSPKYJm/lDgC9CpEjFMkmzWTpVLU3Qsv9sqZuo58z+sGhIcJfPsCFFWHpqbQ==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.6", + "debug": "^4.4.0", + "fb-dotslash": "0.5.8" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.86.3.tgz", + "integrity": "sha512-LiEPTqTg/63bYUnrPyHLfjTDCNhA/+CUqI1+DsA9tYyewtSbULd5awsva6SgE10I+2iMhgKXS3ymkhU/kSCrGA==", + "license": "MIT", + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.86.3", + "@react-native/debugger-shell": "0.86.3", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^0.3.0", + "connect": "^3.6.5", + "debug": "^4.4.0", + "invariant": "^2.2.4", + "nullthrows": "^1.1.1", + "open": "^7.0.3", + "serve-static": "^1.16.2", + "ws": "^7.5.10" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/@react-native/dev-middleware/node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.86.3.tgz", + "integrity": "sha512-lxmx0GqLEWRIpZfpYFXlYVIs3ENQwaW6Vmp6oi29l2GoQJ1wZfFZRdMimDWlGEk8LKfHar3QH3iaPMkTcK9lEQ==", + "license": "MIT", + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.86.3.tgz", + "integrity": "sha512-eYIJ0es967+tePBFQDnl/gidVFxLns3fnbiK6rxscQrGodvuUO6hwxpQnfNynJ8MjbbndImXihXjcnJdc7SzJg==", + "license": "MIT", + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.86.3.tgz", + "integrity": "sha512-Cv3CDkprb67GrzuaS9BGbBJC/6G4lIw3nyKOHRKTqTTum4bn37y5+R0Z04L8mcbQN85eEohNrRwb7IOM4j6uvg==", + "license": "MIT" + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.86.3.tgz", + "integrity": "sha512-1j44NEyNn05Ut40vHAmoSWbsIcybFkMAOBTwQt1PrESyfSS+qBoyU1LGIogNva0VIa0rQyEC5PzbA7R4/7Nhyw==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + }, + "peerDependencies": { + "@types/react": "^19.2.0", + "react": "*", + "react-native": "0.86.3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@redis/bloom": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.12.1.tgz", + "integrity": "sha512-PUUfv+ms7jgPSBVoo/DN4AkPHj4D5TZSd6SbJX7egzBplkYUcKmHRE8RKia7UtZ8bSQbLguLvxVO+asKtQfZWA==", + "license": "MIT", + "engines": { + "node": ">= 18.19.0" + }, + "peerDependencies": { + "@redis/client": "^5.12.1" + } + }, + "node_modules/@redis/client": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-5.12.1.tgz", + "integrity": "sha512-7aPGWeqA3uFm43o19umzdl16CEjK/JQGtSXVPevplTaOU3VJA/rseBC1QvYUz9lLDIMBimc4SW/zrW4S89BaCA==", + "license": "MIT", + "dependencies": { + "cluster-key-slot": "1.1.2" + }, + "engines": { + "node": ">= 18.19.0" + }, + "peerDependencies": { + "@node-rs/xxhash": "^1.1.0", + "@opentelemetry/api": ">=1 <2" + }, + "peerDependenciesMeta": { + "@node-rs/xxhash": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + } + } + }, + "node_modules/@redis/client/node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@redis/json": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-5.12.1.tgz", + "integrity": "sha512-eOze75esLve4vfqDel7aMX08CNaiLLQS2fV8mpRN9NxPe1rVR4vQyYiW/OgtGUysF6QOr9ANhfxABKNOJfXdKg==", + "license": "MIT", + "engines": { + "node": ">= 18.19.0" + }, + "peerDependencies": { + "@redis/client": "^5.12.1" + } + }, + "node_modules/@redis/search": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-5.12.1.tgz", + "integrity": "sha512-ItlxbxC9cKI6IU1TLWoczwJCRb6TdmkEpWv05UrPawqaAnWGRu3rcIqsc5vN483T2fSociuyV1UkWIL5I4//2w==", + "license": "MIT", + "engines": { + "node": ">= 18.19.0" + }, + "peerDependencies": { + "@redis/client": "^5.12.1" + } + }, + "node_modules/@redis/time-series": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.12.1.tgz", + "integrity": "sha512-c6JL6E3EcZJuNqKFz+KM+l9l5mpcQiKvTwgA3blt5glWJ8hjDk0yeHN3beE/MpqYIQ8UEX44ItQzgkE/gCBELQ==", + "license": "MIT", + "engines": { + "node": ">= 18.19.0" + }, + "peerDependencies": { + "@redis/client": "^5.12.1" + } + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.12", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.12.tgz", + "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==", + "license": "MIT" + }, + "node_modules/@stellar/js-xdr": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-5.0.0.tgz", + "integrity": "sha512-HBDNKnxr+ecdaEmbZ0mcKkirOF8tXXEbWSw34P3wT40Tn3g+u+cCH17xAWZymzscq8cojHB8340pR8QNVaD32w==", + "license": "Apache-2.0", + "engines": { + "node": ">=22.0.0", + "pnpm": ">=10.0.0" + } + }, + "node_modules/@stellar/stellar-sdk": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-17.0.1.tgz", + "integrity": "sha512-fsHHbzJ14N5Ttq5Qpz4AX0ytmPSLCzcy4XC3uIgSQz0cBkEgv0Zb4KE6tWEd3nDQUk/1qP8ZX9cRonIaUXO3Sw==", + "license": "Apache-2.0", + "dependencies": { + "@exodus/bytes": "^1.15.1", + "@noble/ed25519": "^3.1.0", + "@noble/hashes": "^2.2.0", + "@stellar/js-xdr": "^5.0.0", + "@types/json-schema": "^7.0.15", + "axios": "1.18.0", + "bignumber.js": "^11.1.4", + "commander": "^14.0.3", + "eventsource": "^4.1.0", + "feaxios": "^0.0.23", + "smol-toml": "^1.6.1", + "uint8array-extras": "^1.5.0" + }, + "bin": { + "stellar-js": "bin/stellar-js" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@stellar/stellar-sdk/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/@tokenizer/inflate": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", + "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "token-types": "^6.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.13.tgz", + "integrity": "sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz", + "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "^2" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.3.tgz", + "integrity": "sha512-dPfW8NFiOF4wOHc7+N/QSxlY9cfSsenewGbAz8C8U/MULPd/YZ27LvJUIlzaXie7e6Ove9YunJGgC9tbHD2cKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*" + } + }, + "node_modules/@types/validator": { + "version": "13.15.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", + "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", + "license": "MIT" + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.4.0.tgz", + "integrity": "sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==", + "license": "ISC" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.15.tgz", + "integrity": "sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-cli-detector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/agent-cli-detector/-/agent-cli-detector-0.1.6.tgz", + "integrity": "sha512-vKrPeEVN3upDF3GjWxsWBbwQgMtNJ8VB1cduPvK3svmmz4ENpS7yaPxbogsbe3w+xp9xp2Cu+0Ar41rjAR4+lA==", + "license": "MIT", + "bin": { + "agent-cli-detector": "dist/cli.js" + }, + "engines": { + "node": ">=18.18" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", + "integrity": "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==", + "license": "MIT" + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz", + "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-react-compiler": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz", + "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + } + }, + "node_modules/babel-plugin-react-native-web": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.21.2.tgz", + "integrity": "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==", + "license": "MIT" + }, + "node_modules/babel-plugin-syntax-hermes-parser": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.36.0.tgz", + "integrity": "sha512-LhD0xdoedDw7ansQgXbB2DADLZIK/LRXuWNBPuVzMc5S2WK5GyT89tCM+cQzxFGO0mGyLK6D5TrVOJJzAoDy8Q==", + "license": "MIT", + "dependencies": { + "hermes-parser": "0.36.0" + } + }, + "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-estree": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.36.0.tgz", + "integrity": "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w==", + "license": "MIT" + }, + "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-parser": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.36.0.tgz", + "integrity": "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.36.0" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.15", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.15.tgz", + "integrity": "sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bignumber.js": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-11.1.5.tgz", + "integrity": "sha512-6WmzCNtUnfKpbozq+hOgWaZMMzORmYBwF1xZScyoIX3QRYWeKTtxxwDOW5tIz7C9BdjkIYHGTcelCLkXg0mndw==", + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^2.0.0", + "debug": "^4.4.3", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", + "on-finished": "^2.4.1", + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/bson": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", + "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bullmq": { + "version": "5.81.3", + "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.81.3.tgz", + "integrity": "sha512-Q7uEH2G92rVjX3Yl2qw3+6VEO15uxehC6DfeTHQBQTehddcRDSDuquD9zuvDjxiCffXsPUaBwrRlvlbVcgKs7g==", + "license": "MIT", + "dependencies": { + "cron-parser": "4.9.0", + "ioredis": "5.11.1", + "msgpackr": "2.0.5", + "node-abort-controller": "3.1.1", + "semver": "7.8.5", + "tslib": "2.8.1" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "redis": ">=5.0.0" + }, + "peerDependenciesMeta": { + "redis": { + "optional": true + } + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "node_modules/chardet": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", + "integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==", "dev": true, "license": "MIT" }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "license": "MIT", + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "engines": { + "node": ">=6.0" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, + "node_modules/chromium-edge-launcher": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-0.3.0.tgz", + "integrity": "sha512-p03azHlGjtyRvFEee3cyvtsRYdniSkwjkzmM/KmVnqT5d7QkkwpJBhis/zCLMYdQMVJ5tt140TBNqqrZPaWeFA==", "license": "Apache-2.0", "dependencies": { - "@xtuc/long": "4.2.2" + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "license": "MIT" }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, + "node_modules/class-transformer": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", + "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "license": "MIT" + }, + "node_modules/class-validator": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.4.tgz", + "integrity": "sha512-AwNusCCam51q703dW82x95tOqQp6oC9HNUl724KxJJOfnKscI8dOloXFgyez7LbTTKWuRBA37FScqVbJEoq8Yw==", "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" + "@types/validator": "^13.15.3", + "libphonenumber-js": "^1.11.1", + "validator": "^13.15.22" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "license": "BSD-3-Clause" + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "license": "Apache-2.0" + "node_modules/cluster-key-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", + "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 0.6" + "node": ">=7.0.0" } }, - "node_modules/acorn": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", - "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", - "dev": true, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">=0.4.0" + "node": ">= 0.8" } }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, "license": "MIT", "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" + "node": ">= 6" } }, - "node_modules/acorn-walk": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", - "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "node_modules/comment-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-5.0.0.tgz", + "integrity": "sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.0" + "array-timsort": "^1.0.3", + "esprima": "^4.0.1" }, "engines": { - "node": ">=0.4.0" + "node": ">= 6" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "license": "MIT", "dependencies": { - "debug": "4" + "mime-db": ">= 1.43.0 < 2" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 0.6" } }, - "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "dev": true, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "dev": true, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "ms": "2.0.0" } }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 0.10.0" } }, - "node_modules/ansis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", - "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", - "license": "MIT" - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/array-timsort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" + "node_modules/connect/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "node_modules/axios": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz", - "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==", + "node_modules/connect/node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.16.0", - "form-data": "^4.0.5", - "https-proxy-agent": "^5.0.1", - "proxy-from-env": "^2.1.0" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" + "node_modules/connect/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } }, - "node_modules/baseline-browser-mapping": { - "version": "2.11.15", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.15.tgz", - "integrity": "sha512-FwMjJJ7HnyZpWe+oWxegG0fezZyBZUagI5LZEoO3GCbtbKNwRfMH9Ue5d5v01PNePBy1QSfPSDTTeVL0Hb9EzA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" + "node_modules/connect/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "license": "MIT", + "engines": { + "node": ">=18" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">= 0.6" } }, - "node_modules/bignumber.js": { - "version": "11.1.5", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-11.1.5.tgz", - "integrity": "sha512-6WmzCNtUnfKpbozq+hOgWaZMMzORmYBwF1xZScyoIX3QRYWeKTtxxwDOW5tIz7C9BdjkIYHGTcelCLkXg0mndw==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/body-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", - "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/core-js-compat": { + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz", + "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", "license": "MIT", "dependencies": { - "bytes": "^3.1.2", - "content-type": "^2.0.0", - "debug": "^4.4.3", - "http-errors": "^2.0.1", - "iconv-lite": "^0.7.2", - "on-finished": "^2.4.1", - "qs": "^6.15.2", - "raw-body": "^3.0.2", - "type-is": "^2.1.0" + "browserslist": "^4.28.7" }, "engines": { - "node": ">=18" + "node": ">=6.4.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://opencollective.com/core-js" } }, - "node_modules/body-parser/node_modules/content-type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", - "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, "engines": { - "node": ">=18" + "node": ">= 0.10" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, - "node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/browserslist": { - "version": "4.28.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", - "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "type": "github", + "url": "https://github.com/sponsors/puzrin" }, { "type": "github", - "url": "https://github.com/sponsors/ai" + "url": "https://github.com/sponsors/nodeca" } ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.11.12", - "caniuse-lite": "^1.0.30001809", - "electron-to-chromium": "^1.5.402", - "node-releases": "^2.0.53", - "update-browserslist-db": "^1.3.0" + "argparse": "^2.0.1" }, "bin": { - "browserslist": "cli.js" + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "deprecated": "v4 is no longer maintained, upgrade to v5", + "license": "MIT", + "dependencies": { + "luxon": "^3.2.1" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">=12.0.0" } }, - "node_modules/bson": { - "version": "6.10.4", - "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", - "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", - "license": "Apache-2.0", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=16.20.1" + "node": ">= 8" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } - ], + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dnssd-advertise": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/dnssd-advertise/-/dnssd-advertise-1.1.6.tgz", + "integrity": "sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg==", "license": "MIT" }, - "node_modules/bullmq": { - "version": "5.81.3", - "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.81.3.tgz", - "integrity": "sha512-Q7uEH2G92rVjX3Yl2qw3+6VEO15uxehC6DfeTHQBQTehddcRDSDuquD9zuvDjxiCffXsPUaBwrRlvlbVcgKs7g==", - "license": "MIT", + "node_modules/dotenv": { + "version": "17.4.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.1.tgz", + "integrity": "sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-12.0.3.tgz", + "integrity": "sha512-uc47g4b+4k/M/SeaW1y4OApx+mtLWl92l5LMPP0GNXctZqELk+YGgOPIIC5elYmUH4OuoK3JLhuRUYegeySiFA==", + "license": "BSD-2-Clause", "dependencies": { - "cron-parser": "4.9.0", - "ioredis": "5.11.1", - "msgpackr": "2.0.5", - "node-abort-controller": "3.1.1", - "semver": "7.8.5", - "tslib": "2.8.1" + "dotenv": "^16.4.5" }, "engines": { - "node": ">=12.22.0" + "node": ">=12" }, - "peerDependencies": { - "redis": ">=5.0.0" + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "redis": { - "optional": true - } + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", "dependencies": { - "streamsearch": "^1.1.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=10.16.0" + "node": ">= 0.4" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.411", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.411.tgz", + "integrity": "sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg==", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/enhanced-resolve": { + "version": "5.24.5", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", + "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" }, "engines": { - "node": ">= 0.4" + "node": ">=10.13.0" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001809", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", - "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" + "license": "MIT" }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/chardet": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", - "integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==", - "dev": true, - "license": "MIT" - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { - "readdirp": "^4.0.1" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "node": ">= 0.4" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", "engines": { - "node": ">=6.0" + "node": ">=6" } }, - "node_modules/class-transformer": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", - "integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, - "node_modules/class-validator": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.4.tgz", - "integrity": "sha512-AwNusCCam51q703dW82x95tOqQp6oC9HNUl724KxJJOfnKscI8dOloXFgyez7LbTTKWuRBA37FScqVbJEoq8Yw==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "license": "MIT", - "dependencies": { - "@types/validator": "^13.15.3", - "libphonenumber-js": "^1.11.1", - "validator": "^13.15.22" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "restore-cursor": "^3.1.0" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4" } }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "string-width": "^4.2.0" + "estraverse": "^5.2.0" }, "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" + "node": ">=4.0" } }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "engines": { - "node": ">= 12" + "node": ">=4.0" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=0.8" + "node": ">=4.0" } }, - "node_modules/cluster-key-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", - "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", - "license": "Apache-2.0", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=6" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/eventsource": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-4.1.1.tgz", + "integrity": "sha512-D6bTRWh6KahHTK/m4WnjPQyEinNPf9eFLEZSEoj7d6fTibspnAVYfzHvirL7u/aoX5d9YYfIkBVAhmigUELk9w==", "license": "MIT", "dependencies": { - "delayed-stream": "~1.0.0" + "eventsource-parser": "^3.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">=20.0.0" } }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, + "node_modules/eventsource-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.1.tgz", + "integrity": "sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==", "license": "MIT", "engines": { - "node": ">= 6" + "node": ">=18.0.0" } }, - "node_modules/comment-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-5.0.0.tgz", - "integrity": "sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==", - "dev": true, + "node_modules/expo": { + "version": "57.0.18", + "resolved": "https://registry.npmjs.org/expo/-/expo-57.0.18.tgz", + "integrity": "sha512-6nax9hJPhf9dWrstliXUABTJXDNIJrfJKcCtjSxuYVs2Yf127GIhKf3wsEYSFUl+LFdRbPPTNaweJePH159wZA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "@expo/cli": "^57.0.20", + "@expo/config": "~57.0.9", + "@expo/config-plugins": "~57.0.9", + "@expo/devtools": "~57.0.1", + "@expo/dom-webview": "~57.0.1", + "@expo/fingerprint": "^0.20.11", + "@expo/local-build-cache-provider": "^57.0.8", + "@expo/log-box": "^57.0.4", + "@expo/metro": "~56.0.2", + "@expo/metro-config": "~57.0.12", + "@ungap/structured-clone": "^1.3.0", + "babel-preset-expo": "~57.0.9", + "expo-asset": "~57.0.15", + "expo-constants": "~57.0.16", + "expo-file-system": "~57.0.6", + "expo-font": "~57.0.2", + "expo-keep-awake": "~57.0.1", + "expo-modules-autolinking": "~57.0.12", + "expo-modules-core": "~57.0.14", + "pretty-format": "^29.7.0", + "react-refresh": "^0.14.2", + "whatwg-url-minimum": "^0.1.2" + }, + "bin": { + "expo": "bin/cli", + "expo-modules-autolinking": "bin/autolinking", + "fingerprint": "bin/fingerprint" + }, + "peerDependencies": { + "@expo/dom-webview": "*", + "@expo/metro-runtime": "*", + "react": "*", + "react-dom": "*", + "react-native": "*", + "react-native-web": "*", + "react-native-webview": "*" + }, + "peerDependenciesMeta": { + "@expo/dom-webview": { + "optional": true + }, + "@expo/metro-runtime": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native-web": { + "optional": true + }, + "react-native-webview": { + "optional": true + } + } + }, + "node_modules/expo-modules-autolinking": { + "version": "57.0.12", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-57.0.12.tgz", + "integrity": "sha512-Q8KAlq37nLKsQ+HsS9NpQVpd5jCgqtu694TDUNHBUBpV9ViD82mRBh8Uug/h68RG9xnLS+kuL4nYaCuFRghHjg==", "license": "MIT", "dependencies": { - "array-timsort": "^1.0.3", - "esprima": "^4.0.1" + "@expo/require-utils": "^57.0.5", + "@expo/spawn-async": "^1.8.0", + "chalk": "^4.1.0", + "commander": "^7.2.0" }, - "engines": { - "node": ">= 6" + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" + "node_modules/expo-modules-autolinking/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "engines": [ - "node >= 6.0" - ], + "node_modules/expo-modules-core": { + "version": "57.0.14", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-57.0.14.tgz", + "integrity": "sha512-Cg3aQnVsQhZcMOF/RFgPGzMuhIak5W9eR9ecwmFSeQ813r4/49ut6RMA6PqUuUKuPCUIRqnBAHfSyTm1W9nfzg==", "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" + "@expo/expo-modules-macros-plugin": "0.6.1", + "expo-modules-jsi": "~57.0.6", + "invariant": "^2.2.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*", + "react-native-worklets": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0" + }, + "peerDependenciesMeta": { + "react-native-worklets": { + "optional": true + } } }, - "node_modules/content-disposition": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", - "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "node_modules/expo-modules-jsi": { + "version": "57.0.6", + "resolved": "https://registry.npmjs.org/expo-modules-jsi/-/expo-modules-jsi-57.0.6.tgz", + "integrity": "sha512-WK0xFEe0FdZTCLCdfXK+HVNYfAmEbA6goecRxqjr0gh3XYRKAr9tikxqcM0ItLQoEPKntscPZhWcPLGvr97Tfw==", "license": "MIT", - "engines": { - "node": ">=18" + "peerDependencies": { + "react-native": "*" + } + }, + "node_modules/expo-server": { + "version": "57.0.3", + "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-57.0.3.tgz", + "integrity": "sha512-aK+LdKzauHSGmsOStZtyxdzv0zWssCkxTw3m4QuOhfDSJsZaMRTd9O41d8ixU/QfELTbaJ0oRNcF7JFV/7O9YQ==", + "license": "MIT", + "engines": { + "node": ">=20.16.0" + } + }, + "node_modules/expo/node_modules/@expo/cli": { + "version": "57.0.20", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-57.0.20.tgz", + "integrity": "sha512-ZjWz7SA5TBTyKq4+aFRUPgMFxmqHtKkDMv6d85J2UAAjdRhkNRf+B80t+rr5IFo2ywuTvyrPRBth4ei4w08olA==", + "license": "MIT", + "dependencies": { + "@expo/code-signing-certificates": "^0.0.6", + "@expo/config": "~57.0.9", + "@expo/config-plugins": "~57.0.9", + "@expo/devcert": "^1.2.1", + "@expo/env": "~2.4.3", + "@expo/image-utils": "^0.11.5", + "@expo/inline-modules": "^0.1.7", + "@expo/json-file": "^11.0.1", + "@expo/log-box": "^57.0.4", + "@expo/metro": "~56.0.2", + "@expo/metro-config": "~57.0.12", + "@expo/metro-file-map": "^57.0.2", + "@expo/osascript": "^2.7.1", + "@expo/package-manager": "^1.13.1", + "@expo/plist": "^0.8.1", + "@expo/prebuild-config": "^57.0.15", + "@expo/require-utils": "^57.0.5", + "@expo/router-server": "^57.0.8", + "@expo/schema-utils": "^57.0.2", + "@expo/spawn-async": "^1.8.0", + "@expo/ws-tunnel": "^2.0.0", + "@expo/xcpretty": "^4.4.4", + "@react-native/dev-middleware": "0.86.3", + "accepts": "^1.3.8", + "agent-cli-detector": "0.1.6", + "arg": "^5.0.2", + "bplist-creator": "0.1.0", + "bplist-parser": "^0.3.1", + "chalk": "^4.0.0", + "ci-info": "^3.3.0", + "compression": "^1.7.4", + "connect": "^3.7.0", + "debug": "^4.3.4", + "dnssd-advertise": "^1.1.4", + "expo-server": "^57.0.3", + "fetch-nodeshim": "^0.4.10", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "lan-network": "^0.2.1", + "multitars": "^1.0.2", + "node-forge": "^1.3.3", + "npm-package-arg": "^11.0.0", + "ora": "^3.4.0", + "picomatch": "^4.0.4", + "pretty-format": "^29.7.0", + "progress": "^2.0.3", + "prompts": "^2.3.2", + "resolve-from": "^5.0.0", + "sandbox-cli-detector": "^0.2.0", + "semver": "^7.6.0", + "send": "^0.19.0", + "slugify": "^1.3.4", + "stacktrace-parser": "^0.1.10", + "structured-headers": "^0.4.1", + "terminal-link": "^2.1.1", + "toqr": "^0.1.1", + "wrap-ansi": "^7.0.0", + "ws": "^8.12.1", + "zod": "^3.25.76" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "bin": { + "expo-internal": "main.js" + }, + "peerDependencies": { + "expo": "*", + "expo-router": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "expo-router": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "node_modules/expo/node_modules/@expo/cli/node_modules/@expo/router-server": { + "version": "57.0.8", + "resolved": "https://registry.npmjs.org/@expo/router-server/-/router-server-57.0.8.tgz", + "integrity": "sha512-lEPGYoDmh97yyEcY/MFWQsfE7yIgMRnGDcnsBN7B6AiWBFSJIMEcGnO0aYPgY0ZjNWyJDi7Ee8QZRGqB+LhI6w==", "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "@expo/metro-runtime": "^57.0.14", + "expo": "*", + "expo-constants": "^57.0.15", + "expo-font": "^57.0.1", + "expo-router": "*", + "expo-server": "^57.0.3", + "react": "*", + "react-dom": "*", + "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" + }, + "peerDependenciesMeta": { + "@expo/metro-runtime": { + "optional": true + }, + "expo-router": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-server-dom-webpack": { + "optional": true + } } }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "node_modules/expo/node_modules/@expo/dom-webview": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/@expo/dom-webview/-/dom-webview-57.0.1.tgz", + "integrity": "sha512-lAKsME4SAq+8sf56oN0DX5TBYyruupoRxbWbD2xf9RnKY8y6x8eb9LCE5pxSN0qyWdqnp+0wmyWzDkKboThKAw==", "license": "MIT", - "engines": { - "node": ">= 0.6" + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "node_modules/expo/node_modules/@expo/log-box": { + "version": "57.0.4", + "resolved": "https://registry.npmjs.org/@expo/log-box/-/log-box-57.0.4.tgz", + "integrity": "sha512-IxwS9s1L2muj8mj8AQSuiy7u8OFJdc02NRFo2me/Tj6DiaeG5SREqmpBE4rQpR2cadqSg5jl8Qab8Cjie616dg==", "license": "MIT", - "engines": { - "node": ">=6.6.0" + "dependencies": { + "@expo/dom-webview": "^57.0.1", + "anser": "^1.4.9", + "stacktrace-parser": "^0.1.10" + }, + "peerDependencies": { + "@expo/dom-webview": "^57.0.1", + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo/node_modules/@expo/metro-config": { + "version": "57.0.12", + "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-57.0.12.tgz", + "integrity": "sha512-S62Lrq35HZqBFD55423pmWb8PjaiR/W02zQC1uECBmw1vTN8WZaFz4TJ0i21EeJzwfebMb9MLxL8JZ102Z6VbA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.20.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.5", + "@expo/config": "~57.0.9", + "@expo/env": "~2.4.3", + "@expo/json-file": "~11.0.1", + "@expo/metro": "~56.0.2", + "@expo/require-utils": "^57.0.5", + "@expo/spawn-async": "^1.8.0", + "@jridgewell/gen-mapping": "^0.3.13", + "@jridgewell/remapping": "^2.3.5", + "@jridgewell/sourcemap-codec": "^1.5.5", + "browserslist": "^4.25.0", + "chalk": "^4.1.0", + "debug": "^4.3.2", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "hermes-parser": "^0.36.0", + "jsc-safe-url": "^0.2.4", + "lightningcss": "^1.30.1", + "picomatch": "^4.0.4", + "postcss": "^8.5.14", + "resolve-from": "^5.0.0" + }, + "peerDependencies": { + "expo": "*" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + } + } + }, + "node_modules/expo/node_modules/@expo/ws-tunnel": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-2.0.0.tgz", + "integrity": "sha512-j+JfTRdCk820J9dU0sA2SqshQIKFOMo7ED84w9MJFcebfbNQgsLztEY/SABDkGnjatrW4xGqnUhVRxSBVyCkXw==", + "license": "MIT", + "peerDependencies": { + "ws": "^8.0.0" } }, - "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "node_modules/expo/node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" }, "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.6" } }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, + "node_modules/expo/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "license": "MIT", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" + "node": ">=6" + } + }, + "node_modules/expo/node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/expo/node_modules/babel-preset-expo": { + "version": "57.0.9", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-57.0.9.tgz", + "integrity": "sha512-T19biGOBTnMp161PyBqWOoSIEeZug8/EjtuUdVob8JPQKZMTalHUQaQt+qtQQE7XsEkZJ6erb3k0CohneTFzQg==", + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.20.5", + "@babel/helper-module-imports": "^7.25.9", + "@babel/plugin-proposal-decorators": "^7.12.9", + "@babel/plugin-proposal-export-default-from": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-class-static-block": "^7.27.1", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-flow-strip-types": "^7.25.2", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.28.6", + "@babel/plugin-transform-react-jsx-development": "^7.27.1", + "@babel/plugin-transform-react-pure-annotations": "^7.27.1", + "@babel/plugin-transform-runtime": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.25.2", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/preset-typescript": "^7.23.0", + "@react-native/babel-plugin-codegen": "0.86.3", + "babel-plugin-react-compiler": "^1.0.0", + "babel-plugin-react-native-web": "~0.21.0", + "babel-plugin-syntax-hermes-parser": "^0.36.0", + "babel-plugin-transform-flow-enums": "^0.0.2", + "debug": "^4.3.4" }, "peerDependencies": { - "typescript": ">=4.9.5" + "@babel/runtime": "^7.20.0", + "expo": "*", + "expo-widgets": "^57.0.13", + "react-refresh": ">=0.14.0 <1.0.0" }, "peerDependenciesMeta": { - "typescript": { + "@babel/runtime": { + "optional": true + }, + "expo": { + "optional": true + }, + "expo-widgets": { "optional": true } } }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", - "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", - "dev": true, + "node_modules/expo/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "funding": [ { "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" + "url": "https://github.com/sponsors/sibiraj-s" } ], "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=8" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cron-parser": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", - "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", - "deprecated": "v4 is no longer maintained, upgrade to v5", + "node_modules/expo/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", "license": "MIT", "dependencies": { - "luxon": "^3.2.1" + "restore-cursor": "^2.0.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=4" } }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/expo/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "license": "MIT", "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "color-name": "1.1.3" } }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, + "node_modules/expo/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/expo/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, + "node_modules/expo/node_modules/expo-asset": { + "version": "57.0.15", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-57.0.15.tgz", + "integrity": "sha512-ZoiUftQb1Nn1jvL6l1kZoUXvgRCx57tMQYxSsp+g4ZvY+jgVWp/THruXOtPtZVdC/WWZxPUTct53bfAm2EPDAQ==", "license": "MIT", "dependencies": { - "clone": "^1.0.2" + "@expo/image-utils": "^0.11.5", + "expo-constants": "~57.0.15" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/expo/node_modules/expo-constants": { + "version": "57.0.16", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-57.0.16.tgz", + "integrity": "sha512-HG3yJjGZo2BPTo2F1sBoxdJZRwX7d9C554EhKn8m12K62pxGolCsvPSoh/lQf95OEP9vO34wwXB2C3QFs0KG0g==", "license": "MIT", - "engines": { - "node": ">=0.4.0" + "dependencies": { + "@expo/env": "~2.4.3" + }, + "peerDependencies": { + "expo": "*", + "react-native": "*" } }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" + "node_modules/expo/node_modules/expo-file-system": { + "version": "57.0.6", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-57.0.6.tgz", + "integrity": "sha512-pm8PMYEW6BnVOCBJ7df9FcDmQtE1tqImuYphlfYe1ipQRLYtdCayRczJcbKIsnB3mqEyp4gC2gWmMbsAsAOjVg==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react-native": "*" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/expo/node_modules/expo-font": { + "version": "57.0.2", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-57.0.2.tgz", + "integrity": "sha512-eWR0CAdysgVqg8VewJ8b5wKh1pa6C8YShIEU3SP0+hlSqOk4djUwuJjn3P04KHVzL3hws9FrUuPxCNmd4TGung==", "license": "MIT", - "engines": { - "node": ">= 0.8" + "dependencies": { + "fontfaceobserver": "^2.1.0" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" + "node_modules/expo/node_modules/expo-keep-awake": { + "version": "57.0.1", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-57.0.1.tgz", + "integrity": "sha512-28lkFImeXTS+bhAjuCFV7w7tW5bXg27BJVrxv+nC/nyYa86qEa0oFeHwqol6ha5k4pdVDQgBF09GM4A1k76Ssg==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*" } }, - "node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/expo/node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">= 0.6" } }, - "node_modules/dotenv": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.1.tgz", - "integrity": "sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==", - "license": "BSD-2-Clause", + "node_modules/expo/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">=4" } }, - "node_modules/dotenv-expand": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-12.0.3.tgz", - "integrity": "sha512-uc47g4b+4k/M/SeaW1y4OApx+mtLWl92l5LMPP0GNXctZqELk+YGgOPIIC5elYmUH4OuoK3JLhuRUYegeySiFA==", - "license": "BSD-2-Clause", - "dependencies": { - "dotenv": "^16.4.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } + "node_modules/expo/node_modules/hermes-estree": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.36.1.tgz", + "integrity": "sha512-guv1nQ6IJ7S83NRFPWc3SA7IBZrdNC9kapwOq6uXvF4wP+sDCgjzQbKPCoyYmoyZRzztF/n/c36l/rccCZSiCw==", + "license": "MIT" }, - "node_modules/dotenv-expand/node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node_modules/expo/node_modules/hermes-parser": { + "version": "0.36.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.36.1.tgz", + "integrity": "sha512-GApNk4zLHi2UWoWZZkx7LNCOSzLSc5lB55pZ/PhK7ycFeg7u5LcF88p/WbpIi1XUDtE0MpHE3uRR3u3KB7TjSQ==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.36.1" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/expo/node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "chalk": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.411", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.411.tgz", - "integrity": "sha512-gglkxzokjHfawpGxq75XdBV2/l3BAPzrsMs70qgaZdTW5rpV1tC4MdgJVP9fN126bODA4ZJQkn1wryEzJyQXIg==", - "dev": true, - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/expo/node_modules/log-symbols/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/enhanced-resolve": { - "version": "5.24.5", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.24.5.tgz", - "integrity": "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==", - "dev": true, + "node_modules/expo/node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.3" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=4" } }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, + "node_modules/expo/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "engines": { + "node": ">= 0.6" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/expo/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, "engines": { - "node": ">= 0.4" + "node": ">= 0.6" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/expo/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/es-module-lexer": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", - "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "node_modules/expo/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, "engines": { - "node": ">= 0.4" + "node": ">= 0.6" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/expo/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "mimic-fn": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, + "node_modules/expo/node_modules/ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", "license": "MIT", + "dependencies": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, "engines": { "node": ">=6" } }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/expo/node_modules/ora/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=4" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "node_modules/expo/node_modules/ora/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/expo/node_modules/ora/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "ansi-regex": "^4.1.0" }, "engines": { - "node": ">=4.0" + "node": ">=6" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/expo/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">= 0.6" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/expo/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=8" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/expo/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", "license": "MIT", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, + "node_modules/expo/node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, "engines": { - "node": ">=0.8.x" + "node": ">= 0.8.0" } }, - "node_modules/eventsource": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-4.1.1.tgz", - "integrity": "sha512-D6bTRWh6KahHTK/m4WnjPQyEinNPf9eFLEZSEoj7d6fTibspnAVYfzHvirL7u/aoX5d9YYfIkBVAhmigUELk9w==", + "node_modules/expo/node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "eventsource-parser": "^3.0.1" + "ms": "2.0.0" + } + }, + "node_modules/expo/node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/expo/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/expo/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=4" } }, - "node_modules/eventsource-parser": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.1.tgz", - "integrity": "sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==", + "node_modules/expo/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=18.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/expo/node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "license": "Apache-2.0" + }, "node_modules/express": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", @@ -2863,6 +6223,44 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fb-dotslash": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/fb-dotslash/-/fb-dotslash-0.5.8.tgz", + "integrity": "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==", + "license": "(MIT OR Apache-2.0)", + "bin": { + "dotslash": "bin/dotslash" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/feaxios": { "version": "0.0.23", "resolved": "https://registry.npmjs.org/feaxios/-/feaxios-0.0.23.tgz", @@ -2872,6 +6270,12 @@ "is-retry-allowed": "^3.0.0" } }, + "node_modules/fetch-nodeshim": { + "version": "0.4.10", + "resolved": "https://registry.npmjs.org/fetch-nodeshim/-/fetch-nodeshim-0.4.10.tgz", + "integrity": "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==", + "license": "MIT" + }, "node_modules/file-type": { "version": "21.3.4", "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.4.tgz", @@ -2890,6 +6294,18 @@ "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -2911,6 +6327,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "license": "MIT" + }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", @@ -2931,6 +6353,12 @@ } } }, + "node_modules/fontfaceobserver": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz", + "integrity": "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg==", + "license": "BSD-2-Clause" + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz", @@ -3045,6 +6473,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -3082,11 +6528,19 @@ "node": ">= 0.4" } }, + "node_modules/getenv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/getenv/-/getenv-2.0.0.tgz", + "integrity": "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/glob": { "version": "13.0.6", "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "minimatch": "^10.2.2", @@ -3111,7 +6565,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" @@ -3121,7 +6574,6 @@ "version": "5.0.9", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -3134,7 +6586,6 @@ "version": "10.2.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.8" @@ -3162,14 +6613,12 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3214,6 +6663,45 @@ "node": ">= 0.4" } }, + "node_modules/hermes-compiler": { + "version": "250829098.0.17", + "resolved": "https://registry.npmjs.org/hermes-compiler/-/hermes-compiler-250829098.0.17.tgz", + "integrity": "sha512-qG1PXzTEtriF6oQLZF3vyHhSMxOdW5h2TqqLri0rdpstPustd2fSvRZQMVAPdlhgFwBfYnj3OUZtiO6LjYsEFw==", + "license": "MIT" + }, + "node_modules/hermes-estree": { + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.35.0.tgz", + "integrity": "sha512-xVx5Opwy8Oo1I5yGpVRhCvWL/iV3M+ylksSKVNlxxD90cpDpR/AR1jLYqK8HWihm065a6UI3HeyAmYzwS8NOOg==", + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.35.0.tgz", + "integrity": "sha512-9JLjeHxBx8T4CAsydZR49PNZUaix+WpQJwu9p2010lu+7Kwl6D/7wYFFJxoz+aXkaaClp9Zfg6W6/zVlSJORaA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.35.0" + } + }, + "node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -3283,6 +6771,15 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -3306,6 +6803,15 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ioredis": { "version": "5.11.1", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.11.1.tgz", @@ -3344,11 +6850,40 @@ "dev": true, "license": "MIT" }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3364,6 +6899,15 @@ "node": ">=8" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -3395,6 +6939,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, "node_modules/iterare": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", @@ -3404,6 +6966,76 @@ "node": ">=6" } }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -3435,11 +7067,16 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/jimp-compact": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz", + "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==", + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -3464,6 +7101,24 @@ "js-yaml": "bin/js-yaml.mjs" } }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "license": "0BSD" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -3482,7 +7137,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -3507,24 +7161,337 @@ "dependencies": { "universalify": "^2.0.0" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lan-network": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/lan-network/-/lan-network-0.2.1.tgz", + "integrity": "sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A==", + "license": "MIT", + "bin": { + "lan-network": "dist/lan-network-cli.js" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/libphonenumber-js": { + "version": "1.13.11", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.13.11.tgz", + "integrity": "sha512-ETER2kMaIFTI/Nh1a8Gk03dUF/SL0VZqtI+CcVHZxp5WIHYwNS7S+uiYZDYCvLy3lOR4/DAD5jf0h5WkePPpqg==", + "license": "MIT" + }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lighthouse-logger/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/lighthouse-logger/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/kareem": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", - "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", - "license": "Apache-2.0", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.0.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/libphonenumber-js": { - "version": "1.13.11", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.13.11.tgz", - "integrity": "sha512-ETER2kMaIFTI/Nh1a8Gk03dUF/SL0VZqtI+CcVHZxp5WIHYwNS7S+uiYZDYCvLy3lOR4/DAD5jf0h5WkePPpqg==", - "license": "MIT" + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -3572,6 +7539,18 @@ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -3589,11 +7568,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "11.5.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", - "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" @@ -3625,6 +7615,21 @@ "dev": true, "license": "ISC" }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marky": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", + "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", + "license": "Apache-2.0" + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -3660,6 +7665,12 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==", + "license": "MIT" + }, "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", @@ -3678,13 +7689,425 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/metro": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.84.5.tgz", + "integrity": "sha512-r1liLkyFZMVSEMNjU1CJU5pRzs3NdkxHqXS60O25c0rCIqAR+cGk7rPydw/g0WAIKVXojIBIF45yYBPagJGcgw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/core": "^7.25.2", + "@babel/generator": "^7.29.1", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "accepts": "^2.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^4.4.0", + "error-stack-parser": "^2.0.6", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.35.0", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.84.5", + "metro-cache": "0.84.5", + "metro-cache-key": "0.84.5", + "metro-config": "0.84.5", + "metro-core": "0.84.5", + "metro-file-map": "0.84.5", + "metro-resolver": "0.84.5", + "metro-runtime": "0.84.5", + "metro-source-map": "0.84.5", + "metro-symbolicate": "0.84.5", + "metro-transform-plugins": "0.84.5", + "metro-transform-worker": "0.84.5", + "mime-types": "^3.0.1", + "nullthrows": "^1.1.1", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "throat": "^5.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.84.5.tgz", + "integrity": "sha512-2WbHILKMiJUzfdjmGOQOqU1bWi9//gqiclc/tkk/AIsrrVw3efhZ1uhkOwMTxUEPOzqoo091H0olLmVZH5FHGQ==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "hermes-parser": "0.35.0", + "metro-cache-key": "0.84.5", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-cache": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.84.5.tgz", + "integrity": "sha512-WHS0n2OxQqtwEjSeQFPePNrMvEFhmQcUQM9cRJMHByWoi/GMWFBEWOf7hVkAM/0KRutAXNbDlSu/cZB6CyxgQQ==", + "license": "MIT", + "dependencies": { + "exponential-backoff": "^3.1.1", + "flow-enums-runtime": "^0.0.6", + "https-proxy-agent": "^7.0.5", + "metro-core": "0.84.5" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-cache-key": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.84.5.tgz", + "integrity": "sha512-3dPB2TnvGjjf0/9O7AXVQURKXuQNauTZE7WpTGTlR017Gh/B5y0m/2wcqxfveUguHSpu89KhVxCAlr2k/H7uhQ==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-cache/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/metro-cache/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/metro-config": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.84.5.tgz", + "integrity": "sha512-zie+uN6oohscowi2S7ByU+wUw6CrT4ZxW9uAbONOObSxx86RGmnIAmjXHLkfmcdYoY7jzOPEbqcI6oeVmqyBQA==", + "license": "MIT", + "dependencies": { + "connect": "^3.6.5", + "flow-enums-runtime": "^0.0.6", + "jest-validate": "^29.7.0", + "metro": "0.84.5", + "metro-cache": "0.84.5", + "metro-core": "0.84.5", + "metro-runtime": "0.84.5", + "yaml": "^2.6.1" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-core": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.84.5.tgz", + "integrity": "sha512-xwm605hCi5Y6eJTTb8ZWo6pkUcoBEIyiQOfkZh5GwtDwUrP9SNhTQZhzJHrBCwwxlf3Ptl/pxWJgQ1rsNYMnrA==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.84.5" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-file-map": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.84.5.tgz", + "integrity": "sha512-mlm/JL8toSbSc2akpKIGmzvrVRSCgZ5vkbycI34oMLoOnLGuLyC8WTyVJ6P0hZG/usDaGwZSl/s9BCRriqjGJA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "fb-watchman": "^2.0.0", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-file-map/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro-file-map/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/metro-minify-terser": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.84.5.tgz", + "integrity": "sha512-BJoFwCEDsYnagPqarayInv2+diCDNDdLlaof/p6s9w4gh+gc9HXYM+pDvsKGKKUumpZswNF3Z/ftTMqKl/5IBg==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "terser": "^5.15.0" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-resolver": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.84.5.tgz", + "integrity": "sha512-VSSnepg1k6LyCwtb6eirWdAWlpKwBG8Rdtsr1mU38rMelFyWgh3/QuMSiZIZAIjwg/fsa8GhW5/FO54CAUPCEA==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-runtime": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.84.5.tgz", + "integrity": "sha512-U1m2+d1Pr+JO2/iVXBB2OfXXityz7tqwIorxfrT15IEgaHvpJBq/OHiqnOWPKJbUl3JcxjcdviZZOKk85oK4Qg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-source-map": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.84.5.tgz", + "integrity": "sha512-2BtV5L9uPc49F13Gn5wiP6bX/EncqzqTIk2VL/0F/96Vo0YEOjluT/qktQjFODfqGFsucwnh5mPEAl/2jVEfeg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.84.5", + "nullthrows": "^1.1.1", + "ob1": "0.84.5", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.84.5.tgz", + "integrity": "sha512-rQ40zYDAkaWBN9yvjUuAD0ZpzBMZSoKyGYXnb5JrfbKjun7fTvfoLHL3KXFYenBTYZkQtlp4cKSCv/1utxFyOw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.84.5", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-symbolicate/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.84.5.tgz", + "integrity": "sha512-+InaSVGaOyt0DyRo4Y/zIdPI6CZwnbNho5LAL23tgmuGwv7fyfkF7kKfPjZcfxXBcoYdTLLFnCfCH/dHSiCqNg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.29.1", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "flow-enums-runtime": "^0.0.6", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.84.5.tgz", + "integrity": "sha512-ui1Z8x4s5RL36gMmKLaMMO7O9NNDHNdthEZSCDQHAau3JcAsTaFOK6I+2q4I/kW5u8hSEjJk9L45TXSVJw6g1A==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.29.1", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "flow-enums-runtime": "^0.0.6", + "metro": "0.84.5", + "metro-babel-transformer": "0.84.5", + "metro-cache": "0.84.5", + "metro-cache-key": "0.84.5", + "metro-minify-terser": "0.84.5", + "metro-source-map": "0.84.5", + "metro-transform-plugins": "0.84.5", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, + "node_modules/metro/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", @@ -3747,12 +8170,23 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mongodb": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.20.0.tgz", @@ -3951,6 +8385,12 @@ "node": ">= 0.6" } }, + "node_modules/multitars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/multitars/-/multitars-1.0.2.tgz", + "integrity": "sha512-6GwVw5eLi9sThdtlS4PKwC7yRLaf45pYhIEzKBHdKxi+YOXGKFX8acIniH+Uh/+k9mS2lQOupTccjoe5r0/1IQ==", + "license": "MIT" + }, "node_modules/mute-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", @@ -3961,6 +8401,24 @@ "node": "^18.17.0 || >=20.5.0" } }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", @@ -3993,6 +8451,15 @@ "lodash": "^4.17.21" } }, + "node_modules/node-forge": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/node-gyp-build-optional-packages": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", @@ -4008,16 +8475,54 @@ "node-gyp-build-optional-packages-test": "build-test.js" } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "license": "MIT" + }, "node_modules/node-releases": { "version": "2.0.53", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" } }, + "node_modules/npm-package-arg": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", + "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "license": "MIT" + }, + "node_modules/ob1": { + "version": "0.84.5", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.84.5.tgz", + "integrity": "sha512-aH9RkoZc7w/90HBamFxTw8ZLFr05wXS+iOnvmrgo53Ep8Pyrm5FieQSaPIVROkfFVQISeD/zo92fes26TOwe+A==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4051,6 +8556,15 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4076,6 +8590,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -4132,6 +8662,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-png": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", + "integrity": "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==", + "license": "MIT", + "dependencies": { + "pngjs": "^3.3.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -4141,11 +8683,25 @@ "node": ">= 0.8" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, "node_modules/path-scurry": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^11.0.0", @@ -4182,14 +8738,12 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -4198,6 +8752,29 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/plist/node_modules/@xmldom/xmldom": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.12.tgz", + "integrity": "sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -4208,6 +8785,109 @@ "node": ">=4" } }, + "node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/proc-log": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", + "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "license": "MIT", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -4283,6 +8963,108 @@ "node": ">= 0.10" } }, + "node_modules/react": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", + "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-6.1.5.tgz", + "integrity": "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==", + "license": "MIT", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-native": { + "version": "0.86.3", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.86.3.tgz", + "integrity": "sha512-JR5s3bM9ezud+Mw24GlNXNfthqPIKwrQgPPJcam+L97t2sKjjEavhCzBn+fyqZZRcM5+XlhYxpTxVkK7e1n38Q==", + "license": "MIT", + "dependencies": { + "@react-native/assets-registry": "0.86.3", + "@react-native/codegen": "0.86.3", + "@react-native/community-cli-plugin": "0.86.3", + "@react-native/gradle-plugin": "0.86.3", + "@react-native/js-polyfills": "0.86.3", + "@react-native/normalize-colors": "0.86.3", + "@react-native/virtualized-lists": "0.86.3", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "babel-plugin-syntax-hermes-parser": "0.36.0", + "base64-js": "^1.5.1", + "commander": "^12.0.0", + "flow-enums-runtime": "^0.0.6", + "hermes-compiler": "250829098.0.17", + "invariant": "^2.2.4", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.84.3", + "metro-source-map": "^0.84.3", + "nullthrows": "^1.1.1", + "pretty-format": "^29.7.0", + "promise": "^8.3.0", + "react-devtools-core": "^6.1.5", + "react-refresh": "^0.14.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.27.0", + "semver": "^7.1.3", + "stacktrace-parser": "^0.1.10", + "tinyglobby": "^0.2.15", + "whatwg-fetch": "^3.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0" + }, + "peerDependencies": { + "@react-native/jest-preset": "0.86.3", + "@types/react": "^19.1.1", + "react": "^19.2.3" + }, + "peerDependenciesMeta": { + "@react-native/jest-preset": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-native/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -4354,6 +9136,74 @@ "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "license": "Apache-2.0" }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.2.tgz", + "integrity": "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -4364,6 +9214,27 @@ "node": ">=0.10.0" } }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -4374,6 +9245,12 @@ "node": ">=4" } }, + "node_modules/resolve-workspace-root": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.1.tgz", + "integrity": "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==", + "license": "MIT" + }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -4446,6 +9323,33 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/sandbox-cli-detector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sandbox-cli-detector/-/sandbox-cli-detector-0.2.0.tgz", + "integrity": "sha512-4lyHX0ZU0AZKwjgZ1InxZAa3PNpyEb8rOQ+Zss1ReYmhNzW0Q+h1zE5nvniXN0HaAWZaZE1zgVNEirb0R7LmNg==", + "license": "MIT", + "bin": { + "sandbox-cli-detector": "dist/cli.js" + }, + "engines": { + "node": ">=18.18" + } + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -4537,6 +9441,15 @@ "url": "https://opencollective.com/express" } }, + "node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/serve-static": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", @@ -4562,6 +9475,39 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", + "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/side-channel": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", @@ -4653,6 +9599,32 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slugify": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.9.tgz", + "integrity": "sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/smol-toml": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz", @@ -4675,11 +9647,19 @@ "node": ">= 8" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -4690,7 +9670,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -4705,6 +9684,24 @@ "memory-pager": "^1.0.2" } }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-parser": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", + "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", @@ -4720,6 +9717,15 @@ "node": ">= 0.8" } }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -4741,7 +9747,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -4756,7 +9761,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -4791,11 +9795,16 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/structured-headers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz", + "integrity": "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -4804,6 +9813,31 @@ "node": ">=8" } }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/swagger-ui-dist": { "version": "5.32.13", "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.32.13.tgz", @@ -4837,11 +9871,26 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/terser": { "version": "5.50.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.50.0.tgz", "integrity": "sha512-CN9BVxWhgS/hRxtUMjtC2uRWSTcSfQFHMDWma6sKKfIivCD91sM+FOPfvwoaRMqCSrUpe1nv3jDamd9eEQ4y+w==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -4970,9 +10019,48 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, "license": "MIT" }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -5000,6 +10088,12 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/toqr": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/toqr/-/toqr-0.1.1.tgz", + "integrity": "sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA==", + "license": "MIT" + }, "node_modules/tr46": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", @@ -5093,6 +10187,15 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, "node_modules/type-is": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", @@ -5134,7 +10237,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -5172,9 +10275,48 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, "license": "MIT" }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -5198,7 +10340,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.1.tgz", "integrity": "sha512-ZZ61DsRsOnakl74HAmp3oSN4aXUmEWXf+i/yv0h7tIBfICc3VdrFErQKUUKPgu3AMsTUMbcongALEN4l6GSUrQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5241,6 +10382,25 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -5248,6 +10408,15 @@ "dev": true, "license": "MIT" }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/validator": { "version": "13.15.35", "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz", @@ -5266,6 +10435,21 @@ "node": ">= 0.8" } }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "license": "MIT" + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/watchpack": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", @@ -5283,7 +10467,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, "license": "MIT", "dependencies": { "defaults": "^1.0.3" @@ -5404,6 +10587,12 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, "node_modules/whatwg-url": { "version": "14.2.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", @@ -5417,6 +10606,27 @@ "node": ">=18" } }, + "node_modules/whatwg-url-minimum": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/whatwg-url-minimum/-/whatwg-url-minimum-0.1.2.tgz", + "integrity": "sha512-XPEm0XFQWNVG292lII1PrRRJl3sItrs7CettZ4ncYxuDVpLyy+NwlGyut2hXI0JswcJUxeCH+CyOJK0ZzAXD6A==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -5438,11 +10648,123 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, + "node_modules/ws": { + "version": "7.5.13", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz", + "integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xml2js": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz", + "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" diff --git a/backend/package.json b/backend/package.json index 5404167..0c511f7 100644 --- a/backend/package.json +++ b/backend/package.json @@ -26,7 +26,10 @@ "redis": "^5.0.0", "reflect-metadata": "^0.2.1", "rxjs": "^7.0.0", - "zod": "^3.24.0" + "zod": "^3.24.0", + "expo": "~57.0.18", + "react": "19.2.3", + "react-native": "0.86.3" }, "devDependencies": { "@nestjs/cli": "^11.0.0", diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 4fce6e9..032f779 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -19,6 +19,10 @@ import { StellarModule } from './stellar/stellar.module'; imports: [ConfigModule], useFactory: (config: ConfigService) => ({ uri: config.get('MONGODB_URI', 'mongodb://localhost:27017/save'), + // Stellar routes do not depend on MongoDB. Start the API even when the + // local database is temporarily offline so network and vault health + // checks remain available. + lazyConnection: true, }), inject: [ConfigService], }), diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 228fc83..c5051a4 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -16,8 +16,13 @@ "strictNullChecks": true, "strictPropertyInitialization": false, "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, + "forceConsistentCasingInFileNames": true }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules", "dist"] + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "node_modules", + "dist" + ] } diff --git a/src/app/stellar.tsx b/src/app/stellar.tsx index 1cc3c3b..bb4fe4b 100644 --- a/src/app/stellar.tsx +++ b/src/app/stellar.tsx @@ -265,7 +265,7 @@ export default function StellarScreen() { {!walletConfig.configured ? WalletConnect configuration requiredSet EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID in the root .env, then restart Expo. A custom metadata URL is optional. : null} {walletConfig.configured && walletConfig.usingDefaultMetadata ? Using the SAVE GitHub repository as temporary WalletConnect metadata. : null} {walletSession ? <>✓ {walletSession.walletName}{walletSession.address} void disconnectFreighter()}>{walletBusy ? 'Disconnecting…' : 'Disconnect Freighter'} : void connectFreighter()}>{walletBusy ? 'Waiting for Freighter approval…' : 'Connect Freighter Mobile'}} - {pairingUri ? void copyPairingUri()}>Copy Pairing URI void Linking.openURL(`freighterwallet://wc?uri=${encodeURIComponent(pairingUri)}`)}>Open Freighter : null} + {pairingUri ? void copyPairingUri()}>Copy Pairing URI void Linking.openURL(`freighterwallet://wc-redirect?uri=${encodeURIComponent(pairingUri)}`)}>Open Freighter : null} Watch-only Testnet account diff --git a/src/lib/wallet-connect.native.ts b/src/lib/wallet-connect.native.ts index 7f88ed3..721416f 100644 --- a/src/lib/wallet-connect.native.ts +++ b/src/lib/wallet-connect.native.ts @@ -5,7 +5,7 @@ import type { SessionTypes } from '@walletconnect/types'; const TESTNET_CHAIN = 'stellar:testnet'; const REQUIRED_METHOD = 'stellar_signXDR'; -const FREIGHTER_DEEP_LINK = 'freighterwallet://wc?uri='; +const FREIGHTER_DEEP_LINK = 'freighterwallet://wc-redirect?uri='; const DEFAULT_METADATA_URL = 'https://github.com/FWDP/save-project'; const DEFAULT_METADATA_ICON = 'https://raw.githubusercontent.com/FWDP/save-project/main/assets/images/icon.png'; From 71b86fa45af4a21b9f3ad148ca6c8f544201158c Mon Sep 17 00:00:00 2001 From: Peter Joshua Brion Date: Mon, 31 Aug 2026 17:35:50 +0800 Subject: [PATCH 5/5] feat(savings): link tracked goals to Stellar vault --- README.md | 306 +++++++++++++++------ backend/.env.example | 5 +- backend/src/savings/savings-goal.schema.ts | 7 +- backend/src/savings/savings.dto.ts | 15 +- backend/src/savings/savings.service.ts | 4 + backend/src/stellar/stellar.dto.ts | 5 + backend/src/stellar/stellar.module.ts | 14 +- backend/src/stellar/stellar.schema.ts | 2 + backend/src/stellar/stellar.service.ts | 84 +++++- src/app/(tabs)/savings.tsx | 50 ++-- src/app/stellar.tsx | 62 ++++- src/lib/api.ts | 6 +- 12 files changed, 420 insertions(+), 140 deletions(-) diff --git a/README.md b/README.md index a622610..7715880 100644 --- a/README.md +++ b/README.md @@ -1,121 +1,253 @@ -# SAVE Project +

+ SAVE Finance logo +

-This project includes: +# SAVE Finance -- Expo mobile app for Android/iOS -- NestJS backend API -- Next.js admin dashboard -- MongoDB for primary data persistence -- Redis for cache and queues -- MinIO for object storage -- Docker Compose for local services +### Personal finance and goal-based saving, with optional Stellar rails -## Quick start +Track spending. Plan budgets. Build savings on Stellar Testnet without giving up custody of your wallet. -1. Install root app dependencies: +SAVE brings everyday money management, receipt capture, savings goals, and externally signed Stellar transactions into one mobile-first workspace. A NestJS API supports the app, while a Next.js dashboard provides an operational view. - ```bash - npm install - ``` +[Explore the repository](https://github.com/FWDP/save-project) · [Stellar architecture](docs/STELLAR_ARCHITECTURE.md) · [Savings vault contract](docs/CONTRACT.md) · [Test evidence](docs/DELIVERABLES_1_2_TEST_REPORT.md) -2. Install backend dependencies: +> [!IMPORTANT] +> SAVE's blockchain features are alpha software for **Stellar Testnet only**. The project does not support Mainnet or real-value custody. SAVE never asks for or stores a wallet secret seed; an external wallet must approve every transaction. - ```bash - cd backend && npm install - ``` +--- -3. Install admin dashboard dependencies: +## 🧩 Why SAVE - ```bash - cd admin && npm install - ``` +Personal finances are often split across expense trackers, spreadsheets, receipt folders, bank apps, and crypto wallets. That fragmentation makes it difficult to connect daily spending decisions with longer-term savings goals. -4. Start local services: +SAVE combines those workflows while keeping a clear trust boundary: private financial records remain off-chain, public ledger activity is independently verifiable, and signing authority stays in the user's wallet. - ```bash - docker compose up -d - ``` +## 🔁 The SAVE Money Loop -5. Start the backend: +**Track → Budget → Save → Sign → Verify** - ```bash - cd backend && npm run start:dev - ``` +| Capability | What SAVE helps you do | Current status | +| --- | --- | --- | +| 🧾 Track | Record transactions, organize categories, and capture receipts. | Implemented alpha | +| 📊 Budget | Plan category budgets and review financial reports. | Implemented alpha | +| 🎯 Save | Create and manage traditional or Stellar-backed savings goals. | Implemented alpha | +| ✍️ Sign | Prepare unsigned Testnet transactions and approve them in an external wallet. | Freighter Mobile via WalletConnect v2; SEP-7/XDR fallbacks | +| 🔎 Verify | Reconcile transaction status through Horizon and Stellar RPC, with explorer links for ledger proof. | Testnet qualification implemented | -6. Start the admin dashboard: +## ✨ What You Can Do Today - ```bash - cd admin && npm run dev - ``` +- Track expenses and transactions across configurable categories. +- Create budgets, savings goals, custom fields, and financial reports. +- Photograph receipts for expense capture and keep private metadata off-chain. +- Link a watch-only Stellar Testnet public address without sharing a secret seed. +- Create savings goals backed by the deployed Soroban savings vault. +- Prepare goal contributions, completions, withdrawals, and cancellations as unsigned XDR. +- Approve transactions in Freighter Mobile through WalletConnect v2. +- Review account activity, contract events, transaction state, and Stellar Expert proof. +- Use the REST API and Swagger UI to integrate or inspect backend operations. -7. Start the Expo app: +## 🌐 How SAVE Uses Stellar - ```bash - npm start - ``` +SAVE uses Stellar as an optional authorization and settlement-verification layer for goal-based saving. It does not place receipts, merchant details, category labels, profiles, or goal names on-chain. -## Environment files +| Stellar capability | How SAVE uses it | +| --- | --- | +| Wallets and signatures | The app stores a public address only. Freighter Mobile or another compatible external flow approves transaction signatures. | +| Horizon | The backend reads classic account and payment history and submits supported signed transactions. | +| Stellar RPC | The backend simulates Soroban calls, checks fees and transaction status, reads vault state, and indexes contract events. | +| Soroban | `save-savings-vault` holds approved Stellar Asset Contract tokens per goal and enforces lifecycle authorization. | +| Ledger verification | Prepared requests have deterministic hashes, and submitted transactions remain pending until network reconciliation reports success or failure. | -- Copy `backend/.env.example` to `backend/.env` and update values as needed. -- Copy `.env.example` to `.env` for the Expo app. WalletConnect values prefixed - with `EXPO_PUBLIC_` are public app configuration, not wallet secrets. -- The admin app can use its own local `.env.local` file for API URLs and secrets. +```mermaid +flowchart LR + App[SAVE mobile app] -->|public address and intent| API[SAVE API] + API -->|unsigned XDR| App + App -->|approval request| Wallet[External wallet] + Wallet -->|signed transaction| Stellar[Stellar Testnet] + API --> Horizon[Horizon] + API --> RPC[Stellar RPC] + Horizon --> Stellar + RPC --> Stellar + API --> Data[(MongoDB)] +``` -## Stack summary +The browser or mobile client cannot declare a transaction successful. SAVE reconciles network evidence before it updates the final transaction state. -- Mobile: React Native + Expo -- Language: TypeScript -- Navigation: Expo Router -- State management: Zustand + TanStack Query -- Local storage: SQLite + SecureStore + FileSystem + Camera -- Backend: NestJS + MongoDB + Redis + BullMQ -- Object storage: MinIO / S3-compatible storage -- Web/admin: Next.js dashboard for operations and analytics +## 💡 Design Principles -## Stellar Testnet and Soroban +- **Non-custodial by design:** secret seeds are never generated, accepted, transmitted, logged, or stored by SAVE. +- **Private data stays private:** sensitive personal-finance records remain in the application data layer, not on the public ledger. +- **Network evidence over client trust:** wallet responses and callbacks are validated; final state comes from Horizon or Stellar RPC. +- **Exact amounts:** classic payments use validated decimal strings, while Soroban amounts are converted to atomic integer units. +- **Explicit release boundaries:** Testnet features, production requirements, and deliberate non-goals are documented separately. -SAVE uses a non-custodial architecture: the mobile app links a public Testnet address, the backend reads Horizon/RPC data and prepares unsigned XDR, and a compatible external wallet approves signatures. Secret seeds are never accepted by the API. +## 👥 Who SAVE Is For -- Mobile route: `/stellar` -- Backend endpoints: `/stellar/network`, `/stellar/accounts`, `/stellar/payments`, `/stellar/vault`, `/stellar/transactions` -- Contract source: `contract/savings-vault` -- Contract specification and deployment: `docs/CONTRACT.md` +- People who want one mobile workspace for spending, budgets, and savings goals. +- Testnet users exploring non-custodial, goal-based saving with Soroban. +- Developers evaluating a React Native, NestJS, and Stellar integration. +- Reviewers who need repeatable contract tests and public ledger evidence. -Run `npm run contract:test` and `npm run contract:build` before deployment. Actual Testnet deployment requires an operator-owned funded Stellar CLI identity and setting `STELLAR_VAULT_CONTRACT_ID` in `backend/.env`. +## 🔗 Current Testnet Contracts -### Freighter Mobile signing +| Contract | Address | Explorer | +| --- | --- | --- | +| SAVE Savings Vault | `CALFEOYNTNJYB5HTUPYHHFHMNNYLYEBOCV43Z73J54G3CQNSH5VCNP7H` | [View on Stellar Expert](https://stellar.expert/explorer/testnet/contract/CALFEOYNTNJYB5HTUPYHHFHMNNYLYEBOCV43Z73J54G3CQNSH5VCNP7H) | +| Native XLM SAC | `CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC` | [View on Stellar Expert](https://stellar.expert/explorer/testnet/contract/CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC) | -The app uses WalletConnect v2 to request `stellar_signXDR` approval from -Freighter Mobile. SEP-7 and copied unsigned XDR remain available as manual -fallbacks. +These are public Testnet identifiers, not credentials. Deployments may be replaced as SAVE evolves; update the backend environment and contract documentation together after any redeployment. -1. Create a dApp project at the [WalletConnect dashboard](https://dashboard.walletconnect.com/). -2. Copy `.env.example` to `.env` and set: +## 🛠️ Tech Stack - ```dotenv - EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID=your_public_project_id - # Optional until SAVE has a public website: - EXPO_PUBLIC_WALLETCONNECT_METADATA_URL= - ``` +- **Mobile:** Expo SDK 57, React Native 0.86, React 19, TypeScript, and Expo Router. +- **Client data:** Zustand, TanStack Query, SQLite, SecureStore, and AsyncStorage. +- **Device features:** Expo Camera, FileSystem, Local Authentication, and native development builds. +- **Backend:** NestJS 11, MongoDB/Mongoose, Redis, BullMQ, and Swagger/OpenAPI. +- **Stellar:** `@stellar/stellar-sdk`, Horizon, Stellar RPC, WalletConnect v2, and Freighter Mobile. +- **Smart contract:** Rust, Soroban SDK, Stellar CLI, and the SAVE Savings Vault. +- **Admin:** Next.js 16 and React 19. +- **Local infrastructure:** Docker Compose, MongoDB, Redis, and MinIO-compatible object storage. - When omitted, the app uses the SAVE GitHub repository as temporary metadata. - For production, set this to a public HTTPS page identifying the app and add - the same origin to the WalletConnect project allowlist when enabled. +## 🚀 Run SAVE Locally -3. Install Freighter Mobile, import or create a dedicated **Testnet-only** - account, and switch Freighter to Testnet. Never enter its secret seed in - SAVE or the backend. -4. Fully restart Metro after changing `.env`: +### Prerequisites - ```bash - npx expo start -c - ``` +- Node.js LTS and npm. +- Docker with Docker Compose. +- Android Studio or Xcode for a native development build. +- Rust and the Stellar CLI for contract development. +- A funded Stellar Testnet account and Freighter Mobile for the complete signing flow. +- A public WalletConnect project ID. -5. Open **More → Stellar Testnet → Connect Freighter Mobile**. Approve the - WalletConnect session, create a savings goal, then fund it. Freighter shows - the XDR approval; SAVE submits the signed XDR and displays the ledger - confirmation and updated goal balance. +### 1. Install dependencies -For native testing, use an Expo development build (`npm run android` or an EAS -development build). Keep the backend reachable from the phone and point the -app's API URL at the computer's LAN address rather than `localhost`. +From the repository root: + +```bash +npm install +npm --prefix backend install +npm --prefix admin install +``` + +### 2. Configure the environments + +```bash +cp .env.example .env +cp backend/.env.example backend/.env +``` + +Set `EXPO_PUBLIC_API_URL` to a backend URL reachable by the phone, such as `http://192.168.1.25:3000`. Add your public `EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID`; values prefixed with `EXPO_PUBLIC_` are bundled into the client and must never contain secrets. + +Review the local MongoDB, Redis, MinIO, JWT, Stellar Testnet, callback, and contract settings in `backend/.env` before starting the API. The admin app can use `admin/.env.local` for its own API configuration. + +### 3. Start local services + +```bash +docker compose up -d +``` + +This starts MongoDB on `27017`, Redis on `6379`, MinIO on `9000`, and the MinIO console on `9001`. + +### 4. Start the applications + +Run each process in a separate terminal from the repository root: + +```bash +npm --prefix backend run start:dev +npm --prefix admin run dev +npm start +``` + +The API listens on `http://localhost:3000`, with Swagger UI at `http://localhost:3000/docs`. The admin dashboard uses the URL printed by Next.js, normally `http://localhost:3001` when the API already occupies port `3000`. + +### 5. Use a native development build + +SAVE includes native integrations and `expo-dev-client`, so use a development build for complete device testing: + +```bash +npm run android +# or, on macOS +npm run ios +``` + +After changing `.env`, restart the development server with a clean Metro cache: + +```bash +npx expo start -c +``` + +In the app, open **More → Stellar Testnet → Connect Freighter Mobile**. Use a dedicated Testnet-only wallet, approve the WalletConnect session, create a goal, and approve the prepared XDR in Freighter. Never enter a secret seed in SAVE or the backend. + +## 🧪 Test and Validate + +Run the application checks from the repository root: + +```bash +npm run lint +npx tsc --noEmit +npm --prefix backend test +npm run admin:build +``` + +Run the Soroban contract suite and build its Wasm artifact: + +```bash +npm run contract:test +npm run contract:build +``` + +The contract artifact is written to `contract/target/wasm32v1-none/release/save_savings_vault.wasm`. See the [test report](docs/DELIVERABLES_1_2_TEST_REPORT.md) for repeatable runtime checks and existing Testnet evidence. + +## 🚢 Deploy the Savings Vault + +Contract deployment is an explicit operator action. Use a funded Stellar CLI identity—never put its secret key in a command, environment file, application, or repository. + +Read the [contract deployment guide](docs/CONTRACT.md) before deploying. It documents the build artifact, current Wasm hash, deployment command, configuration update, and pre-Mainnet security requirements. + +> [!CAUTION] +> A working Testnet deployment is not evidence of Mainnet readiness. Independent review, stronger invariant testing, recovery procedures, key custody, asset allowlists, operational controls, and legal review are required before real-value use. + +## 📦 Repository Map + +```text +. +├── src/ # Expo Router mobile application +├── assets/ # App icons and image assets +├── android/ # Native Android project +├── ios/ # Native iOS project +├── backend/ # NestJS API, persistence, and Stellar integration +├── admin/ # Next.js operations dashboard +├── contract/ # Soroban workspace and savings-vault contract +├── docs/ # Architecture, contract, and verification evidence +├── scripts/ # Project utility scripts +├── docker-compose.yml # MongoDB, Redis, and MinIO services +└── eas.json # Expo Application Services build profiles +``` + +## 📚 Documentation + +- [Stellar architecture](docs/STELLAR_ARCHITECTURE.md) — network decisions, trust boundaries, reconciliation, and non-goals. +- [Savings vault contract](docs/CONTRACT.md) — interface, events, deployment, and security review. +- [Deliverables 1–2 test report](docs/DELIVERABLES_1_2_TEST_REPORT.md) — acceptance evidence and repeatable verification. +- [Combined Stellar implementation](docs/COMBINED_SOROBAN_STELLAR_IMPLEMENTATION.md) — implementation context across the app, API, and contract. + +## ⚠️ Alpha Boundaries + +Before evaluating SAVE, keep these constraints in view: + +- Blockchain flows target Stellar Testnet only. +- Wallet linking is watch-only; SAVE does not provide custody or recovery. +- Native XLM through its Testnet Stellar Asset Contract is the currently approved vault asset. +- Mainnet, fiat ramps, yield, stablecoin trustlines, anchors/KYC, DeFi, rewards, sponsored fees, shared vaults, and smart-wallet recovery are not enabled. +- A phone must be able to reach the backend and its wallet callback URL during end-to-end testing. +- Offline or client-reported data is never represented as ledger-final. +- Testnet assets have no real-world value, and the software has not completed a production security audit. + +## 🤝 Contributing + +Keep changes focused, preserve the non-custodial and off-chain privacy boundaries, and add tests beside behavior changes. Before opening a pull request, run the relevant mobile, backend, admin, and contract checks. Include screenshots for visible interface changes and update the associated architecture or contract document when a trust boundary changes. + +## 📄 License + +This repository includes an [MIT license](LICENSE). diff --git a/backend/.env.example b/backend/.env.example index 2e49c92..eb3875c 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -19,9 +19,10 @@ STELLAR_RPC_URL=https://soroban-testnet.stellar.org STELLAR_FRIENDBOT_URL=https://friendbot.stellar.org STELLAR_VAULT_CONTRACT_ID=CALFEOYNTNJYB5HTUPYHHFHMNNYLYEBOCV43Z73J54G3CQNSH5VCNP7H STELLAR_XLM_SAC_ID=CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC -STELLAR_MAX_SOROBAN_FEE=2000000 +# Maximum assembled Soroban fee in stroops (1000000000 = 100 XLM). +STELLAR_MAX_SOROBAN_FEE=1000000000 STELLAR_EVENT_POLL_MS=15000 STELLAR_CALLBACK_BASE_URL=http://localhost:3000 STELLAR_ORIGIN_DOMAIN= STELLAR_INTEGRITY_SIGNER_SECRET_FILE= -EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID=219c5a0dcc9ced2856f12d0df4a2d484 \ No newline at end of file +EXPO_PUBLIC_WALLETCONNECT_PROJECT_ID=219c5a0dcc9ced2856f12d0df4a2d484 diff --git a/backend/src/savings/savings-goal.schema.ts b/backend/src/savings/savings-goal.schema.ts index dd07402..ea0fb8e 100644 --- a/backend/src/savings/savings-goal.schema.ts +++ b/backend/src/savings/savings-goal.schema.ts @@ -3,7 +3,7 @@ import { Document } from 'mongoose'; export type SavingsGoalDocument = SavingsGoal & Document; -export type SavingsGoalStatus = 'draft' | 'pending' | 'active' | 'completed' | 'withdrawn'; +export type SavingsGoalStatus = 'draft' | 'pending' | 'active' | 'completed' | 'withdrawn' | 'cancelled'; @Schema({ timestamps: true }) export class SavingsGoal { @@ -24,7 +24,7 @@ export class SavingsGoal { @Prop({ required: true, - enum: ['draft', 'pending', 'active', 'completed', 'withdrawn'], + enum: ['draft', 'pending', 'active', 'completed', 'withdrawn', 'cancelled'], default: 'draft', }) status: SavingsGoalStatus; @@ -38,6 +38,9 @@ export class SavingsGoal { @Prop({ trim: true }) contractId?: string; + @Prop({ trim: true }) + vaultGoalId?: string; + @Prop({ trim: true }) transactionHash?: string; } diff --git a/backend/src/savings/savings.dto.ts b/backend/src/savings/savings.dto.ts index 53ffa9d..1306466 100644 --- a/backend/src/savings/savings.dto.ts +++ b/backend/src/savings/savings.dto.ts @@ -5,6 +5,7 @@ import { IsOptional, IsPositive, IsString, + Matches, Min, } from 'class-validator'; import { SavingsGoalStatus } from './savings-goal.schema'; @@ -32,7 +33,7 @@ export class CreateSavingsGoalDto { asset?: string; @IsOptional() - @IsEnum(['draft', 'pending', 'active', 'completed', 'withdrawn']) + @IsEnum(['draft', 'pending', 'active', 'completed', 'withdrawn', 'cancelled']) status?: SavingsGoalStatus; @IsOptional() @@ -47,6 +48,11 @@ export class CreateSavingsGoalDto { @IsString() contractId?: string; + @IsOptional() + @IsString() + @Matches(/^\d+$/) + vaultGoalId?: string; + @IsOptional() @IsString() transactionHash?: string; @@ -77,7 +83,7 @@ export class UpdateSavingsGoalDto { asset?: string; @IsOptional() - @IsEnum(['draft', 'pending', 'active', 'completed', 'withdrawn']) + @IsEnum(['draft', 'pending', 'active', 'completed', 'withdrawn', 'cancelled']) status?: SavingsGoalStatus; @IsOptional() @@ -92,6 +98,11 @@ export class UpdateSavingsGoalDto { @IsString() contractId?: string; + @IsOptional() + @IsString() + @Matches(/^\d+$/) + vaultGoalId?: string; + @IsOptional() @IsString() transactionHash?: string; diff --git a/backend/src/savings/savings.service.ts b/backend/src/savings/savings.service.ts index a8d37fe..1f554a2 100644 --- a/backend/src/savings/savings.service.ts +++ b/backend/src/savings/savings.service.ts @@ -17,6 +17,7 @@ export type SavingsGoalResponse = { network?: string; ownerAddress?: string; contractId?: string; + vaultGoalId?: string; transactionHash?: string; }; @@ -32,6 +33,7 @@ function toSavingsGoalResponse(doc: any): SavingsGoalResponse { network: doc.network ?? 'testnet', ownerAddress: doc.ownerAddress, contractId: doc.contractId, + vaultGoalId: doc.vaultGoalId, transactionHash: doc.transactionHash, }; } @@ -104,6 +106,7 @@ export class SavingsService implements OnModuleInit { network: dto.network ?? 'testnet', ownerAddress: dto.ownerAddress, contractId: dto.contractId, + vaultGoalId: dto.vaultGoalId, transactionHash: dto.transactionHash, }); const saved = await goal.save(); @@ -120,6 +123,7 @@ export class SavingsService implements OnModuleInit { network: dto.network ?? 'testnet', ownerAddress: dto.ownerAddress, contractId: dto.contractId, + vaultGoalId: dto.vaultGoalId, transactionHash: dto.transactionHash, }; this.inMemoryGoals.unshift(fallback); diff --git a/backend/src/stellar/stellar.dto.ts b/backend/src/stellar/stellar.dto.ts index c7b5550..cd07e90 100644 --- a/backend/src/stellar/stellar.dto.ts +++ b/backend/src/stellar/stellar.dto.ts @@ -56,6 +56,11 @@ export class PrepareVaultInvocationDto { @Matches(/^\d+$/) goalId?: string; + @IsOptional() + @IsString() + @IsNotEmpty() + savingsGoalId?: string; + @IsOptional() @IsString() @Matches(/^\d+$/) diff --git a/backend/src/stellar/stellar.module.ts b/backend/src/stellar/stellar.module.ts index f63d983..7504e99 100644 --- a/backend/src/stellar/stellar.module.ts +++ b/backend/src/stellar/stellar.module.ts @@ -4,13 +4,17 @@ import { MongooseModule } from '@nestjs/mongoose'; import { StellarController, StellarTomlController } from './stellar.controller'; import { StellarService } from './stellar.service'; import { StellarAccount, StellarAccountSchema, StellarContractEvent, StellarContractEventSchema, StellarSigningRequest, StellarSigningRequestSchema } from './stellar.schema'; +import { SavingsModule } from '../savings/savings.module'; @Module({ - imports: [MongooseModule.forFeature([ - { name: StellarAccount.name, schema: StellarAccountSchema }, - { name: StellarSigningRequest.name, schema: StellarSigningRequestSchema }, - { name: StellarContractEvent.name, schema: StellarContractEventSchema }, - ])], + imports: [ + SavingsModule, + MongooseModule.forFeature([ + { name: StellarAccount.name, schema: StellarAccountSchema }, + { name: StellarSigningRequest.name, schema: StellarSigningRequestSchema }, + { name: StellarContractEvent.name, schema: StellarContractEventSchema }, + ]), + ], controllers: [StellarController, StellarTomlController], providers: [StellarService], exports: [StellarService], diff --git a/backend/src/stellar/stellar.schema.ts b/backend/src/stellar/stellar.schema.ts index db105d0..5f433ec 100644 --- a/backend/src/stellar/stellar.schema.ts +++ b/backend/src/stellar/stellar.schema.ts @@ -21,6 +21,8 @@ export class StellarSigningRequest { @Prop({ required: true, enum: ['prepared', 'submitted', 'pending', 'success', 'failed'], index: true }) status: string; @Prop({ index: true }) hash?: string; @Prop() fee?: string; + @Prop({ index: true }) savingsGoalId?: string; + @Prop() goalId?: string; @Prop() error?: string; } export type StellarSigningRequestDocument = HydratedDocument; diff --git a/backend/src/stellar/stellar.service.ts b/backend/src/stellar/stellar.service.ts index f142b09..4d83bdd 100644 --- a/backend/src/stellar/stellar.service.ts +++ b/backend/src/stellar/stellar.service.ts @@ -22,6 +22,7 @@ import { import { LinkStellarAccountDto, PreparePaymentDto, PrepareVaultInvocationDto, StellarEventsQueryDto, SubmitStellarTransactionDto } from './stellar.dto'; import { assertMatchingSignedTransaction, buildSep7SigningUrl, loadIntegritySigner, transactionHash } from './stellar.sep7'; import { StellarAccount, StellarAccountDocument, StellarContractEvent, StellarContractEventDocument, StellarSigningRequest, StellarSigningRequestDocument } from './stellar.schema'; +import { SavingsService } from '../savings/savings.service'; type SigningRequest = { idempotencyKey: string; @@ -32,6 +33,8 @@ type SigningRequest = { status: 'prepared' | 'submitted' | 'pending' | 'success' | 'failed'; hash: string; fee?: string; + savingsGoalId?: string; + goalId?: string; error?: string; createdAt: string; }; @@ -53,7 +56,7 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { private readonly networkPassphrase: string; private readonly vaultContractId?: string; private readonly xlmSacId: string; - private readonly maxSorobanFee: number; + private readonly maxSorobanFee: bigint; private readonly callbackBaseUrl?: string; private readonly originDomain?: string; private readonly integritySigner?: Keypair; @@ -70,13 +73,18 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { @InjectModel(StellarAccount.name) private readonly accountModel: Model, @InjectModel(StellarSigningRequest.name) private readonly signingRequestModel: Model, @InjectModel(StellarContractEvent.name) private readonly eventModel: Model, + private readonly savingsService: SavingsService, ) { this.horizonUrl = config.get('STELLAR_HORIZON_URL') ?? 'https://horizon-testnet.stellar.org'; this.rpcUrl = config.get('STELLAR_RPC_URL') ?? 'https://soroban-testnet.stellar.org'; this.networkPassphrase = config.get('STELLAR_NETWORK_PASSPHRASE') ?? Networks.TESTNET; this.vaultContractId = config.get('STELLAR_VAULT_CONTRACT_ID'); this.xlmSacId = config.get('STELLAR_XLM_SAC_ID') ?? Asset.native().contractId(this.networkPassphrase); - this.maxSorobanFee = Number(config.get('STELLAR_MAX_SOROBAN_FEE') ?? 2_000_000); + const configuredMaxSorobanFee = String(config.get('STELLAR_MAX_SOROBAN_FEE') ?? '1000000000').trim(); + if (!/^\d+$/.test(configuredMaxSorobanFee) || BigInt(configuredMaxSorobanFee) <= 0n) { + throw new Error('STELLAR_MAX_SOROBAN_FEE must be a positive integer in stroops'); + } + this.maxSorobanFee = BigInt(configuredMaxSorobanFee); this.eventPollMs = Math.max(Number(config.get('STELLAR_EVENT_POLL_MS') ?? 15_000), 5_000); this.callbackBaseUrl = config.get('STELLAR_CALLBACK_BASE_URL')?.replace(/\/+$/, ''); this.originDomain = config.get('STELLAR_ORIGIN_DOMAIN')?.trim() || undefined; @@ -212,8 +220,21 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { const operation = contract.call(dto.action, ...this.vaultArguments(dto)); const raw = new TransactionBuilder(source, { fee: BASE_FEE, networkPassphrase: this.networkPassphrase }).addOperation(operation).setTimeout(180).build(); const prepared = await this.rpc.prepareTransaction(raw); - if (Number(prepared.fee) > this.maxSorobanFee) throw new BadRequestException(`Simulated fee ${prepared.fee} exceeds configured bound ${this.maxSorobanFee}`); - return this.recordSigningRequest(dto.idempotencyKey, 'soroban', dto.action, dto.source, prepared.toXDR(), prepared.fee); + const simulatedFee = BigInt(prepared.fee); + if (simulatedFee > this.maxSorobanFee) { + throw new BadRequestException( + `Simulated fee ${prepared.fee} stroops exceeds configured maximum ${this.maxSorobanFee.toString()} stroops`, + ); + } + return this.recordSigningRequest( + dto.idempotencyKey, + 'soroban', + dto.action, + dto.source, + prepared.toXDR(), + prepared.fee, + { savingsGoalId: dto.savingsGoalId, goalId: dto.goalId }, + ); } catch (error) { if (error instanceof BadRequestException) throw error; throw new ServiceUnavailableException(`Unable to simulate vault invocation: ${error instanceof Error ? error.message : 'RPC error'}`); @@ -357,6 +378,7 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { source: string, unsignedXdr: string, fee = BASE_FEE, + linkedGoal: Pick = {}, ) { const request: SigningRequest = { idempotencyKey, @@ -367,6 +389,8 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { status: 'prepared', hash: transactionHash(unsignedXdr, this.networkPassphrase), fee: String(fee), + savingsGoalId: linkedGoal.savingsGoalId, + goalId: linkedGoal.goalId, createdAt: new Date().toISOString(), }; this.signingRequests.set(idempotencyKey, request); @@ -409,6 +433,8 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { status: persisted.status as SigningRequest['status'], hash: persisted.hash, fee: persisted.fee, + savingsGoalId: persisted.savingsGoalId, + goalId: persisted.goalId, error: persisted.error, createdAt: ((persisted as unknown as { createdAt?: Date }).createdAt ?? new Date()).toISOString(), }; @@ -425,7 +451,11 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { request.error = result.successful ? undefined : 'Transaction failed on Stellar Testnet'; } else { const result = await this.rpc.getTransaction(request.hash); - if (result.status === 'SUCCESS') { request.status = 'success'; request.error = undefined; } + if (result.status === 'SUCCESS') { + request.status = 'success'; + request.error = undefined; + await this.syncLinkedSavingsGoal(request, result.returnValue); + } else if (result.status === 'FAILED') { request.status = 'failed'; request.error = 'Soroban transaction failed on Stellar Testnet'; } else if (result.status === 'NOT_FOUND' && Date.now() - Date.parse(request.createdAt) > 180_000) { request.status = 'failed'; request.error = 'Wallet approval expired. Prepare a fresh request and retry.'; @@ -438,7 +468,45 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { request.status = 'failed'; request.error = 'Wallet approval expired. Prepare a fresh request and retry.'; } } - await this.persistRequestUpdate(request.idempotencyKey, request.status, request.hash, request.error); + await this.persistRequestUpdate(request.idempotencyKey, request.status, request.hash, request.error, request.goalId); + } + + private async syncLinkedSavingsGoal(request: SigningRequest, returnValue?: unknown) { + if (!request.savingsGoalId) return; + try { + if (request.action === 'create_goal' && returnValue) { + request.goalId = String(scValToNative(returnValue as Parameters[0])); + } + if (!request.goalId) return; + + const response = await this.rpc.queryContract>( + this.requireVaultContract(), + 'get_goal', + { goal_id: BigInt(request.goalId) }, + this.networkPassphrase, + ); + const goal = this.presentGoal(response.result); + const balance = Number(BigInt(goal.balance)) / 10_000_000; + const status = goal.status === 'Cancelled' + ? 'cancelled' + : goal.status === 'Completed' && BigInt(goal.balance) === 0n + ? 'withdrawn' + : goal.status === 'Completed' + ? 'completed' + : 'active'; + await this.savingsService.update(request.savingsGoalId, { + fundedAmount: balance, + status, + network: 'testnet', + ownerAddress: goal.owner, + contractId: this.requireVaultContract(), + vaultGoalId: request.goalId, + transactionHash: request.hash, + }); + } catch { + // The confirmed on-chain transaction remains authoritative. A later + // refresh can retry tracker reconciliation without affecting funds. + } } private assertAccount(address: string) { @@ -450,10 +518,10 @@ export class StellarService implements OnModuleInit, OnModuleDestroy { return this.vaultContractId; } - private async persistRequestUpdate(idempotencyKey: string, status: SigningRequest['status'], hash: string, error?: string) { + private async persistRequestUpdate(idempotencyKey: string, status: SigningRequest['status'], hash: string, error?: string, goalId?: string) { await this.signingRequestModel.updateOne( { idempotencyKey }, - { $set: { status, hash, error: error ?? null } }, + { $set: { status, hash, error: error ?? null, ...(goalId ? { goalId } : {}) } }, ).catch(() => undefined); } } diff --git a/src/app/(tabs)/savings.tsx b/src/app/(tabs)/savings.tsx index 8548bab..8e2dd18 100644 --- a/src/app/(tabs)/savings.tsx +++ b/src/app/(tabs)/savings.tsx @@ -118,7 +118,19 @@ export default function SavingsScreen() { Math.round(((goal.fundedAmount || 0) / Math.max(goal.targetAmount, 1)) * 100), 100, ); - const hasOnChainProof = Boolean(goal.contractId && goal.transactionHash); + const hasOnChainGoal = Boolean(goal.contractId && goal.vaultGoalId); + const hasOnChainProof = Boolean(hasOnChainGoal && goal.transactionHash); + const canFundOnChain = hasOnChainGoal && goal.status !== 'cancelled' && goal.status !== 'withdrawn'; + const openVaultGoal = () => router.push({ + pathname: '/stellar', + params: { + savingsGoalId: goal.id, + goalName: goal.name, + targetAmount: String(goal.targetAmount), + targetDate: goal.targetDate, + vaultGoalId: canFundOnChain ? goal.vaultGoalId : undefined, + }, + }); return ( @@ -177,35 +189,29 @@ export default function SavingsScreen() { ? localStyles.fundingVerifiedTitle : localStyles.fundingDraftTitle }> - {hasOnChainProof ? '✓ Funding verified on Stellar' : 'Tracker only · no funds held'} + {hasOnChainGoal ? '✓ Linked to a specific Stellar vault goal' : 'Tracker only · no funds held'} - {hasOnChainProof - ? 'This amount has an on-chain transaction proof.' - : 'Saving this draft does not transfer XLM. Use the Stellar vault to fund a real goal.'} + {hasOnChainGoal + ? `Vault Goal #${goal.vaultGoalId} · ${goal.fundedAmount.toLocaleString('en-US')} ${goal.asset} verified on-chain.` + : 'Saving this tracker does not transfer XLM. Create its dedicated Stellar vault goal first.'} { - if (hasOnChainProof && goal.transactionHash) { - void Linking.openURL( - `https://stellar.expert/explorer/testnet/tx/${goal.transactionHash}`, - ); - } else { - router.push('/stellar'); - } - }}> - - {hasOnChainProof ? 'View Transaction Proof' : 'Open Stellar Vault to Fund'} + style={localStyles.fundButton} + onPress={openVaultGoal}> + + {canFundOnChain ? `Fund Vault Goal #${goal.vaultGoalId}` : hasOnChainGoal ? 'Create Replacement Vault Goal' : 'Create Dedicated Vault Goal'} + {hasOnChainProof && goal.transactionHash ? ( + void Linking.openURL(`https://stellar.expert/explorer/testnet/tx/${goal.transactionHash}`)}> + View Latest Transaction Proof + + ) : null}
); })} diff --git a/src/app/stellar.tsx b/src/app/stellar.tsx index bb4fe4b..676100e 100644 --- a/src/app/stellar.tsx +++ b/src/app/stellar.tsx @@ -1,10 +1,11 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import * as Clipboard from 'expo-clipboard'; +import { useLocalSearchParams } from 'expo-router'; import { Alert, AppState, Linking, Platform, Pressable, StyleSheet, Text, TextInput, View } from 'react-native'; import { FinancePage } from '@/components/layout/finance-page'; import { - fetchStellarNetwork, fetchStellarPayments, fetchStellarSigningRequest, fetchVaultGoals, + fetchSavingsGoal, fetchStellarNetwork, fetchStellarPayments, fetchStellarSigningRequest, fetchVaultGoals, linkStellarAccount, prepareVaultInvocation, submitStellarTransaction, type StellarNetworkStatus, type StellarPortfolio, type StellarSigningRequest, type StellarVaultEvent, type StellarVaultGoal, type StellarVaultGoalsResponse, } from '@/lib/api'; @@ -21,6 +22,7 @@ import { const ACCOUNT_KEY = 'save.stellar.testnet.account'; const STROOPS_PER_XLM = 10_000_000n; const newIdempotencyKey = (action: string) => `${action}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`; +const routeValue = (value: string | string[] | undefined) => Array.isArray(value) ? value[0] : value; const saveAccount = async (address: string) => { if (Platform.OS === 'web') { if (typeof window !== 'undefined') window.localStorage.setItem(ACCOUNT_KEY, address); return; } @@ -61,13 +63,24 @@ const fundingStatusCopy = (status: StellarSigningRequest['status']) => { type VaultIntent = Omit[0], 'idempotencyKey'>; export default function StellarScreen() { + const route = useLocalSearchParams<{ + savingsGoalId?: string; + goalName?: string; + targetAmount?: string; + targetDate?: string; + vaultGoalId?: string; + }>(); + const savingsGoalId = routeValue(route.savingsGoalId); + const routedVaultGoalId = routeValue(route.vaultGoalId); const [network, setNetwork] = useState(null); const [portfolio, setPortfolio] = useState(null); const [vault, setVault] = useState(null); const [payments, setPayments] = useState>>([]); const [address, setAddress] = useState(''); - const [targetXlm, setTargetXlm] = useState('1'); - const [targetDate, setTargetDate] = useState(''); + const [targetXlm, setTargetXlm] = useState(routeValue(route.targetAmount) ?? '1'); + const [targetDate, setTargetDate] = useState(routeValue(route.targetDate) ?? ''); + const [linkedGoalName, setLinkedGoalName] = useState(routeValue(route.goalName) ?? ''); + const [focusedVaultGoalId, setFocusedVaultGoalId] = useState(routedVaultGoalId); const [contributions, setContributions] = useState>({}); const [withdrawals, setWithdrawals] = useState>({}); const [request, setRequest] = useState(null); @@ -78,6 +91,11 @@ export default function StellarScreen() { const [busy, setBusy] = useState(null); const [message, setMessage] = useState(null); const walletConfig = useMemo(() => walletConnectConfiguration(), []); + const orderedVaultGoals = useMemo(() => { + const goals = vault?.goals ?? []; + if (!focusedVaultGoalId) return goals; + return [...goals].sort((left, right) => Number(right.id === focusedVaultGoalId) - Number(left.id === focusedVaultGoalId)); + }, [focusedVaultGoalId, vault]); const loadVault = useCallback(async (owner: string) => { const result = await fetchVaultGoals(owner); setVault(result); return result; }, []); const connect = useCallback(async (nextAddress: string) => { @@ -108,6 +126,7 @@ export default function StellarScreen() { try { const updated = await fetchStellarSigningRequest(request.idempotencyKey); setRequest(updated); if (updated.status === 'success' && portfolio) { + if (updated.goalId) setFocusedVaultGoalId(updated.goalId); const [linked, activity] = await Promise.all([linkStellarAccount(portfolio.address), fetchStellarPayments(portfolio.address), loadVault(portfolio.address)]); setPortfolio(linked); setPayments(activity); setMessage(`${updated.action.replaceAll('_', ' ')} confirmed on Stellar Testnet.`); } @@ -124,6 +143,25 @@ export default function StellarScreen() { }) .catch((error) => setMessage(error instanceof Error ? error.message : 'Unable to restore wallet session.')); }, [connect]); + useEffect(() => { + if (!savingsGoalId) return; + let active = true; + void fetchSavingsGoal(savingsGoalId) + .then((goal) => { + if (!active) return; + if (goal.asset !== 'XLM') throw new Error('The Stellar vault currently supports XLM savings goals only.'); + setLinkedGoalName(goal.name); + setTargetXlm(String(goal.targetAmount)); + setTargetDate(goal.targetDate ?? ''); + if (goal.vaultGoalId && goal.status !== 'cancelled' && goal.status !== 'withdrawn') { + setFocusedVaultGoalId(goal.vaultGoalId); + } + }) + .catch((error) => { + if (active) setMessage(error instanceof Error ? error.message : 'Unable to load the selected savings goal.'); + }); + return () => { active = false; }; + }, [savingsGoalId]); useEffect(() => subscribeStellarWalletSession((reason) => { setWalletSession(null); setPairingUri(null); @@ -239,20 +277,21 @@ export default function StellarScreen() { try { const deadline = targetDate.trim() ? Math.floor(new Date(`${targetDate.trim()}T23:59:59Z`).getTime() / 1000) : undefined; if (deadline !== undefined && (!Number.isFinite(deadline) || deadline <= Date.now() / 1000)) throw new Error('Target date must be a future YYYY-MM-DD date.'); - await prepareIntent({ source: portfolio.address, owner: portfolio.address, action: 'create_goal', assetContractId: network.xlmSacId, targetAmount: xlmToAtomic(targetXlm), targetDate: deadline?.toString() }); + await prepareIntent({ source: portfolio.address, owner: portfolio.address, action: 'create_goal', assetContractId: network.xlmSacId, targetAmount: xlmToAtomic(targetXlm), targetDate: deadline?.toString(), savingsGoalId }); } catch (error) { setMessage(error instanceof Error ? error.message : 'Invalid goal details.'); } }; const actOnGoal = async (goal: StellarVaultGoal, action: VaultIntent['action']) => { if (!portfolio) return; try { const amount = action === 'contribute' ? xlmToAtomic(contributions[goal.id] ?? '') : action === 'withdraw' ? xlmToAtomic(withdrawals[goal.id] ?? '') : undefined; - await prepareIntent({ source: portfolio.address, action, goalId: goal.id, contributor: action === 'contribute' ? portfolio.address : undefined, amount }); + await prepareIntent({ source: portfolio.address, action, goalId: goal.id, savingsGoalId: goal.id === focusedVaultGoalId ? savingsGoalId : undefined, contributor: action === 'contribute' ? portfolio.address : undefined, amount }); } catch (error) { setMessage(error instanceof Error ? error.message : 'Invalid transaction details.'); } }; const xlmBalance = useMemo(() => portfolio?.balances.find((balance) => balance.asset === 'XLM')?.balance ?? '0', [portfolio]); return Non-custodial Testnet flowSAVE prepares transactions and tracks their public proof. Your external wallet remains the only user-transaction signer. + {savingsGoalId ? SELECTED SAVINGS GOAL{linkedGoalName || 'Loading goal…'}{focusedVaultGoalId ? `Linked to Vault Goal #${focusedVaultGoalId}. Funding actions below apply to this exact goal.` : 'No active vault goal is linked yet. Create its dedicated on-chain goal below.'} : null} Network{network ? `LIVE · ledger ${network.latestLedger}` : 'UNAVAILABLE'} Stellar Testnet · Protocol {network?.protocolVersion ?? '—'} · Asset: XLM @@ -296,13 +335,13 @@ export default function StellarScreen() { {request.status === 'failed' && lastIntent ? void prepareIntent(lastIntent)}>Prepare Fresh Retry : null} : null} {portfolio ? Soroban goals void loadVault(portfolio.address)}>Refresh : null} - {vault?.goals.map((goal) => { + {orderedVaultGoals.map((goal) => { const target = BigInt(goal.targetAmount || '0'); const balance = BigInt(goal.balance || '0'); const progress = target > 0n ? Math.min(Number((balance * 10000n) / target) / 100, 100) : 0; - const goalEvents = vault.events.filter((item) => item.goalId === goal.id); + const goalEvents = (vault?.events ?? []).filter((item) => item.goalId === goal.id); const event = [...goalEvents].reverse().find((item) => item.successful); const contributionEvent = [...goalEvents].reverse().find((item) => item.successful && item.type.toLowerCase().includes('contribution')); - return setContributions((current) => ({ ...current, [goal.id]: value }))} onWithdrawalChange={(value) => setWithdrawals((current) => ({ ...current, [goal.id]: value }))} onAction={(action) => void actOnGoal(goal, action)} />; @@ -313,14 +352,14 @@ export default function StellarScreen() { ; } -function GoalCard(props: { goal: StellarVaultGoal; event?: StellarVaultEvent; contributionEvent?: StellarVaultEvent; ledgerVerified: boolean; progress: number; contribution: string; withdrawal: string; busy: string | null; onContributionChange: (value: string) => void; onWithdrawalChange: (value: string) => void; onAction: (action: VaultIntent['action']) => void }) { +function GoalCard(props: { goal: StellarVaultGoal; trackerName?: string; selected: boolean; event?: StellarVaultEvent; contributionEvent?: StellarVaultEvent; ledgerVerified: boolean; progress: number; contribution: string; withdrawal: string; busy: string | null; onContributionChange: (value: string) => void; onWithdrawalChange: (value: string) => void; onAction: (action: VaultIntent['action']) => void }) { const { goal, event, contributionEvent } = props; const balance = BigInt(goal.balance || '0'); const target = BigInt(goal.targetAmount || '0'); const fundingState = balance === 0n ? 'NOT FUNDED' : balance >= target ? 'TARGET REACHED' : 'PARTIALLY FUNDED'; const lastContribution = eventField(contributionEvent, 'amount'); - return - Goal #{goal.id}{goal.status} + return + {props.trackerName || `Goal #${goal.id}`}{props.trackerName ? Vault Goal #{goal.id} · selected tracker : null}{goal.status} {props.ledgerVerified ? '✓ LIVE SOROBAN BALANCE' : 'BALANCE UNVERIFIED'} 0n && styles.fundingBadgeActive]}>{fundingState} {atomicToXlm(goal.balance)} XLM funded @@ -340,6 +379,7 @@ const statusColor = (status: StellarSigningRequest['status']) => status === 'suc const confirmationBannerStyle = (status: StellarSigningRequest['status']) => status === 'success' ? styles.confirmationSuccess : status === 'failed' ? styles.confirmationFailed : status === 'prepared' ? styles.confirmationPrepared : styles.confirmationPending; const styles = StyleSheet.create({ card: { backgroundColor: '#0d1629', borderWidth: 1, borderColor: '#1c2941', borderRadius: 12, padding: 15, gap: 11 }, failedCard: { borderColor: '#6d2c3a' }, confirmedCard: { borderColor: '#226a57' }, + selectedGoalCard: { borderColor: '#5ca9ff', borderWidth: 2 }, selectedTracker: { backgroundColor: '#10233a', borderWidth: 1, borderColor: '#5ca9ff', borderRadius: 12, padding: 15, gap: 5 }, selectedTrackerLabel: { color: '#72b7ff', fontSize: 9, fontWeight: '900' }, selectedTrackerTitle: { color: '#f2f6fb', fontSize: 18, fontWeight: '900' }, notice: { backgroundColor: '#10233a', borderWidth: 1, borderColor: '#275382', borderRadius: 12, padding: 15 }, noticeTitle: { color: '#72b7ff', fontWeight: '800', marginBottom: 6 }, title: { color: '#f2f6fb', fontWeight: '800', fontSize: 14 }, sectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 2 }, sectionTitle: { color: '#f2f6fb', fontWeight: '800', fontSize: 17 }, help: { color: '#8d99ad', fontSize: 11, lineHeight: 17 }, row: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', gap: 10 }, actionRow: { flexDirection: 'row', gap: 9 }, diff --git a/src/lib/api.ts b/src/lib/api.ts index bc9171d..a2935bd 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -33,7 +33,7 @@ export type ApiCategory = { color: string; }; -export type ApiSavingsGoalStatus = 'draft' | 'pending' | 'active' | 'completed' | 'withdrawn'; +export type ApiSavingsGoalStatus = 'draft' | 'pending' | 'active' | 'completed' | 'withdrawn' | 'cancelled'; export type ApiSavingsGoal = { id: string; @@ -46,6 +46,7 @@ export type ApiSavingsGoal = { network?: string; ownerAddress?: string; contractId?: string; + vaultGoalId?: string; transactionHash?: string; }; @@ -89,6 +90,8 @@ export type StellarSigningRequest = { networkPassphrase: string; signingUrl: string; fee?: string; + savingsGoalId?: string; + goalId?: string; hash: string; source: string; error?: string; @@ -314,6 +317,7 @@ export function prepareVaultInvocation(payload: { contributor?: string; assetContractId?: string; goalId?: string; + savingsGoalId?: string; targetAmount?: string; targetDate?: string; amount?: string;