feat(onboarding): interactive welcome + nickname spotlight tour

Stage 1+2 des post-signup Onboarding-Flows:
- Welcome-Screen: dark-slate Full-Screen mit Pulse-Hero, 3 Mission-Bullets,
  DSGVO-Box, CTA "Los geht's"
- Nickname-Spotlight via react-native-copilot ums TextInput in /profile/edit,
  auto-start wenn step='nickname', nach Save → step='block' + back to /(app)
- Backend: Profile.onboardingStep enum (welcome/nickname/block/done),
  Migration mit Backfill (existing → done), PATCH /api/profile/me/onboarding-step,
  /api/auth/me erweitert
- Frontend: CopilotProvider in root, Routing-Gate in (app)/_layout, useMe um
  onboardingStep ergänzt
- i18n (de/en/fr) für onboarding.welcome.* + onboarding.nickname_spotlight.*

Stage 3 (Block-Aktivierung-Spotlight) folgt in nächster Session — der bestehende
ProtectionOnboardingSheet auf Android wird daran angebunden.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
chahinebrini 2026-05-16 21:00:20 +02:00
parent c1dd7e7320
commit 38a8517259
15 changed files with 1141 additions and 15 deletions

View File

@ -15,6 +15,7 @@ import { protection } from '../../lib/protection';
import { preloadTabIcons, getTabIcon } from '../../lib/tabIcons'; import { preloadTabIcons, getTabIcon } from '../../lib/tabIcons';
import { apiFetch } from '../../lib/api'; import { apiFetch } from '../../lib/api';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useMe } from '../../hooks/useMe';
const ONBOARDING_COMPLETED_KEY = '@rebreak/protection-onboarding-completed'; const ONBOARDING_COMPLETED_KEY = '@rebreak/protection-onboarding-completed';
@ -96,6 +97,21 @@ export default function AppLayout() {
} }
}, [session, loading]); }, [session, loading]);
// Onboarding-Routing-Gate (resume-on-relaunch via DB-State)
// Wird nur ausgewertet wenn das Profile geladen ist — bei `me=null` warten wir.
// Welcome → /onboarding/welcome (Stage 1)
// Nickname → /profile/edit (Stage 2, Spotlight startet dort)
// Block/Done → keine Umleitung, normale App
const { me } = useMe();
useEffect(() => {
if (!session || !me) return;
if (me.onboardingStep === 'welcome') {
router.replace('/onboarding/welcome');
} else if (me.onboardingStep === 'nickname') {
router.replace('/profile/edit');
}
}, [session, me?.onboardingStep]);
useEffect(() => { useEffect(() => {
if (!session) { if (!session) {
resetNotifications(); resetNotifications();

View File

@ -17,6 +17,8 @@ import {
Nunito_800ExtraBold, Nunito_800ExtraBold,
} from '@expo-google-fonts/nunito'; } from '@expo-google-fonts/nunito';
import { supabase } from '../lib/supabase'; import { supabase } from '../lib/supabase';
import { CopilotProvider } from 'react-native-copilot';
import { useTranslation } from 'react-i18next';
import { useAuthStore } from '../stores/auth'; import { useAuthStore } from '../stores/auth';
import { useThemeStore } from '../stores/theme'; import { useThemeStore } from '../stores/theme';
import { useRealtimeDebugStore } from '../stores/realtimeDebug'; import { useRealtimeDebugStore } from '../stores/realtimeDebug';
@ -184,11 +186,42 @@ function RootLayoutInner() {
animation: 'slide_from_right', animation: 'slide_from_right',
}} }}
/> />
<Stack.Screen
name="onboarding/welcome"
options={{
headerShown: false,
presentation: 'card',
animation: 'fade',
gestureEnabled: false,
}}
/>
</Stack> </Stack>
</AppLockGate> </AppLockGate>
); );
} }
function CopilotShell({ children }: { children: React.ReactNode }) {
const { t } = useTranslation();
return (
<CopilotProvider
overlay="svg"
animated
backdropColor="rgba(15, 23, 42, 0.78)"
arrowColor="#1c1c1e"
stopOnOutsideClick={false}
margin={8}
labels={{
skip: t('common.cancel'),
previous: t('common.back'),
next: t('common.continue'),
finish: t('onboarding.nickname_spotlight.finish'),
}}
>
{children as any}
</CopilotProvider>
);
}
export default function RootLayout() { export default function RootLayout() {
return ( return (
<GestureHandlerRootView style={{ flex: 1 }}> <GestureHandlerRootView style={{ flex: 1 }}>
@ -196,7 +229,9 @@ export default function RootLayout() {
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<ActionSheetProvider> <ActionSheetProvider>
<SafeAreaProvider> <SafeAreaProvider>
<RootLayoutInner /> <CopilotShell>
<RootLayoutInner />
</CopilotShell>
</SafeAreaProvider> </SafeAreaProvider>
</ActionSheetProvider> </ActionSheetProvider>
</QueryClientProvider> </QueryClientProvider>

View File

@ -0,0 +1,404 @@
import { useEffect, useRef, useState } from 'react';
import {
Animated,
Dimensions,
Easing,
Text,
TouchableOpacity,
View,
} from 'react-native';
import Svg, { Defs, RadialGradient, Rect, Stop } from 'react-native-svg';
import { useRouter } from 'expo-router';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
import { useTranslation } from 'react-i18next';
import { apiFetch } from '../../lib/api';
import { invalidateMe } from '../../hooks/useMe';
const { height: SH } = Dimensions.get('window');
type Bullet = {
icon: keyof typeof Ionicons.glyphMap;
titleKey: string;
descKey: string;
};
const BULLETS: Bullet[] = [
{ icon: 'eye-off-outline', titleKey: 'onboarding.welcome.bullet_anon_title', descKey: 'onboarding.welcome.bullet_anon_desc' },
{ icon: 'shield-checkmark-outline', titleKey: 'onboarding.welcome.bullet_protect_title', descKey: 'onboarding.welcome.bullet_protect_desc' },
{ icon: 'people-outline', titleKey: 'onboarding.welcome.bullet_community_title', descKey: 'onboarding.welcome.bullet_community_desc' },
];
export default function OnboardingWelcomeScreen() {
const router = useRouter();
const insets = useSafeAreaInsets();
const { t } = useTranslation();
const [submitting, setSubmitting] = useState(false);
// Animation values — Spiegel zur LandingScreen-Choreografie für visuelle Kohärenz
const glowOpacity = useRef(new Animated.Value(0.5)).current;
const haloOpacity = useRef(new Animated.Value(0)).current;
const haloScale = useRef(new Animated.Value(0.6)).current;
const heroOpacity = useRef(new Animated.Value(0)).current;
const heroScale = useRef(new Animated.Value(0.85)).current;
const heroPulse = useRef(new Animated.Value(1)).current;
const headlineOpacity = useRef(new Animated.Value(0)).current;
const headlineTranslate = useRef(new Animated.Value(10)).current;
const bulletsOpacity = useRef([0, 0, 0].map(() => new Animated.Value(0))).current;
const bulletsTranslate = useRef([0, 0, 0].map(() => new Animated.Value(14))).current;
const privacyOpacity = useRef(new Animated.Value(0)).current;
const privacyTranslate = useRef(new Animated.Value(14)).current;
const ctaOpacity = useRef(new Animated.Value(0)).current;
const ctaTranslate = useRef(new Animated.Value(14)).current;
useEffect(() => {
Animated.loop(
Animated.sequence([
Animated.timing(glowOpacity, { toValue: 0.9, duration: 2200, useNativeDriver: true }),
Animated.timing(glowOpacity, { toValue: 0.5, duration: 2200, useNativeDriver: true }),
]),
).start();
const ease = (toValue: number, duration: number) => ({
toValue,
duration,
useNativeDriver: true,
easing: Easing.out(Easing.cubic),
});
Animated.parallel([
Animated.timing(haloOpacity, ease(1, 900)),
Animated.timing(haloScale, ease(1, 900)),
]).start();
setTimeout(() => {
Animated.parallel([
Animated.timing(heroOpacity, ease(1, 650)),
Animated.spring(heroScale, { toValue: 1, useNativeDriver: true, friction: 6, tension: 80 }),
]).start();
}, 250);
setTimeout(() => {
Animated.loop(
Animated.sequence([
Animated.timing(heroPulse, { toValue: 1.06, duration: 1400, useNativeDriver: true }),
Animated.timing(heroPulse, { toValue: 1, duration: 1400, useNativeDriver: true }),
]),
).start();
}, 1000);
setTimeout(() => {
Animated.parallel([
Animated.timing(headlineOpacity, ease(1, 600)),
Animated.timing(headlineTranslate, ease(0, 600)),
]).start();
}, 700);
BULLETS.forEach((_, i) => {
setTimeout(() => {
Animated.parallel([
Animated.timing(bulletsOpacity[i], ease(1, 450)),
Animated.timing(bulletsTranslate[i], ease(0, 450)),
]).start();
}, 1100 + i * 180);
});
setTimeout(() => {
Animated.parallel([
Animated.timing(privacyOpacity, ease(1, 600)),
Animated.timing(privacyTranslate, ease(0, 600)),
]).start();
}, 1700);
setTimeout(() => {
Animated.parallel([
Animated.timing(ctaOpacity, ease(1, 600)),
Animated.timing(ctaTranslate, ease(0, 600)),
]).start();
}, 1950);
}, []);
async function handleStart() {
if (submitting) return;
setSubmitting(true);
try {
await apiFetch('/api/profile/me/onboarding-step', {
method: 'PATCH',
body: JSON.stringify({ step: 'nickname' }),
});
invalidateMe();
router.replace('/profile/edit');
} catch (e) {
console.warn('[onboarding/welcome] failed to advance step:', e);
// Sackgasse-Verhalten: Step bleibt 'welcome', User kann nochmal tappen.
setSubmitting(false);
}
}
return (
<View style={{ flex: 1, backgroundColor: '#0f172a', overflow: 'hidden' }}>
{/* Atmender Top-Glow */}
<Animated.View
pointerEvents="none"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: SH * 0.5,
opacity: glowOpacity,
}}
>
<Svg width="100%" height="100%">
<Defs>
<RadialGradient id="welcomeGlow" cx="50%" cy="0%" rx="70%" ry="100%" fx="50%" fy="0%">
<Stop offset="0%" stopColor="#1e3a8a" stopOpacity="1" />
<Stop offset="100%" stopColor="#1e3a8a" stopOpacity="0" />
</RadialGradient>
</Defs>
<Rect width="100%" height="100%" fill="url(#welcomeGlow)" />
</Svg>
</Animated.View>
{/* Center indigo halo */}
<Animated.View
pointerEvents="none"
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
opacity: haloOpacity,
transform: [{ scale: haloScale }],
}}
>
<Svg width="100%" height="100%">
<Defs>
<RadialGradient id="welcomeHalo" cx="50%" cy="30%" rx="55%" ry="55%">
<Stop offset="0%" stopColor="#6366f1" stopOpacity="0.22" />
<Stop offset="100%" stopColor="#6366f1" stopOpacity="0" />
</RadialGradient>
</Defs>
<Rect width="100%" height="100%" fill="url(#welcomeHalo)" />
</Svg>
</Animated.View>
<View
style={{
flex: 1,
paddingHorizontal: 24,
paddingTop: insets.top + 24,
paddingBottom: insets.bottom + 20,
}}
>
{/* Hero-Icon */}
<View style={{ alignItems: 'center', marginTop: 12 }}>
<Animated.View
style={{
width: 120,
height: 120,
borderRadius: 28,
backgroundColor: 'rgba(99,102,241,0.18)',
borderWidth: 1,
borderColor: 'rgba(99,102,241,0.35)',
alignItems: 'center',
justifyContent: 'center',
opacity: heroOpacity,
transform: [
{ scale: Animated.multiply(heroScale, heroPulse) as any },
],
}}
>
<Ionicons name="shield-checkmark" size={66} color="#a5b4fc" />
</Animated.View>
</View>
{/* Headline + Subhead */}
<Animated.View
style={{
marginTop: 28,
opacity: headlineOpacity,
transform: [{ translateY: headlineTranslate }],
}}
>
<Text
style={{
fontFamily: 'Nunito_800ExtraBold',
fontSize: 28,
lineHeight: 34,
color: '#ffffff',
textAlign: 'center',
letterSpacing: -0.4,
}}
>
{t('onboarding.welcome.headline')}
</Text>
<Text
style={{
fontFamily: 'Nunito_400Regular',
fontSize: 15,
lineHeight: 22,
color: 'rgba(255,255,255,0.72)',
textAlign: 'center',
marginTop: 10,
}}
>
{t('onboarding.welcome.subhead')}
</Text>
</Animated.View>
{/* Mission-Bullets */}
<View style={{ marginTop: 28, gap: 12 }}>
{BULLETS.map((b, i) => (
<Animated.View
key={b.titleKey}
style={{
flexDirection: 'row',
alignItems: 'flex-start',
gap: 14,
backgroundColor: 'rgba(255,255,255,0.05)',
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.08)',
borderRadius: 16,
padding: 14,
opacity: bulletsOpacity[i],
transform: [{ translateY: bulletsTranslate[i] }],
}}
>
<View
style={{
width: 36,
height: 36,
borderRadius: 10,
backgroundColor: 'rgba(99,102,241,0.18)',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Ionicons name={b.icon} size={20} color="#a5b4fc" />
</View>
<View style={{ flex: 1 }}>
<Text
style={{
fontFamily: 'Nunito_700Bold',
fontSize: 15,
color: '#ffffff',
}}
>
{t(b.titleKey)}
</Text>
<Text
style={{
fontFamily: 'Nunito_400Regular',
fontSize: 13,
lineHeight: 19,
color: 'rgba(255,255,255,0.65)',
marginTop: 2,
}}
>
{t(b.descKey)}
</Text>
</View>
</Animated.View>
))}
</View>
{/* DSGVO-Box */}
<Animated.View
style={{
flexDirection: 'row',
alignItems: 'flex-start',
gap: 12,
marginTop: 16,
paddingVertical: 14,
paddingHorizontal: 14,
borderRadius: 14,
backgroundColor: 'rgba(34,197,94,0.10)',
borderWidth: 1,
borderColor: 'rgba(34,197,94,0.30)',
opacity: privacyOpacity,
transform: [{ translateY: privacyTranslate }],
}}
>
<Ionicons name="lock-closed" size={18} color="#86efac" style={{ marginTop: 2 }} />
<View style={{ flex: 1 }}>
<Text
style={{
fontFamily: 'Nunito_700Bold',
fontSize: 13,
color: '#bbf7d0',
letterSpacing: 0.2,
textTransform: 'uppercase',
}}
>
{t('onboarding.welcome.privacy_label')}
</Text>
<Text
style={{
fontFamily: 'Nunito_400Regular',
fontSize: 13,
lineHeight: 19,
color: 'rgba(255,255,255,0.82)',
marginTop: 4,
}}
>
{t('onboarding.welcome.privacy_body')}
</Text>
</View>
</Animated.View>
<View style={{ flex: 1 }} />
{/* CTA */}
<Animated.View
style={{
opacity: ctaOpacity,
transform: [{ translateY: ctaTranslate }],
}}
>
<TouchableOpacity
onPress={handleStart}
disabled={submitting}
activeOpacity={0.85}
style={{
backgroundColor: '#6366f1',
borderRadius: 16,
paddingVertical: 16,
alignItems: 'center',
opacity: submitting ? 0.6 : 1,
}}
>
<Text
style={{
fontFamily: 'Nunito_700Bold',
fontSize: 16,
color: '#ffffff',
letterSpacing: 0.2,
}}
>
{submitting ? t('onboarding.welcome.cta_loading') : t('onboarding.welcome.cta')}
</Text>
</TouchableOpacity>
<Text
style={{
fontFamily: 'Nunito_400Regular',
fontSize: 11,
lineHeight: 16,
color: 'rgba(255,255,255,0.45)',
textAlign: 'center',
marginTop: 10,
}}
>
{t('onboarding.welcome.next_hint')}
</Text>
</Animated.View>
</View>
</View>
);
}

View File

@ -1,4 +1,4 @@
import { useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { import {
View, View,
Text, Text,
@ -16,6 +16,7 @@ import * as ImagePicker from 'expo-image-picker';
// TODO(sdk54): migrate to new expo-file-system class-based API — see Task #14 // TODO(sdk54): migrate to new expo-file-system class-based API — see Task #14
import * as FileSystem from 'expo-file-system/legacy'; import * as FileSystem from 'expo-file-system/legacy';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { CopilotStep, useCopilot, walkthroughable } from 'react-native-copilot';
import { useColors } from '../../lib/theme'; import { useColors } from '../../lib/theme';
import { HERO_AVATARS, getAvatarUrl } from '../../lib/avatars'; import { HERO_AVATARS, getAvatarUrl } from '../../lib/avatars';
import { resolveAvatar } from '../../lib/resolveAvatar'; import { resolveAvatar } from '../../lib/resolveAvatar';
@ -23,12 +24,29 @@ import { apiFetch } from '../../lib/api';
import { useMe } from '../../hooks/useMe'; import { useMe } from '../../hooks/useMe';
import { KeyboardAwareScreen } from '../../components/KeyboardAwareScreen'; import { KeyboardAwareScreen } from '../../components/KeyboardAwareScreen';
const WalkthroughView = walkthroughable(View);
export default function ProfileEditScreen() { export default function ProfileEditScreen() {
const router = useRouter(); const router = useRouter();
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
const { t } = useTranslation(); const { t } = useTranslation();
const colors = useColors(); const colors = useColors();
const { me, reload } = useMe(); const { me, reload } = useMe();
const copilot = useCopilot();
const tourStartedRef = useRef(false);
const onboardingActive = me?.onboardingStep === 'nickname';
// Spotlight-Tour einmalig starten wenn User im Onboarding-Flow auf dieser Page landet.
// useCopilot.start ist async; wir setzen ein ref-Flag damit es nicht doppelt feuert
// wenn `me` mehrfach updated (z.B. nach reload).
useEffect(() => {
if (!onboardingActive || tourStartedRef.current) return;
tourStartedRef.current = true;
const t = setTimeout(() => {
copilot.start().catch(() => {});
}, 350); // kurzer Delay damit Layout fertig measure'd ist
return () => clearTimeout(t);
}, [onboardingActive]);
const INPUT_STYLE = { const INPUT_STYLE = {
fontSize: 16, fontSize: 16,
@ -105,8 +123,20 @@ export default function ProfileEditScreen() {
}, },
}); });
reload(); // Onboarding-Übergang: Nickname → Block (Stage 3 kommt später).
router.back(); // Wenn nicht im Onboarding-Flow → normale Save/Back-Semantik.
if (onboardingActive) {
await apiFetch('/api/profile/me/onboarding-step', {
method: 'PATCH',
body: { step: 'block' },
}).catch(() => {});
copilot.stop().catch(() => {});
reload();
router.replace('/(app)');
} else {
reload();
router.back();
}
} catch (err: any) { } catch (err: any) {
setUploading(false); setUploading(false);
console.error('[profile/edit] save failed:', err?.message ?? err); console.error('[profile/edit] save failed:', err?.message ?? err);
@ -283,17 +313,26 @@ export default function ProfileEditScreen() {
> >
{t('profile.edit_nickname_label').toUpperCase()} {t('profile.edit_nickname_label').toUpperCase()}
</Text> </Text>
<TextInput <CopilotStep
style={INPUT_STYLE} name="nickname"
value={nickname} order={1}
onChangeText={setNickname} text={t('onboarding.nickname_spotlight.body')}
placeholder={t('auth.nicknamePlaceholder')} active={onboardingActive}
placeholderTextColor="#a3a3a3" >
autoCapitalize="none" <WalkthroughView style={{ borderRadius: 12 }}>
autoCorrect={false} <TextInput
maxLength={32} style={INPUT_STYLE}
returnKeyType="done" value={nickname}
/> onChangeText={setNickname}
placeholder={t('auth.nicknamePlaceholder')}
placeholderTextColor="#a3a3a3"
autoCapitalize="none"
autoCorrect={false}
maxLength={32}
returnKeyType="done"
/>
</WalkthroughView>
</CopilotStep>
<Text <Text
style={{ style={{
marginTop: 6, marginTop: 6,

View File

@ -17,6 +17,8 @@ export type Plan = 'free' | 'pro' | 'legend';
* Stand (Avatar/Nickname/Plan werden via Profile-Edit-API geupdated, landen * Stand (Avatar/Nickname/Plan werden via Profile-Edit-API geupdated, landen
* in der DB, NICHT zurück ins JWT-Claim). * in der DB, NICHT zurück ins JWT-Claim).
*/ */
export type OnboardingStep = 'welcome' | 'nickname' | 'block' | 'done';
export type Me = { export type Me = {
id: string; id: string;
email: string; email: string;
@ -26,6 +28,7 @@ export type Me = {
plan: Plan; plan: Plan;
streak: number; streak: number;
lyraVoiceId: string | null; lyraVoiceId: string | null;
onboardingStep: OnboardingStep;
created_at?: string; created_at?: string;
}; };

View File

@ -347,6 +347,28 @@
"empty_web": "Noch keine eigenen Domains.\nTippe + um eine hinzuzufügen.", "empty_web": "Noch keine eigenen Domains.\nTippe + um eine hinzuzufügen.",
"empty_mail": "Noch keine Mail-Domains. Tippe + um eine E-Mail-Adresse oder Domain zu blockieren." "empty_mail": "Noch keine Mail-Domains. Tippe + um eine E-Mail-Adresse oder Domain zu blockieren."
}, },
"onboarding": {
"welcome": {
"headline": "Willkommen bei rebreak.",
"subhead": "Wir helfen dir, raus aus dem Glücksspiel zu kommen — anonym, geschützt, gemeinsam.",
"bullet_anon_title": "Du bleibst anonym",
"bullet_anon_desc": "Du wählst einen Alias. Niemand sieht deinen echten Namen — auch wir nicht.",
"bullet_protect_title": "Dein Gerät wird geschützt",
"bullet_protect_desc": "Glücksspiel-Seiten und -Apps werden für dich blockiert. Auch wenn der Drang kommt.",
"bullet_community_title": "Du gehst nicht allein",
"bullet_community_desc": "Andere auf dem gleichen Weg. Anonym schreiben, Streaks teilen, Halt finden.",
"privacy_label": "DSGVO · Datenminimierung",
"privacy_body": "Wir verarbeiten so wenig wie möglich. Du brauchst nur einen Alias. Kein Klarname, keine Tracker, keine Werbung.",
"cta": "Los geht's",
"cta_loading": "Einen Moment...",
"next_hint": "Im nächsten Schritt wählst du deinen Alias."
},
"nickname_spotlight": {
"title": "Wähle deinen Alias",
"body": "Das ist dein einziger Name in rebreak. Niemand sieht deine Mail oder deinen echten Namen.",
"finish": "Verstanden"
}
},
"protection_onboarding": { "protection_onboarding": {
"sheet_title": "Schutz einrichten", "sheet_title": "Schutz einrichten",
"sheet_intro": "Richte beide Schutz-Layer ein — in dieser Reihenfolge. Sobald der App-Schutz aktiv ist, kannst du VPN-Einstellungen nicht mehr öffnen.", "sheet_intro": "Richte beide Schutz-Layer ein — in dieser Reihenfolge. Sobald der App-Schutz aktiv ist, kannst du VPN-Einstellungen nicht mehr öffnen.",

View File

@ -347,6 +347,28 @@
"empty_web": "No custom domains yet.\nTap + to add one.", "empty_web": "No custom domains yet.\nTap + to add one.",
"empty_mail": "No mail domains yet. Tap + to block an email address or domain." "empty_mail": "No mail domains yet. Tap + to block an email address or domain."
}, },
"onboarding": {
"welcome": {
"headline": "Welcome to rebreak.",
"subhead": "We help you get out of gambling — anonymously, protected, together.",
"bullet_anon_title": "You stay anonymous",
"bullet_anon_desc": "You pick an alias. No one sees your real name — not even us.",
"bullet_protect_title": "Your device gets protected",
"bullet_protect_desc": "Gambling sites and apps are blocked for you. Even when the urge hits.",
"bullet_community_title": "You're not alone",
"bullet_community_desc": "Others walking the same path. Post anonymously, share streaks, find support.",
"privacy_label": "GDPR · Data minimization",
"privacy_body": "We process as little as possible. You only need an alias. No real name, no trackers, no ads.",
"cta": "Let's go",
"cta_loading": "One moment...",
"next_hint": "Next, you'll pick your alias."
},
"nickname_spotlight": {
"title": "Pick your alias",
"body": "This is your only name on rebreak. No one sees your email or real name.",
"finish": "Got it"
}
},
"protection_onboarding": { "protection_onboarding": {
"sheet_title": "Set up protection", "sheet_title": "Set up protection",
"sheet_intro": "Set up both protection layers in this order. Once the app lock is active, you won't be able to open VPN settings anymore.", "sheet_intro": "Set up both protection layers in this order. Once the app lock is active, you won't be able to open VPN settings anymore.",

View File

@ -345,6 +345,28 @@
"empty_web": "Aucun domaine personnalisé.\nAppuyez sur + pour en ajouter un.", "empty_web": "Aucun domaine personnalisé.\nAppuyez sur + pour en ajouter un.",
"empty_mail": "Aucun domaine mail. Appuyez sur + pour bloquer une adresse ou un domaine." "empty_mail": "Aucun domaine mail. Appuyez sur + pour bloquer une adresse ou un domaine."
}, },
"onboarding": {
"welcome": {
"headline": "Bienvenue sur rebreak.",
"subhead": "On t'aide à sortir du jeu — anonymement, en sécurité, ensemble.",
"bullet_anon_title": "Tu restes anonyme",
"bullet_anon_desc": "Tu choisis un alias. Personne ne voit ton vrai nom — nous non plus.",
"bullet_protect_title": "Ton appareil est protégé",
"bullet_protect_desc": "Les sites et apps de jeu sont bloqués pour toi. Même quand l'envie revient.",
"bullet_community_title": "Tu n'es pas seul",
"bullet_community_desc": "D'autres font le même chemin. Écris anonymement, partage tes streaks, trouve du soutien.",
"privacy_label": "RGPD · Minimisation des données",
"privacy_body": "Nous traitons le strict minimum. Un alias suffit. Pas de vrai nom, pas de trackers, pas de pubs.",
"cta": "On y va",
"cta_loading": "Un instant...",
"next_hint": "À l'étape suivante, tu choisiras ton alias."
},
"nickname_spotlight": {
"title": "Choisis ton alias",
"body": "C'est ton seul nom sur rebreak. Personne ne voit ton e-mail ni ton vrai nom.",
"finish": "Compris"
}
},
"mail": { "mail": {
"title": "Protection Mail", "title": "Protection Mail",
"subtitle": "Bloquer automatiquement les mails de jeux d'argent", "subtitle": "Bloquer automatiquement les mails de jeux d'argent",

View File

@ -57,6 +57,7 @@
"react-i18next": "^15.1.0", "react-i18next": "^15.1.0",
"react-native": "0.81.5", "react-native": "0.81.5",
"react-native-bottom-tabs": "^1.2.0", "react-native-bottom-tabs": "^1.2.0",
"react-native-copilot": "^3.3.3",
"react-native-gesture-handler": "~2.28.0", "react-native-gesture-handler": "~2.28.0",
"react-native-keyboard-controller": "^1.21.7", "react-native-keyboard-controller": "^1.21.7",
"react-native-mmkv": "^3.1.0", "react-native-mmkv": "^3.1.0",

View File

@ -0,0 +1,21 @@
-- Interaktiver Onboarding-Stand pro Profile.
--
-- Werte: "welcome" (Default) | "nickname" | "block" | "done"
--
-- Das Frontend nutzt diesen Wert als Single-Source-of-Truth für den Stand der
-- Spotlight-Tour. So bleibt der Onboarding-Stand auch nach App-Reinstall oder
-- Re-Login erhalten — kein AsyncStorage-Reset-Problem mehr.
--
-- Backfill: existierende Profile (created_at < NOW()) bekommen "done" — sie
-- haben den Onboarding-Flow nicht durchlaufen können (weil er noch nicht
-- existierte), sollen aber auch keinen retroaktiven Spotlight kriegen.
-- Wer testen will (z.B. eigenes Profile zurücksetzen), kann manuell:
-- UPDATE rebreak.profiles SET onboarding_step = 'welcome' WHERE id = '...';
ALTER TABLE "rebreak"."profiles"
ADD COLUMN IF NOT EXISTS "onboarding_step" TEXT NOT NULL DEFAULT 'welcome';
-- Existing rows: bereits onboardet (zumindest implizit) → "done"
UPDATE "rebreak"."profiles"
SET "onboarding_step" = 'done'
WHERE "created_at" < NOW();

View File

@ -52,6 +52,12 @@ model Profile {
// ─── DiGA-Banner Persistence (server-side, überlebt Re-Install) ───────── // ─── DiGA-Banner Persistence (server-side, überlebt Re-Install) ─────────
digaBannerDismissedAt DateTime? @map("diga_banner_dismissed_at") digaBannerDismissedAt DateTime? @map("diga_banner_dismissed_at")
// ─── Interaktives Onboarding (Welcome → Nickname → Block → Done) ────────
// Werte: "welcome" (Default für neue Profile) | "nickname" | "block" | "done"
// Frontend nutzt diesen Wert um den Onboarding-Spotlight-Tour-Stand
// wiederherzustellen — auch nach App-Reinstall (DB-State statt AsyncStorage).
onboardingStep String @default("welcome") @map("onboarding_step")
// ─── Install-Tracking (für Streak: max(last_resolved_cooldown, last_install)) ── // ─── Install-Tracking (für Streak: max(last_resolved_cooldown, last_install)) ──
lastInstallAt DateTime? @map("last_install_at") lastInstallAt DateTime? @map("last_install_at")

View File

@ -23,6 +23,7 @@ export default defineEventHandler(async (event) => {
foundingMember: dbProfile?.foundingMember ?? false, foundingMember: dbProfile?.foundingMember ?? false,
streak: dbProfile?.streak ?? 0, streak: dbProfile?.streak ?? 0,
lyraVoiceId: dbProfile?.lyraVoiceId ?? null, lyraVoiceId: dbProfile?.lyraVoiceId ?? null,
onboardingStep: dbProfile?.onboardingStep ?? "welcome",
created_at: dbProfile?.createdAt?.toISOString() ?? user.created_at, created_at: dbProfile?.createdAt?.toISOString() ?? user.created_at,
// Für useUserPlan im Frontend — Key-Subset der PlanLimits // Für useUserPlan im Frontend — Key-Subset der PlanLimits
planLimits: { planLimits: {

View File

@ -0,0 +1,27 @@
import { setOnboardingStep, isOnboardingStep } from "../../../db/profile";
/**
* PATCH /api/profile/me/onboarding-step
*
* Setzt den Onboarding-Stand des eingeloggten Users.
* Werte: "welcome" | "nickname" | "block" | "done"
*
* Body: { step: "nickname" | "block" | "done" }
*
* Das Frontend ruft das nach jedem abgeschlossenen Schritt auf:
* Welcome-Screen "Los geht's" step="nickname"
* Nickname-Save step="block"
* Block-Aktivierung done step="done"
*/
export default defineEventHandler(async (event) => {
const user = await requireUser(event);
const body = await readBody(event);
const { step } = body as { step?: unknown };
if (!isOnboardingStep(step)) {
throw createError({ statusCode: 400, statusMessage: "invalid_step" });
}
const updated = await setOnboardingStep(user.id, step);
return { success: true, data: { onboardingStep: updated.onboardingStep } };
});

View File

@ -22,6 +22,24 @@ export async function deleteProfile(userId: string) {
return db.profile.delete({ where: { id: userId } }); return db.profile.delete({ where: { id: userId } });
} }
// ─── Onboarding-Step ────────────────────────────────────────────────────────
export const ONBOARDING_STEPS = ["welcome", "nickname", "block", "done"] as const;
export type OnboardingStep = (typeof ONBOARDING_STEPS)[number];
export function isOnboardingStep(value: unknown): value is OnboardingStep {
return typeof value === "string" && (ONBOARDING_STEPS as readonly string[]).includes(value);
}
export async function setOnboardingStep(userId: string, step: OnboardingStep) {
const db = usePrisma();
return db.profile.update({
where: { id: userId },
data: { onboardingStep: step },
select: { onboardingStep: true },
});
}
// ─── DiGA-Demographie ────────────────────────────────────────────────────── // ─── DiGA-Demographie ──────────────────────────────────────────────────────
export type DemographicsFields = { export type DemographicsFields = {

489
pnpm-lock.yaml generated
View File

@ -255,6 +255,9 @@ importers:
react-native-bottom-tabs: react-native-bottom-tabs:
specifier: ^1.2.0 specifier: ^1.2.0
version: 1.2.0(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0) version: 1.2.0(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
react-native-copilot:
specifier: ^3.3.3
version: 3.3.3(@types/node@22.19.17)(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
react-native-gesture-handler: react-native-gesture-handler:
specifier: ~2.28.0 specifier: ~2.28.0
version: 2.28.0(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0) version: 2.28.0(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
@ -924,6 +927,67 @@ packages:
resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==} resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==}
engines: {node: '>=18'} engines: {node: '>=18'}
'@changesets/apply-release-plan@7.1.1':
resolution: {integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==}
'@changesets/assemble-release-plan@6.0.10':
resolution: {integrity: sha512-rSDcqdJ9KbVyjpBIuCidhvZNIiVt1XaIYp73ycVQRIA5n/j6wQaEk0ChRLMUQ1vkxZe51PTQ9OIhbg6HQMW45A==}
'@changesets/changelog-git@0.2.1':
resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==}
'@changesets/changelog-github@0.5.2':
resolution: {integrity: sha512-HeGeDl8HaIGj9fQHo/tv5XKQ2SNEi9+9yl1Bss1jttPqeiASRXhfi0A2wv8yFKCp07kR1gpOI5ge6+CWNm1jPw==}
'@changesets/cli@2.31.0':
resolution: {integrity: sha512-AhI4enNTgHu2IZr6K4WZyf0EPch4XVMn1yOMFmCD9gsfBGqMYaHXls5HyDv6/CL5axVQABz68eG30eCtbr2wFg==}
hasBin: true
'@changesets/config@3.1.4':
resolution: {integrity: sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q==}
'@changesets/errors@0.2.0':
resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==}
'@changesets/get-dependents-graph@2.1.4':
resolution: {integrity: sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==}
'@changesets/get-github-info@0.7.0':
resolution: {integrity: sha512-+i67Bmhfj9V4KfDeS1+Tz3iF32btKZB2AAx+cYMqDSRFP7r3/ZdGbjCo+c6qkyViN9ygDuBjzageuPGJtKGe5A==}
'@changesets/get-release-plan@4.0.16':
resolution: {integrity: sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==}
'@changesets/get-version-range-type@0.4.0':
resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==}
'@changesets/git@3.0.4':
resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==}
'@changesets/logger@0.1.1':
resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==}
'@changesets/parse@0.4.3':
resolution: {integrity: sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==}
'@changesets/pre@2.0.2':
resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==}
'@changesets/read@0.6.7':
resolution: {integrity: sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==}
'@changesets/should-skip-package@0.1.2':
resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==}
'@changesets/types@4.1.0':
resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==}
'@changesets/types@6.1.0':
resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==}
'@changesets/write@0.4.0':
resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==}
'@clack/core@1.3.0': '@clack/core@1.3.0':
resolution: {integrity: sha512-xJPHpAmEQUBrXSLx0gF+q5K/IyihXpsHZcha+jB+tyahsKRK3Dxo4D0coZDewHo12NhiuzC3dTtMPbm53GEAAA==} resolution: {integrity: sha512-xJPHpAmEQUBrXSLx0gF+q5K/IyihXpsHZcha+jB+tyahsKRK3Dxo4D0coZDewHo12NhiuzC3dTtMPbm53GEAAA==}
engines: {node: '>= 20.12.0'} engines: {node: '>= 20.12.0'}
@ -1803,6 +1867,15 @@ packages:
'@ide/backoff@1.0.0': '@ide/backoff@1.0.0':
resolution: {integrity: sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==} resolution: {integrity: sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==}
'@inquirer/external-editor@1.0.3':
resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@internationalized/date@3.12.1': '@internationalized/date@3.12.1':
resolution: {integrity: sha512-6IedsVWXyq4P9Tj+TxuU8WGWM70hYLl12nbYU8jkikVpa6WXapFazPUcHUMDMoWftIDE2ILDkFFte6W2nFCkRQ==} resolution: {integrity: sha512-6IedsVWXyq4P9Tj+TxuU8WGWM70hYLl12nbYU8jkikVpa6WXapFazPUcHUMDMoWftIDE2ILDkFFte6W2nFCkRQ==}
@ -1978,6 +2051,12 @@ packages:
react-native-worklets: react-native-worklets:
optional: true optional: true
'@manypkg/find-root@1.1.0':
resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==}
'@manypkg/get-packages@1.1.3':
resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==}
'@mapbox/node-pre-gyp@2.0.3': '@mapbox/node-pre-gyp@2.0.3':
resolution: {integrity: sha512-uwPAhccfFJlsfCxMYTwOdVfOz3xqyj8xYL3zJj8f0pb30tLohnnFPhLuqp4/qoEz8sNxe4SESZedcBojRefIzg==} resolution: {integrity: sha512-uwPAhccfFJlsfCxMYTwOdVfOz3xqyj8xYL3zJj8f0pb30tLohnnFPhLuqp4/qoEz8sNxe4SESZedcBojRefIzg==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -3905,6 +3984,9 @@ packages:
'@types/node-fetch@2.6.13': '@types/node-fetch@2.6.13':
resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==}
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
'@types/node@18.19.130': '@types/node@18.19.130':
resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==}
@ -4303,6 +4385,10 @@ packages:
anser@1.4.10: anser@1.4.10:
resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==}
ansi-colors@4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'}
ansi-escapes@4.3.2: ansi-escapes@4.3.2:
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -4370,6 +4456,10 @@ packages:
array-timsort@1.0.3: array-timsort@1.0.3:
resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==}
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
asap@2.0.6: asap@2.0.6:
resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
@ -4562,6 +4652,10 @@ packages:
resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==}
engines: {node: '>=12.0.0'} engines: {node: '>=12.0.0'}
better-path-resolve@1.0.0:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'}
better-result@2.9.2: better-result@2.9.2:
resolution: {integrity: sha512-WIFoBPCdnTOdk9inkE1ZRvCZ4P0CpSkAiLlchC65N7n9DcjZ3NhqkBOlafzpOVnO8ixyi37kicmSJ3ENhPZl7Q==} resolution: {integrity: sha512-WIFoBPCdnTOdk9inkE1ZRvCZ4P0CpSkAiLlchC65N7n9DcjZ3NhqkBOlafzpOVnO8ixyi37kicmSJ3ENhPZl7Q==}
@ -4709,6 +4803,9 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'} engines: {node: '>=10'}
chardet@2.1.1:
resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==}
chart.js@4.5.1: chart.js@4.5.1:
resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==} resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==}
engines: {pnpm: '>=8'} engines: {pnpm: '>=8'}
@ -4992,6 +5089,9 @@ packages:
resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
engines: {node: '>=12'} engines: {node: '>=12'}
dataloader@1.4.0:
resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==}
db0@0.3.4: db0@0.3.4:
resolution: {integrity: sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw==} resolution: {integrity: sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw==}
peerDependencies: peerDependencies:
@ -5116,6 +5216,10 @@ packages:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'}
detect-libc@1.0.3: detect-libc@1.0.3:
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
engines: {node: '>=0.10'} engines: {node: '>=0.10'}
@ -5153,6 +5257,10 @@ packages:
resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==} resolution: {integrity: sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==}
engines: {node: '>=0.3.1'} engines: {node: '>=0.3.1'}
dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
dlv@1.1.3: dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
@ -5185,6 +5293,10 @@ packages:
resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==} resolution: {integrity: sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==}
engines: {node: '>=12'} engines: {node: '>=12'}
dotenv@8.6.0:
resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==}
engines: {node: '>=10'}
dunder-proto@1.0.1: dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -5280,6 +5392,10 @@ packages:
resolution: {integrity: sha512-xe9vQb5kReirPUxgQrXA3ihgbCqssmTiM7cOZ+Gzu+VeGWgpV98lLZvp0dl4yriyAePcewxGUs9UpKD8PET9KQ==} resolution: {integrity: sha512-xe9vQb5kReirPUxgQrXA3ihgbCqssmTiM7cOZ+Gzu+VeGWgpV98lLZvp0dl4yriyAePcewxGUs9UpKD8PET9KQ==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
enquirer@2.4.1:
resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
engines: {node: '>=8.6'}
entities@4.5.0: entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
@ -5703,6 +5819,9 @@ packages:
exsolve@1.0.8: exsolve@1.0.8:
resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==}
extendable-error@0.1.7:
resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==}
fast-check@3.23.2: fast-check@3.23.2:
resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
@ -5880,6 +5999,14 @@ packages:
fs-constants@1.0.0: fs-constants@1.0.0:
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
fs-extra@7.0.1:
resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
engines: {node: '>=6 <7 || >=8'}
fs-extra@8.1.0:
resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
engines: {node: '>=6 <7 || >=8'}
fs.realpath@1.0.0: fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@ -5980,6 +6107,10 @@ packages:
resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
engines: {node: '>=18'} engines: {node: '>=18'}
globby@11.1.0:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
globby@16.2.0: globby@16.2.0:
resolution: {integrity: sha512-QrJia2qDf5BB/V6HYlDTs0I0lBahyjLzpGQg3KT7FnCdTonAyPy2RtY802m2k4ALx6Dp752f82WsOczEVr3l6Q==} resolution: {integrity: sha512-QrJia2qDf5BB/V6HYlDTs0I0lBahyjLzpGQg3KT7FnCdTonAyPy2RtY802m2k4ALx6Dp752f82WsOczEVr3l6Q==}
engines: {node: '>=20'} engines: {node: '>=20'}
@ -6093,6 +6224,10 @@ packages:
httpxy@0.5.1: httpxy@0.5.1:
resolution: {integrity: sha512-JPhqYiixe1A1I+MXDewWDZqeudBGU8Q9jCHYN8ML+779RQzLjTi78HBvWz4jMxUD6h2/vUL12g4q/mFM0OUw1A==} resolution: {integrity: sha512-JPhqYiixe1A1I+MXDewWDZqeudBGU8Q9jCHYN8ML+779RQzLjTi78HBvWz4jMxUD6h2/vUL12g4q/mFM0OUw1A==}
human-id@4.1.3:
resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==}
hasBin: true
human-signals@5.0.0: human-signals@5.0.0:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'} engines: {node: '>=16.17.0'}
@ -6279,6 +6414,10 @@ packages:
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
is-subdir@1.2.0:
resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==}
engines: {node: '>=4'}
is-typed-array@1.1.15: is-typed-array@1.1.15:
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -6435,6 +6574,9 @@ packages:
resolution: {integrity: sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA==} resolution: {integrity: sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
jsonfile@4.0.0:
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
keyv@4.5.4: keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@ -6667,6 +6809,9 @@ packages:
lodash.memoize@4.1.2: lodash.memoize@4.1.2:
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
lodash.startcase@4.4.0:
resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==}
lodash.throttle@4.1.1: lodash.throttle@4.1.1:
resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
@ -7217,6 +7362,9 @@ packages:
orderedmap@2.1.1: orderedmap@2.1.1:
resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==}
outdent@0.5.0:
resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==}
oxc-minify@0.94.0: oxc-minify@0.94.0:
resolution: {integrity: sha512-7+9iyxwpzfjuiEnSqNJYzTsC1Oud742PPkr/4S1bGY930U4tApdLEK8zmgbT57c1/56cfNOndqZaeQZiAfnJ5A==} resolution: {integrity: sha512-7+9iyxwpzfjuiEnSqNJYzTsC1Oud742PPkr/4S1bGY930U4tApdLEK8zmgbT57c1/56cfNOndqZaeQZiAfnJ5A==}
engines: {node: ^20.19.0 || >=22.12.0} engines: {node: ^20.19.0 || >=22.12.0}
@ -7242,6 +7390,10 @@ packages:
peerDependencies: peerDependencies:
oxc-parser: '>=0.72.0' oxc-parser: '>=0.72.0'
p-filter@2.1.0:
resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==}
engines: {node: '>=8'}
p-limit@2.3.0: p-limit@2.3.0:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -7262,6 +7414,10 @@ packages:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'} engines: {node: '>=10'}
p-map@2.1.0:
resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==}
engines: {node: '>=6'}
p-try@2.2.0: p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -7269,6 +7425,9 @@ packages:
package-json-from-dist@1.0.1: package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
package-manager-detector@0.2.11:
resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==}
package-manager-detector@1.6.0: package-manager-detector@1.6.0:
resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
@ -7320,6 +7479,10 @@ packages:
resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
engines: {node: 18 || 20 || >=22} engines: {node: 18 || 20 || >=22}
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
pathe@1.1.2: pathe@1.1.2:
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
@ -7388,6 +7551,10 @@ packages:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
pify@4.0.1:
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
engines: {node: '>=6'}
pino-abstract-transport@3.0.0: pino-abstract-transport@3.0.0:
resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==} resolution: {integrity: sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==}
@ -7678,6 +7845,11 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
prettier@2.8.8:
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
engines: {node: '>=10.13.0'}
hasBin: true
prettier@3.8.3: prettier@3.8.3:
resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==}
engines: {node: '>=14'} engines: {node: '>=14'}
@ -7885,6 +8057,13 @@ packages:
react: '*' react: '*'
react-native: '*' react-native: '*'
react-native-copilot@3.3.3:
resolution: {integrity: sha512-/LX70DSqVhjOsbSGC3r3RYg+FtovUUudqWKby2agbXb0PsIWaEvjoH5SNQRkBCW8DHbDlZoPMv6oGKSJm3BPrQ==}
peerDependencies:
react: '>=16.8.0'
react-native: '>=0.60.0'
react-native-svg: '>=9.0.0'
react-native-css-interop@0.2.3: react-native-css-interop@0.2.3:
resolution: {integrity: sha512-wc+JI7iUfdFBqnE18HhMTtD0q9vkhuMczToA87UdHGWwMyxdT5sCcNy+i4KInPCE855IY0Ic8kLQqecAIBWz7w==} resolution: {integrity: sha512-wc+JI7iUfdFBqnE18HhMTtD0q9vkhuMczToA87UdHGWwMyxdT5sCcNy+i4KInPCE855IY0Ic8kLQqecAIBWz7w==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -8021,6 +8200,10 @@ packages:
read-cache@1.0.0: read-cache@1.0.0:
resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
read-yaml-file@1.1.0:
resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==}
engines: {node: '>=6'}
read-yaml-file@2.1.0: read-yaml-file@2.1.0:
resolution: {integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==} resolution: {integrity: sha512-UkRNRIwnhG+y7hpqnycCL/xbTk7+ia9VuVTC0S+zVbwd65DI9eUpRMfsWIGrCWxTU/mi+JW8cHQCrv+zfCbEPQ==}
engines: {node: '>=10.13'} engines: {node: '>=10.13'}
@ -8415,6 +8598,9 @@ packages:
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
engines: {node: '>= 12'} engines: {node: '>= 12'}
spawndamnit@3.0.1:
resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==}
speakingurl@14.0.1: speakingurl@14.0.1:
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -8511,6 +8697,10 @@ packages:
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
engines: {node: '>=12'} engines: {node: '>=12'}
strip-bom@3.0.0:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
strip-bom@4.0.0: strip-bom@4.0.0:
resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -8643,6 +8833,10 @@ packages:
teex@1.0.1: teex@1.0.1:
resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==}
term-size@2.2.1:
resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
engines: {node: '>=8'}
terminal-link@2.1.1: terminal-link@2.1.1:
resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -8876,6 +9070,10 @@ packages:
oxc-parser: oxc-parser:
optional: true optional: true
universalify@0.1.2:
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
engines: {node: '>= 4.0.0'}
unpipe@1.0.0: unpipe@1.0.0:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@ -10250,6 +10448,164 @@ snapshots:
dependencies: dependencies:
fontkitten: 1.0.3 fontkitten: 1.0.3
'@changesets/apply-release-plan@7.1.1':
dependencies:
'@changesets/config': 3.1.4
'@changesets/get-version-range-type': 0.4.0
'@changesets/git': 3.0.4
'@changesets/should-skip-package': 0.1.2
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
detect-indent: 6.1.0
fs-extra: 7.0.1
lodash.startcase: 4.4.0
outdent: 0.5.0
prettier: 2.8.8
resolve-from: 5.0.0
semver: 7.7.4
'@changesets/assemble-release-plan@6.0.10':
dependencies:
'@changesets/errors': 0.2.0
'@changesets/get-dependents-graph': 2.1.4
'@changesets/should-skip-package': 0.1.2
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
semver: 7.7.4
'@changesets/changelog-git@0.2.1':
dependencies:
'@changesets/types': 6.1.0
'@changesets/changelog-github@0.5.2':
dependencies:
'@changesets/get-github-info': 0.7.0
'@changesets/types': 6.1.0
dotenv: 8.6.0
transitivePeerDependencies:
- encoding
'@changesets/cli@2.31.0(@types/node@22.19.17)':
dependencies:
'@changesets/apply-release-plan': 7.1.1
'@changesets/assemble-release-plan': 6.0.10
'@changesets/changelog-git': 0.2.1
'@changesets/config': 3.1.4
'@changesets/errors': 0.2.0
'@changesets/get-dependents-graph': 2.1.4
'@changesets/get-release-plan': 4.0.16
'@changesets/git': 3.0.4
'@changesets/logger': 0.1.1
'@changesets/pre': 2.0.2
'@changesets/read': 0.6.7
'@changesets/should-skip-package': 0.1.2
'@changesets/types': 6.1.0
'@changesets/write': 0.4.0
'@inquirer/external-editor': 1.0.3(@types/node@22.19.17)
'@manypkg/get-packages': 1.1.3
ansi-colors: 4.1.3
enquirer: 2.4.1
fs-extra: 7.0.1
mri: 1.2.0
package-manager-detector: 0.2.11
picocolors: 1.1.1
resolve-from: 5.0.0
semver: 7.7.4
spawndamnit: 3.0.1
term-size: 2.2.1
transitivePeerDependencies:
- '@types/node'
'@changesets/config@3.1.4':
dependencies:
'@changesets/errors': 0.2.0
'@changesets/get-dependents-graph': 2.1.4
'@changesets/logger': 0.1.1
'@changesets/should-skip-package': 0.1.2
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
fs-extra: 7.0.1
micromatch: 4.0.8
'@changesets/errors@0.2.0':
dependencies:
extendable-error: 0.1.7
'@changesets/get-dependents-graph@2.1.4':
dependencies:
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
picocolors: 1.1.1
semver: 7.7.4
'@changesets/get-github-info@0.7.0':
dependencies:
dataloader: 1.4.0
node-fetch: 2.7.0
transitivePeerDependencies:
- encoding
'@changesets/get-release-plan@4.0.16':
dependencies:
'@changesets/assemble-release-plan': 6.0.10
'@changesets/config': 3.1.4
'@changesets/pre': 2.0.2
'@changesets/read': 0.6.7
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
'@changesets/get-version-range-type@0.4.0': {}
'@changesets/git@3.0.4':
dependencies:
'@changesets/errors': 0.2.0
'@manypkg/get-packages': 1.1.3
is-subdir: 1.2.0
micromatch: 4.0.8
spawndamnit: 3.0.1
'@changesets/logger@0.1.1':
dependencies:
picocolors: 1.1.1
'@changesets/parse@0.4.3':
dependencies:
'@changesets/types': 6.1.0
js-yaml: 4.1.1
'@changesets/pre@2.0.2':
dependencies:
'@changesets/errors': 0.2.0
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
fs-extra: 7.0.1
'@changesets/read@0.6.7':
dependencies:
'@changesets/git': 3.0.4
'@changesets/logger': 0.1.1
'@changesets/parse': 0.4.3
'@changesets/types': 6.1.0
fs-extra: 7.0.1
p-filter: 2.1.0
picocolors: 1.1.1
'@changesets/should-skip-package@0.1.2':
dependencies:
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
'@changesets/types@4.1.0': {}
'@changesets/types@6.1.0': {}
'@changesets/write@0.4.0':
dependencies:
'@changesets/types': 6.1.0
fs-extra: 7.0.1
human-id: 4.1.3
prettier: 2.8.8
'@clack/core@1.3.0': '@clack/core@1.3.0':
dependencies: dependencies:
fast-wrap-ansi: 0.2.0 fast-wrap-ansi: 0.2.0
@ -11030,6 +11386,13 @@ snapshots:
'@ide/backoff@1.0.0': {} '@ide/backoff@1.0.0': {}
'@inquirer/external-editor@1.0.3(@types/node@22.19.17)':
dependencies:
chardet: 2.1.1
iconv-lite: 0.7.2
optionalDependencies:
'@types/node': 22.19.17
'@internationalized/date@3.12.1': '@internationalized/date@3.12.1':
dependencies: dependencies:
'@swc/helpers': 0.5.21 '@swc/helpers': 0.5.21
@ -11242,6 +11605,22 @@ snapshots:
react-native-reanimated: 4.1.7(react-native-worklets@0.5.1(@babel/core@7.29.0)(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0) react-native-reanimated: 4.1.7(react-native-worklets@0.5.1(@babel/core@7.29.0)(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
react-native-worklets: 0.5.1(@babel/core@7.29.0)(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0) react-native-worklets: 0.5.1(@babel/core@7.29.0)(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
'@manypkg/find-root@1.1.0':
dependencies:
'@babel/runtime': 7.29.2
'@types/node': 12.20.55
find-up: 4.1.0
fs-extra: 8.1.0
'@manypkg/get-packages@1.1.3':
dependencies:
'@babel/runtime': 7.29.2
'@changesets/types': 4.1.0
'@manypkg/find-root': 1.1.0
fs-extra: 8.1.0
globby: 11.1.0
read-yaml-file: 1.1.0
'@mapbox/node-pre-gyp@2.0.3': '@mapbox/node-pre-gyp@2.0.3':
dependencies: dependencies:
consola: 3.4.2 consola: 3.4.2
@ -13537,6 +13916,8 @@ snapshots:
'@types/node': 22.19.17 '@types/node': 22.19.17
form-data: 4.0.5 form-data: 4.0.5
'@types/node@12.20.55': {}
'@types/node@18.19.130': '@types/node@18.19.130':
dependencies: dependencies:
undici-types: 5.26.5 undici-types: 5.26.5
@ -14151,6 +14532,8 @@ snapshots:
anser@1.4.10: {} anser@1.4.10: {}
ansi-colors@4.1.3: {}
ansi-escapes@4.3.2: ansi-escapes@4.3.2:
dependencies: dependencies:
type-fest: 0.21.3 type-fest: 0.21.3
@ -14220,6 +14603,8 @@ snapshots:
array-timsort@1.0.3: {} array-timsort@1.0.3: {}
array-union@2.1.0: {}
asap@2.0.6: {} asap@2.0.6: {}
assert@2.1.0: assert@2.1.0:
@ -14452,6 +14837,10 @@ snapshots:
dependencies: dependencies:
open: 8.4.2 open: 8.4.2
better-path-resolve@1.0.0:
dependencies:
is-windows: 1.0.2
better-result@2.9.2: {} better-result@2.9.2: {}
big-integer@1.6.52: {} big-integer@1.6.52: {}
@ -14636,6 +15025,8 @@ snapshots:
ansi-styles: 4.3.0 ansi-styles: 4.3.0
supports-color: 7.2.0 supports-color: 7.2.0
chardet@2.1.1: {}
chart.js@4.5.1: chart.js@4.5.1:
dependencies: dependencies:
'@kurkle/color': 0.3.4 '@kurkle/color': 0.3.4
@ -14952,6 +15343,8 @@ snapshots:
dependencies: dependencies:
d3-path: 3.1.0 d3-path: 3.1.0
dataloader@1.4.0: {}
db0@0.3.4(@electric-sql/pglite@0.4.1)(mysql2@3.15.3): db0@0.3.4(@electric-sql/pglite@0.4.1)(mysql2@3.15.3):
optionalDependencies: optionalDependencies:
'@electric-sql/pglite': 0.4.1 '@electric-sql/pglite': 0.4.1
@ -15025,6 +15418,8 @@ snapshots:
destroy@1.2.0: {} destroy@1.2.0: {}
detect-indent@6.1.0: {}
detect-libc@1.0.3: {} detect-libc@1.0.3: {}
detect-libc@2.1.2: {} detect-libc@2.1.2: {}
@ -15062,6 +15457,10 @@ snapshots:
diff@9.0.0: {} diff@9.0.0: {}
dir-glob@3.0.1:
dependencies:
path-type: 4.0.0
dlv@1.1.3: {} dlv@1.1.3: {}
dom-serializer@2.0.0: dom-serializer@2.0.0:
@ -15094,6 +15493,8 @@ snapshots:
dotenv@17.4.2: {} dotenv@17.4.2: {}
dotenv@8.6.0: {}
dunder-proto@1.0.1: dunder-proto@1.0.1:
dependencies: dependencies:
call-bind-apply-helpers: 1.0.2 call-bind-apply-helpers: 1.0.2
@ -15174,6 +15575,11 @@ snapshots:
graceful-fs: 4.2.11 graceful-fs: 4.2.11
tapable: 2.3.3 tapable: 2.3.3
enquirer@2.4.1:
dependencies:
ansi-colors: 4.1.3
strip-ansi: 6.0.1
entities@4.5.0: {} entities@4.5.0: {}
entities@7.0.1: {} entities@7.0.1: {}
@ -15743,6 +16149,8 @@ snapshots:
exsolve@1.0.8: {} exsolve@1.0.8: {}
extendable-error@0.1.7: {}
fast-check@3.23.2: fast-check@3.23.2:
dependencies: dependencies:
pure-rand: 6.1.0 pure-rand: 6.1.0
@ -15965,6 +16373,18 @@ snapshots:
fs-constants@1.0.0: fs-constants@1.0.0:
optional: true optional: true
fs-extra@7.0.1:
dependencies:
graceful-fs: 4.2.11
jsonfile: 4.0.0
universalify: 0.1.2
fs-extra@8.1.0:
dependencies:
graceful-fs: 4.2.11
jsonfile: 4.0.0
universalify: 0.1.2
fs.realpath@1.0.0: {} fs.realpath@1.0.0: {}
fsevents@2.3.3: fsevents@2.3.3:
@ -16059,6 +16479,15 @@ snapshots:
globals@15.15.0: {} globals@15.15.0: {}
globby@11.1.0:
dependencies:
array-union: 2.1.0
dir-glob: 3.0.1
fast-glob: 3.3.3
ignore: 5.3.2
merge2: 1.4.1
slash: 3.0.0
globby@16.2.0: globby@16.2.0:
dependencies: dependencies:
'@sindresorhus/merge-streams': 4.0.0 '@sindresorhus/merge-streams': 4.0.0
@ -16192,6 +16621,8 @@ snapshots:
httpxy@0.5.1: {} httpxy@0.5.1: {}
human-id@4.1.3: {}
human-signals@5.0.0: {} human-signals@5.0.0: {}
humanize-ms@1.2.1: humanize-ms@1.2.1:
@ -16404,6 +16835,10 @@ snapshots:
is-stream@3.0.0: {} is-stream@3.0.0: {}
is-subdir@1.2.0:
dependencies:
better-path-resolve: 1.0.0
is-typed-array@1.1.15: is-typed-array@1.1.15:
dependencies: dependencies:
which-typed-array: 1.1.20 which-typed-array: 1.1.20
@ -16583,6 +17018,10 @@ snapshots:
espree: 9.6.1 espree: 9.6.1
semver: 7.7.4 semver: 7.7.4
jsonfile@4.0.0:
optionalDependencies:
graceful-fs: 4.2.11
keyv@4.5.4: keyv@4.5.4:
dependencies: dependencies:
json-buffer: 3.0.1 json-buffer: 3.0.1
@ -16782,6 +17221,8 @@ snapshots:
lodash.memoize@4.1.2: {} lodash.memoize@4.1.2: {}
lodash.startcase@4.4.0: {}
lodash.throttle@4.1.1: {} lodash.throttle@4.1.1: {}
lodash.uniq@4.5.0: {} lodash.uniq@4.5.0: {}
@ -17742,6 +18183,8 @@ snapshots:
orderedmap@2.1.1: {} orderedmap@2.1.1: {}
outdent@0.5.0: {}
oxc-minify@0.94.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): oxc-minify@0.94.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2):
optionalDependencies: optionalDependencies:
'@oxc-minify/binding-android-arm64': 0.94.0 '@oxc-minify/binding-android-arm64': 0.94.0
@ -17856,6 +18299,10 @@ snapshots:
magic-regexp: 0.10.0 magic-regexp: 0.10.0
oxc-parser: 0.94.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) oxc-parser: 0.94.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
p-filter@2.1.0:
dependencies:
p-map: 2.1.0
p-limit@2.3.0: p-limit@2.3.0:
dependencies: dependencies:
p-try: 2.2.0 p-try: 2.2.0
@ -17876,10 +18323,16 @@ snapshots:
dependencies: dependencies:
p-limit: 3.1.0 p-limit: 3.1.0
p-map@2.1.0: {}
p-try@2.2.0: {} p-try@2.2.0: {}
package-json-from-dist@1.0.1: {} package-json-from-dist@1.0.1: {}
package-manager-detector@0.2.11:
dependencies:
quansync: 0.2.11
package-manager-detector@1.6.0: {} package-manager-detector@1.6.0: {}
pako@0.2.9: {} pako@0.2.9: {}
@ -17924,6 +18377,8 @@ snapshots:
lru-cache: 11.3.6 lru-cache: 11.3.6
minipass: 7.1.3 minipass: 7.1.3
path-type@4.0.0: {}
pathe@1.1.2: {} pathe@1.1.2: {}
pathe@2.0.3: {} pathe@2.0.3: {}
@ -17979,6 +18434,8 @@ snapshots:
pify@2.3.0: {} pify@2.3.0: {}
pify@4.0.1: {}
pino-abstract-transport@3.0.0: pino-abstract-transport@3.0.0:
dependencies: dependencies:
split2: 4.2.0 split2: 4.2.0
@ -18264,6 +18721,8 @@ snapshots:
prelude-ls@1.2.1: {} prelude-ls@1.2.1: {}
prettier@2.8.8: {}
prettier@3.8.3: {} prettier@3.8.3: {}
pretty-bytes@5.6.0: {} pretty-bytes@5.6.0: {}
@ -18498,6 +18957,18 @@ snapshots:
sf-symbols-typescript: 2.2.0 sf-symbols-typescript: 2.2.0
use-latest-callback: 0.2.6(react@19.1.0) use-latest-callback: 0.2.6(react@19.1.0)
react-native-copilot@3.3.3(@types/node@22.19.17)(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0):
dependencies:
'@changesets/changelog-github': 0.5.2
'@changesets/cli': 2.31.0(@types/node@22.19.17)
mitt: 3.0.1
react: 19.1.0
react-native: 0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0)
react-native-svg: 15.12.1(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)
transitivePeerDependencies:
- '@types/node'
- encoding
react-native-css-interop@0.2.3(react-native-reanimated@4.1.7(react-native-worklets@0.5.1(@babel/core@7.29.0)(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.4)): react-native-css-interop@0.2.3(react-native-reanimated@4.1.7(react-native-worklets@0.5.1(@babel/core@7.29.0)(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.29.0)(@types/react@19.2.14)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.4)):
dependencies: dependencies:
'@babel/helper-module-imports': 7.28.6 '@babel/helper-module-imports': 7.28.6
@ -18682,6 +19153,13 @@ snapshots:
dependencies: dependencies:
pify: 2.3.0 pify: 2.3.0
read-yaml-file@1.1.0:
dependencies:
graceful-fs: 4.2.11
js-yaml: 3.14.2
pify: 4.0.1
strip-bom: 3.0.0
read-yaml-file@2.1.0: read-yaml-file@2.1.0:
dependencies: dependencies:
js-yaml: 4.1.1 js-yaml: 4.1.1
@ -19133,6 +19611,11 @@ snapshots:
source-map@0.7.6: {} source-map@0.7.6: {}
spawndamnit@3.0.1:
dependencies:
cross-spawn: 7.0.6
signal-exit: 4.1.0
speakingurl@14.0.1: {} speakingurl@14.0.1: {}
split-on-first@1.1.0: {} split-on-first@1.1.0: {}
@ -19218,6 +19701,8 @@ snapshots:
dependencies: dependencies:
ansi-regex: 6.2.2 ansi-regex: 6.2.2
strip-bom@3.0.0: {}
strip-bom@4.0.0: {} strip-bom@4.0.0: {}
strip-comments-strings@1.2.0: {} strip-comments-strings@1.2.0: {}
@ -19406,6 +19891,8 @@ snapshots:
- bare-abort-controller - bare-abort-controller
- react-native-b4a - react-native-b4a
term-size@2.2.1: {}
terminal-link@2.1.1: terminal-link@2.1.1:
dependencies: dependencies:
ansi-escapes: 4.3.2 ansi-escapes: 4.3.2
@ -19657,6 +20144,8 @@ snapshots:
optionalDependencies: optionalDependencies:
oxc-parser: 0.94.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) oxc-parser: 0.94.0(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
universalify@0.1.2: {}
unpipe@1.0.0: {} unpipe@1.0.0: {}
unplugin-auto-import@21.0.0(@nuxt/kit@4.4.4(magicast@0.5.2))(@vueuse/core@14.3.0(vue@3.5.34(typescript@5.9.3))): unplugin-auto-import@21.0.0(@nuxt/kit@4.4.4(magicast@0.5.2))(@vueuse/core@14.3.0(vue@3.5.34(typescript@5.9.3))):