diff --git a/.github/workflows/deploy-functions.yml b/.github/workflows/deploy-functions.yml new file mode 100644 index 0000000..c75afd9 --- /dev/null +++ b/.github/workflows/deploy-functions.yml @@ -0,0 +1,39 @@ +name: Deploy Firebase Functions + +on: + push: + branches: + - main + paths: + - "apps/functions/**" + - "packages/schemas/**" + - ".github/workflows/deploy-functions.yml" + +jobs: + deploy_functions: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "npm" + + - name: Install Dependencies + run: npm ci + + - name: Build Functions + working-directory: apps/functions + run: npm run build + + - name: Deploy to Firebase + uses: firebase/firebase-tools-action@v0.2 + with: + args: deploy --only functions + env: + FIREBASE_CONFIG: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_KEY }} + PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }} diff --git a/.gitignore b/.gitignore index d37e4d1..a71e8ae 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ firebase-debug.log firestore-debug.log -dist \ No newline at end of file +dist + +dev-data \ No newline at end of file diff --git a/apps/frontend/android/app/src/main/java/com/anonymous/lymoapp/MediaModule.kt b/apps/frontend/android/app/src/main/java/com/anonymous/lymoapp/MediaModule.kt index ea20b3c..8664c10 100644 --- a/apps/frontend/android/app/src/main/java/com/anonymous/lymoapp/MediaModule.kt +++ b/apps/frontend/android/app/src/main/java/com/anonymous/lymoapp/MediaModule.kt @@ -69,7 +69,7 @@ class MediaModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaM putString("album", metadata.getString(MediaMetadata.METADATA_KEY_ALBUM)) putDouble("duration", metadata.getLong(MediaMetadata.METADATA_KEY_DURATION).toDouble()) putBoolean("isPlaying", state.state == PlaybackState.STATE_PLAYING) - putString("coverUrl", albumArtBase64) + putString("albumArt", albumArtBase64) } } diff --git a/apps/frontend/apis/addTrack.ts b/apps/frontend/apis/addTrack.ts deleted file mode 100644 index 7002c53..0000000 --- a/apps/frontend/apis/addTrack.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { AddTrackFlowInput, AddTrackFlowOutput } from "@lymo/schemas/function"; -import { runFlow } from "genkit/beta/client"; - -const addTrack = (input: AddTrackFlowInput) => - runFlow({ - url: "https://addtrack-au5g5tbwtq-du.a.run.app", - input, - }); - -export default addTrack; diff --git a/apps/frontend/apis/generateDetail.ts b/apps/frontend/apis/generateDetail.ts deleted file mode 100644 index 656b207..0000000 --- a/apps/frontend/apis/generateDetail.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { - GenerateDetailFlowInput, - GenerateDetailFlowStream, - GenerateDetailFlowOutput, -} from "@lymo/schemas/function"; - -import { streamFlow } from "@/utils/streamFlow"; - -const generateDetail = (input: GenerateDetailFlowInput) => - streamFlow({ - url: "https://generatedetail-au5g5tbwtq-du.a.run.app", - input, - }); - -export default generateDetail; diff --git a/apps/frontend/apis/getLyrics.ts b/apps/frontend/apis/getLyrics.ts deleted file mode 100644 index 3e41f72..0000000 --- a/apps/frontend/apis/getLyrics.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { LyricsDoc } from "@lymo/schemas/doc"; -import { LyricsProvider } from "@lymo/schemas/shared"; -import { collection, doc, type FirebaseFirestoreTypes } from "@react-native-firebase/firestore"; - -import db from "@/core/firestore"; - -interface GetLyricsProps { - trackId: string; - lyricsProvider: LyricsProvider; -} - -export default async function getLyrics({ trackId, lyricsProvider }: GetLyricsProps) { - const tracksCollection = collection(db, "tracks"); - const trackDoc = doc(tracksCollection, trackId); - const lyricsCollection = collection(trackDoc, "lyrics"); - const lyricsDoc = doc( - lyricsCollection, - lyricsProvider - ) as FirebaseFirestoreTypes.DocumentReference; - - const lyricsData = (await lyricsDoc.get()).data(); - - if (!lyricsData) throw new Error("가사를 찾을 수 없습니다."); - - return lyricsData; -} diff --git a/apps/frontend/apis/getNewTracks.ts b/apps/frontend/apis/getNewTracks.ts index 6c55dfb..58c77b8 100644 --- a/apps/frontend/apis/getNewTracks.ts +++ b/apps/frontend/apis/getNewTracks.ts @@ -1,4 +1,4 @@ -import type { TrackDoc } from "@lymo/schemas/doc"; +import type { Track } from "@lymo/schemas/doc"; import { collection, getDocs, @@ -11,9 +11,9 @@ import { import db from "@/core/firestore"; export default async function getNewTracks() { - const tracksCollection = collection(db, "tracks"); - const q = query(tracksCollection, orderBy("createdAt", "desc"), limit(10)); - const trackDocs = (await getDocs(q)) as FirebaseFirestoreTypes.QuerySnapshot; + const trackCollectionRef = collection(db, "tracks"); + const q = query(trackCollectionRef, orderBy("createdAt", "desc"), limit(10)); + const trackDocs = (await getDocs(q)) as FirebaseFirestoreTypes.QuerySnapshot; const result = trackDocs.docs.map((doc) => ({ ...doc.data(), id: doc.id })); return result; diff --git a/apps/frontend/apis/getPopularTracks.ts b/apps/frontend/apis/getPopularTracks.ts index 36e901c..a2b2cdd 100644 --- a/apps/frontend/apis/getPopularTracks.ts +++ b/apps/frontend/apis/getPopularTracks.ts @@ -1,4 +1,4 @@ -import type { TrackDoc } from "@lymo/schemas/doc"; +import type { Track } from "@lymo/schemas/doc"; import { collection, getDocs, @@ -11,14 +11,14 @@ import { import db from "@/core/firestore"; export default async function getPopularTracks() { - const tracksCollection = collection(db, "tracks"); + const trackCollectionRef = collection(db, "tracks"); const q = query( - tracksCollection, - orderBy("play", "desc"), + trackCollectionRef, + orderBy("stats.viewCount", "desc"), orderBy("createdAt", "asc"), limit(20) ); - const trackDocs = (await getDocs(q)) as FirebaseFirestoreTypes.QuerySnapshot; + const trackDocs = (await getDocs(q)) as FirebaseFirestoreTypes.QuerySnapshot; const result = trackDocs.docs.map((doc) => ({ ...doc.data(), id: doc.id })); return result; diff --git a/apps/frontend/apis/getProvider.ts b/apps/frontend/apis/getProvider.ts deleted file mode 100644 index b33d1df..0000000 --- a/apps/frontend/apis/getProvider.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { ProviderDoc } from "@lymo/schemas/doc"; -import { collection, doc, type FirebaseFirestoreTypes } from "@react-native-firebase/firestore"; - -import db from "@/core/firestore"; - -interface GetProviderProps { - trackId: string; -} - -export default async function getProviders({ trackId }: GetProviderProps) { - const tracksCollection = collection(db, "tracks"); - const trackDoc = doc(tracksCollection, trackId); - const ProvidersCollection = collection( - trackDoc, - "providers" - ) as FirebaseFirestoreTypes.CollectionReference; - - const providerData = (await ProvidersCollection.get()).docs.map((doc) => ({ - ...doc.data(), - id: doc.id, - })); - return providerData; -} diff --git a/apps/frontend/apis/getStoryByTrackId.ts b/apps/frontend/apis/getStoryByTrackId.ts new file mode 100644 index 0000000..d2a769a --- /dev/null +++ b/apps/frontend/apis/getStoryByTrackId.ts @@ -0,0 +1,32 @@ +import type { Story } from "@lymo/schemas/doc"; +import { Language } from "@lymo/schemas/shared"; +import { + collection, + getDocs, + limit, + query, + where, + type FirebaseFirestoreTypes, +} from "@react-native-firebase/firestore"; + +import db from "@/core/firestore"; + +interface GetStoryByTrackIdParams { + trackId: string; + language: Language; +} + +export default async function getStoryByTrackId({ trackId, language }: GetStoryByTrackIdParams) { + const storyCollectionRef = collection(db, "stories"); + const q = query( + storyCollectionRef, + where("language", "==", language), + where("trackId", "==", trackId), + limit(1) + ); + + const storyDoc = (await getDocs(q)).docs[0] as + | FirebaseFirestoreTypes.QueryDocumentSnapshot + | undefined; + return storyDoc?.data() ?? null; +} diff --git a/apps/frontend/apis/getTrack.ts b/apps/frontend/apis/getTrack.ts deleted file mode 100644 index 9df68a2..0000000 --- a/apps/frontend/apis/getTrack.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { TrackDoc } from "@lymo/schemas/doc"; -import { collection, doc, type FirebaseFirestoreTypes } from "@react-native-firebase/firestore"; - -import db from "@/core/firestore"; - -interface GetTrackProps { - trackId: string; -} - -export default async function getTrack({ trackId }: GetTrackProps) { - const tracksCollection = collection(db, "tracks"); - const trackDoc = doc( - tracksCollection, - trackId - ) as FirebaseFirestoreTypes.DocumentReference; - - const trackData = (await trackDoc.get()).data(); - - if (!trackData) throw new Error("곡을 찾을 수 없습니다."); - - return trackData; -} diff --git a/apps/frontend/apis/getTrackById.ts b/apps/frontend/apis/getTrackById.ts new file mode 100644 index 0000000..2a35fd8 --- /dev/null +++ b/apps/frontend/apis/getTrackById.ts @@ -0,0 +1,13 @@ +import type { Track } from "@lymo/schemas/doc"; +import { collection, doc, type FirebaseFirestoreTypes } from "@react-native-firebase/firestore"; + +import db from "@/core/firestore"; + +export default async function getTrackById(trackId: string) { + const trackCollectionRef = collection(db, "tracks"); + const trackDocRef = doc( + trackCollectionRef, + trackId + ) as FirebaseFirestoreTypes.DocumentReference; + return (await trackDocRef.get()).data() ?? null; +} diff --git a/apps/frontend/apis/getTrackDetail.ts b/apps/frontend/apis/getTrackDetail.ts deleted file mode 100644 index 409e4a3..0000000 --- a/apps/frontend/apis/getTrackDetail.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { TrackDetailDoc } from "@lymo/schemas/doc"; -import { Language } from "@lymo/schemas/shared"; -import { collection, doc, type FirebaseFirestoreTypes } from "@react-native-firebase/firestore"; - -import db from "@/core/firestore"; - -interface GetTrackDetailProps { - trackId: string; - providerId: string; - language: Language; -} - -export default async function getTrackDetail({ - trackId, - providerId, - language, -}: GetTrackDetailProps) { - const tracksCollection = collection(db, "tracks"); - const trackDoc = doc(tracksCollection, trackId); - const ProvidersCollection = collection(trackDoc, "providers"); - const providerDoc = doc(ProvidersCollection, providerId); - const DetailsCollection = collection(providerDoc, "details"); - const detailDoc = doc( - DetailsCollection, - language - ) as FirebaseFirestoreTypes.DocumentReference; - - const trackDetailData = (await detailDoc.get()).data(); - - if (!trackDetailData) return null; - - return trackDetailData; -} diff --git a/apps/frontend/apis/retrieveTrack.ts b/apps/frontend/apis/retrieveTrack.ts new file mode 100644 index 0000000..584fc46 --- /dev/null +++ b/apps/frontend/apis/retrieveTrack.ts @@ -0,0 +1,9 @@ +import type { RetrieveTrackInput, RetrieveTrackOutput } from "@lymo/schemas/functions"; +import { httpsCallable } from "@react-native-firebase/functions"; + +import functions from "@/core/functions"; + +export const retrieveTrack = httpsCallable( + functions, + "retrieveTrack" +); diff --git a/apps/frontend/app/_layout.tsx b/apps/frontend/app/_layout.tsx index cad9d0e..735102a 100644 --- a/apps/frontend/app/_layout.tsx +++ b/apps/frontend/app/_layout.tsx @@ -13,6 +13,9 @@ import { SettingProvider } from "@/contexts/useSettingStore"; import { SyncProvider } from "@/contexts/useSyncStore"; import { TrackSourceProvider } from "@/contexts/useTrackSourceStore"; +import "@/core/firestore"; +import "@/core/functions"; + const queryClient = new QueryClient(); export default function RootLayout() { diff --git a/apps/frontend/app/player/index.tsx b/apps/frontend/app/player/index.tsx index 64f0c65..7090f7e 100644 --- a/apps/frontend/app/player/index.tsx +++ b/apps/frontend/app/player/index.tsx @@ -1,12 +1,11 @@ import { useQueryErrorResetBoundary } from "@tanstack/react-query"; import { Redirect } from "expo-router"; -import { Suspense } from "react"; import { ErrorBoundary } from "react-error-boundary"; import { View } from "react-native"; import ErrorIndicator from "@/components/player/ErrorIndicator"; -import LoadingIndicator from "@/components/player/LoadingIndicator"; -import { DeviceTrackPlayer, ManualTrackPlayer } from "@/components/player/Player"; +import FromDevice from "@/components/player/Player/FromDevice"; +import FromManual from "@/components/player/Player/FromManual"; import { useTrackSourceStore } from "@/contexts/useTrackSourceStore"; export default function Player() { @@ -19,10 +18,16 @@ export default function Player() { return ( - }> - {trackSource.from === "manual" && } - {trackSource.from === "device" && } - + {trackSource.from === "manual" && ( + + )} + {trackSource.from === "device" && ( + + )} ); diff --git a/apps/frontend/components/home/DeviceMediaDetection/DeviceMediaDetection.tsx b/apps/frontend/components/home/DeviceMediaDetection/DeviceMediaDetection.tsx index 1a4629c..6bb1e66 100644 --- a/apps/frontend/components/home/DeviceMediaDetection/DeviceMediaDetection.tsx +++ b/apps/frontend/components/home/DeviceMediaDetection/DeviceMediaDetection.tsx @@ -46,7 +46,7 @@ export default function DeviceMediaDetection() { {/* 커버 이미지 */} - + {/* 그라데이션 오버레이 */} diff --git a/apps/frontend/components/home/NewTracksSection/NewTracksSection.tsx b/apps/frontend/components/home/NewTracksSection/NewTracksSection.tsx index 364b8d7..5e0819c 100644 --- a/apps/frontend/components/home/NewTracksSection/NewTracksSection.tsx +++ b/apps/frontend/components/home/NewTracksSection/NewTracksSection.tsx @@ -1,4 +1,5 @@ import MaterialIcons from "@expo/vector-icons/MaterialIcons"; +import { Track } from "@lymo/schemas/doc"; import { Link } from "expo-router"; import { View, Text, FlatList } from "react-native"; @@ -15,10 +16,10 @@ export default function NewTracksSection() { const { setTrackSource } = useTrackSourceStore(); const { setIsSynced } = useSyncStore(); - const handlePlayTrack = (track: { id: string; title: string; coverUrl: string }) => { + const handlePlayTrack = (trackId: string, track: Track) => { setTrackSource({ from: "manual", - track: track, + track: { ...track, id: trackId }, }); setIsSynced(false); }; @@ -41,10 +42,8 @@ export default function NewTracksSection() { - handlePlayTrack({ id: track.id, title: track.title, coverUrl: track.coverUrl }) - } + albumArt={track.albumArt} + onPress={() => handlePlayTrack(track.id, track)} /> )} diff --git a/apps/frontend/components/home/PopularTracksSection/PopularTracksSection.tsx b/apps/frontend/components/home/PopularTracksSection/PopularTracksSection.tsx index 43a620f..2b6b79b 100644 --- a/apps/frontend/components/home/PopularTracksSection/PopularTracksSection.tsx +++ b/apps/frontend/components/home/PopularTracksSection/PopularTracksSection.tsx @@ -1,4 +1,5 @@ import MaterialIcons from "@expo/vector-icons/MaterialIcons"; +import { Track } from "@lymo/schemas/doc"; import { Link } from "expo-router"; import { View, Text, FlatList, ScrollView } from "react-native"; @@ -15,10 +16,10 @@ export default function PopularTracksSection() { const { setTrackSource } = useTrackSourceStore(); const { setIsSynced } = useSyncStore(); - const handlePlayTrack = (track: { id: string; title: string; coverUrl: string }) => { + const handlePlayTrack = (trackId: string, track: Track) => { setTrackSource({ from: "manual", - track: track, + track: { ...track, id: trackId }, }); setIsSynced(false); }; @@ -47,11 +48,9 @@ export default function PopularTracksSection() { - handlePlayTrack({ id: track.id, title: track.title, coverUrl: track.coverUrl }) - } + artists={track.artists} + albumArt={track.albumArt} + onPress={() => handlePlayTrack(track.id, track)} /> )} diff --git a/apps/frontend/components/home/Track/CompactTrack.tsx b/apps/frontend/components/home/Track/CompactTrack.tsx index 06dea7e..83206a8 100644 --- a/apps/frontend/components/home/Track/CompactTrack.tsx +++ b/apps/frontend/components/home/Track/CompactTrack.tsx @@ -4,15 +4,15 @@ import { Image, Text, TouchableOpacity } from "react-native"; import { styles } from "./CompactTrack.styles"; interface CompactTrackProps { - coverUrl: string; + albumArt: string; title: string; onPress?: () => void; } -export default function CompactTrack({ coverUrl, title, onPress }: CompactTrackProps) { +export default function CompactTrack({ albumArt, title, onPress }: CompactTrackProps) { return ( - + {title} diff --git a/apps/frontend/components/home/Track/NormalTrack.tsx b/apps/frontend/components/home/Track/NormalTrack.tsx index f37cd9d..43b3afe 100644 --- a/apps/frontend/components/home/Track/NormalTrack.tsx +++ b/apps/frontend/components/home/Track/NormalTrack.tsx @@ -4,22 +4,22 @@ import { Image, Text, TouchableOpacity, View } from "react-native"; import { styles } from "./NormalTrack.styles"; interface NormalTrackProps { - coverUrl: string; + albumArt: string; title: string; - artist: string[]; + artists: string[]; onPress?: () => void; } -export default function NormalTrack({ coverUrl, title, artist, onPress }: NormalTrackProps) { +export default function NormalTrack({ albumArt, title, artists, onPress }: NormalTrackProps) { return ( - + {title} - {artist.join(", ")} + {artists.join(", ")} diff --git a/apps/frontend/components/player/LoadingIndicator/LoadingIndicator.tsx b/apps/frontend/components/player/LoadingIndicator/LoadingIndicator.tsx index 94a8b48..893b593 100644 --- a/apps/frontend/components/player/LoadingIndicator/LoadingIndicator.tsx +++ b/apps/frontend/components/player/LoadingIndicator/LoadingIndicator.tsx @@ -14,16 +14,16 @@ interface LoadingIndicatorProps { title?: string; artist?: string; album?: string | null; - coverUrl?: string; + albumArt?: string; } export default function LoadingIndicator({ title, artist, album, - coverUrl, + albumArt, }: LoadingIndicatorProps) { - const { data: coverColor } = useCoverColorQuery(coverUrl); + const { data: coverColor } = useCoverColorQuery(albumArt); const headerBackgroundColor = useMemo( () => mixColors([coverColor ?? "#000000", "#000000CC"]), [coverColor] @@ -46,7 +46,7 @@ export default function LoadingIndicator({ }} > {/* 곡 메타데이터 및 설명 */} - + {/* 가사 */} diff --git a/apps/frontend/components/player/Lyrics/Lyrics.tsx b/apps/frontend/components/player/Lyrics/Lyrics.tsx index 7387493..9d659ec 100644 --- a/apps/frontend/components/player/Lyrics/Lyrics.tsx +++ b/apps/frontend/components/player/Lyrics/Lyrics.tsx @@ -1,4 +1,4 @@ -import { LyricsProvider } from "@lymo/schemas/shared"; +import { Lyric, LyricsProvider } from "@lymo/schemas/shared"; import { Ref, useMemo } from "react"; import { Text, View } from "react-native"; @@ -8,13 +8,13 @@ import { useSettingStore } from "@/contexts/useSettingStore"; import { useSyncStore } from "@/contexts/useSyncStore"; import useDeviceMediaTimestamp from "@/hooks/useDeviceMediaTimestamp"; import useTrackKey from "@/hooks/useTrackKey"; +import { Section } from "@/types/track"; import getLyricsProviderName from "@/utils/getLyricsProviderName"; -import { PostLyricsResult } from "@/utils/processLyrics"; import { styles } from "./Lyrics.styles"; interface LyricsProps { - lyrics: PostLyricsResult; + lyrics: Section[]; lyricsProvider?: LyricsProvider; activeSentenceRef: Ref; } @@ -38,21 +38,21 @@ export default function Lyrics({ lyrics, lyricsProvider, activeSentenceRef }: Ly return ( - {lyrics.map((paragraph, paragraphIndex) => ( + {lyrics.map((section, sectionIndex) => ( - {paragraph.sentences.map((sentence, sentenceIndex) => { - const isActive = isSynced && isActiveSentence(sentence, adjustedTimestamp); - const sentenceKey = `${paragraphIndex}-${sentenceIndex}`; + {section.lyrics.map((lyric, lyricIndex) => { + const isActive = isSynced && isActiveSentence(lyric, adjustedTimestamp); + const sentenceKey = `${sectionIndex}-${lyricIndex}`; return ( @@ -71,12 +71,10 @@ export default function Lyrics({ lyrics, lyricsProvider, activeSentenceRef }: Ly ); } -const isActiveParagraph = (paragraph: PostLyricsResult[number]["sentences"], timestamp: number) => - paragraph.length > 0 && - paragraph[0].start <= timestamp && - timestamp < paragraph[paragraph.length - 1].end; +const isActiveParagraph = (section: Section, timestamp: number) => + section.lyrics.length > 0 && + section.lyrics[0].start <= timestamp && + timestamp < section.lyrics[section.lyrics.length - 1].end; -const isActiveSentence = ( - sentence: PostLyricsResult[number]["sentences"][number], - timestamp: number -) => sentence.start <= timestamp && timestamp < sentence.end; +const isActiveSentence = (lyric: Lyric, timestamp: number) => + lyric.start <= timestamp && timestamp < lyric.end; diff --git a/apps/frontend/components/player/LyricsGeneratingIndicator/LyricsGeneratingIndicator.styles.ts b/apps/frontend/components/player/LyricsGeneratingIndicator/LyricsGeneratingIndicator.styles.ts deleted file mode 100644 index d8c7b9a..0000000 --- a/apps/frontend/components/player/LyricsGeneratingIndicator/LyricsGeneratingIndicator.styles.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { StyleSheet } from "react-native"; - -import { colors } from "@/constants/colors"; - -export const styles = StyleSheet.create({ - container: { - flex: 1, - flexDirection: "row", - justifyContent: "center", - alignItems: "center", - gap: 12, - minHeight: 400, - }, - - message: { - color: colors.onBackground, - textAlign: "center", - fontSize: 16, - }, -}); diff --git a/apps/frontend/components/player/LyricsGeneratingIndicator/LyricsGeneratingIndicator.tsx b/apps/frontend/components/player/LyricsGeneratingIndicator/LyricsGeneratingIndicator.tsx deleted file mode 100644 index 3e1958a..0000000 --- a/apps/frontend/components/player/LyricsGeneratingIndicator/LyricsGeneratingIndicator.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { ActivityIndicator, Text, View } from "react-native"; - -import { colors } from "@/constants/colors"; - -import { styles } from "./LyricsGeneratingIndicator.styles"; - -export default function LyricsGeneratingIndicator() { - return ( - - - AI가 열심히 가사를 해석하고 있어요. - - ); -} diff --git a/apps/frontend/components/player/LyricsGeneratingIndicator/index.ts b/apps/frontend/components/player/LyricsGeneratingIndicator/index.ts deleted file mode 100644 index 9c27cb5..0000000 --- a/apps/frontend/components/player/LyricsGeneratingIndicator/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./LyricsGeneratingIndicator"; diff --git a/apps/frontend/components/player/Paragraph/Paragraph.styles.ts b/apps/frontend/components/player/Paragraph/Paragraph.styles.ts index 0d76364..03cdad9 100644 --- a/apps/frontend/components/player/Paragraph/Paragraph.styles.ts +++ b/apps/frontend/components/player/Paragraph/Paragraph.styles.ts @@ -12,13 +12,13 @@ export const styles = StyleSheet.create({ overflow: "hidden", }, - summaryWrapper: { + noteWrapper: { padding: 16, borderRadius: 16, backgroundColor: `${colors.white}80`, }, - summary: { + note: { fontSize: 14, color: colors.black, }, diff --git a/apps/frontend/components/player/Paragraph/Paragraph.tsx b/apps/frontend/components/player/Paragraph/Paragraph.tsx index c13349e..d1af070 100644 --- a/apps/frontend/components/player/Paragraph/Paragraph.tsx +++ b/apps/frontend/components/player/Paragraph/Paragraph.tsx @@ -3,17 +3,19 @@ import { View, Text, Animated } from "react-native"; import Reanimated, { Easing, LinearTransition } from "react-native-reanimated"; import { colors } from "@/constants/colors"; +import { useTypingAnimation } from "@/hooks/useTypingAnimation"; import { styles } from "./Paragraph.styles"; interface ParagraphProps { - summary: string | null; + note: string | null; active: boolean; children: React.ReactNode; } -const Paragraph = memo(({ summary, active, children }: ParagraphProps) => { - const parsedSummary = summary === "null" ? null : summary; +const Paragraph = memo(({ note, active, children }: ParagraphProps) => { + const parsedNote = note === "null" ? null : note; + const displayedNote = useTypingAnimation(parsedNote); const progress = useRef(new Animated.Value(0)).current; @@ -32,12 +34,12 @@ const Paragraph = memo(({ summary, active, children }: ParagraphProps) => { return ( - {parsedSummary && ( + {parsedNote && ( - {parsedSummary} + {displayedNote} )} {children} diff --git a/apps/frontend/components/player/Player/DetailQuery.tsx b/apps/frontend/components/player/Player/DetailQuery.tsx deleted file mode 100644 index a980984..0000000 --- a/apps/frontend/components/player/Player/DetailQuery.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { ProviderDoc, TrackDoc } from "@lymo/schemas/doc"; -import { LyricsProvider } from "@lymo/schemas/shared"; - -import { useSettingStore } from "@/contexts/useSettingStore"; -import useTrackDetailQuery from "@/hooks/queries/useTrackDetailQuery"; - -import LyricsQuery from "./LyricsQuery"; - -interface DetailQueryProps { - track: TrackDoc; - trackId: string; - provider: ProviderDoc; - providerId: string; - lyricsProvider: LyricsProvider; -} - -export default function DetailQuery({ - track, - trackId, - provider, - providerId, - lyricsProvider, -}: DetailQueryProps) { - const { setting } = useSettingStore(); - - const { data: trackDetail, error: trackDetailError } = useTrackDetailQuery({ - trackId, - providerId, - language: setting.defaultLanguage, - }); - - if (trackDetailError) throw trackDetailError; - - return ( - - ); -} diff --git a/apps/frontend/components/player/Player/DeviceTrackPlayer.tsx b/apps/frontend/components/player/Player/DeviceTrackPlayer.tsx deleted file mode 100644 index 00a76f8..0000000 --- a/apps/frontend/components/player/Player/DeviceTrackPlayer.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import useAddTrackQuery from "@/hooks/queries/useAddTrackQuery"; - -import StreamingQuery from "./StreamingQuery"; - -interface DeviceTrackPlayerProps { - title: string; - artist: string; - duration: number; -} - -export default function DeviceTrackPlayer({ title, artist, duration }: DeviceTrackPlayerProps) { - const { data: addTrackResult, error: addTrackError } = useAddTrackQuery({ - title, - artist, - duration, - }); - - if (addTrackError) throw addTrackError; - - return ( - - ); -} diff --git a/apps/frontend/components/player/Player/FromDevice.tsx b/apps/frontend/components/player/Player/FromDevice.tsx new file mode 100644 index 0000000..9328a01 --- /dev/null +++ b/apps/frontend/components/player/Player/FromDevice.tsx @@ -0,0 +1,27 @@ +import { useSettingStore } from "@/contexts/useSettingStore"; +import useRetrieveTrack from "@/hooks/queries/useRetrieveTrack"; +import useStoryQuery from "@/hooks/queries/useStoryQuery"; + +import PlayerContent from "./PlayerContent"; +import StoryRequest from "./StoryRequest"; + +interface FromDeviceProps { + title: string; + artist: string; + durationInSeconds: number; +} + +export default function FromDevice(props: FromDeviceProps) { + const { setting } = useSettingStore(); + + const { data: track } = useRetrieveTrack(props); + const { data: story } = useStoryQuery({ + trackId: track?.id, + language: setting.defaultLanguage, + enabled: !!track?.id, + }); + + if (story !== null) return ; + + return ; +} diff --git a/apps/frontend/components/player/Player/FromManual.tsx b/apps/frontend/components/player/Player/FromManual.tsx new file mode 100644 index 0000000..38ba715 --- /dev/null +++ b/apps/frontend/components/player/Player/FromManual.tsx @@ -0,0 +1,24 @@ +import { Track } from "@lymo/schemas/doc"; + +import { useSettingStore } from "@/contexts/useSettingStore"; +import useStoryQuery from "@/hooks/queries/useStoryQuery"; + +import PlayerContent from "./PlayerContent"; +import StoryRequest from "./StoryRequest"; + +interface FromFromManualProps { + trackId: string; + track: Track; +} + +export default function FromManual({ trackId, track }: FromFromManualProps) { + const { setting } = useSettingStore(); + const { data: story } = useStoryQuery({ + trackId, + language: setting.defaultLanguage, + }); + + if (story === null) return ; + + return ; +} diff --git a/apps/frontend/components/player/Player/LyricsQuery.tsx b/apps/frontend/components/player/Player/LyricsQuery.tsx deleted file mode 100644 index 1d4a28b..0000000 --- a/apps/frontend/components/player/Player/LyricsQuery.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { ProviderDoc, TrackDetailDoc, TrackDoc } from "@lymo/schemas/doc"; -import { LyricsProvider } from "@lymo/schemas/shared"; - -import useLyricsQuery from "@/hooks/queries/useLyricsQuery"; - -import PlayerContent from "./PlayerContent"; -import StreamingQuery from "./StreamingQuery"; - -interface LyricsQueryProps { - track: TrackDoc; - trackId: string; - provider?: ProviderDoc; - trackDetail?: TrackDetailDoc; - lyricsProvider: LyricsProvider; -} - -export default function LyricsQuery({ - track, - trackId, - provider, - trackDetail, - lyricsProvider, -}: LyricsQueryProps) { - const { data: lyrics, error } = useLyricsQuery({ trackId, lyricsProvider }); - - if (error) throw error; - - if (trackDetail && provider) - return ( - - ); - else - return ( - - ); -} diff --git a/apps/frontend/components/player/Player/ManualTrackPlayer.tsx b/apps/frontend/components/player/Player/ManualTrackPlayer.tsx deleted file mode 100644 index eebb3fb..0000000 --- a/apps/frontend/components/player/Player/ManualTrackPlayer.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import useTrackQuery from "@/hooks/queries/useTrackQuery"; - -import ProvidersQuery from "./ProvidersQuery"; - -interface ManualTrackPlayerProps { - trackId: string; -} - -export default function ManualTrackPlayer({ trackId }: ManualTrackPlayerProps) { - const { data: track, error } = useTrackQuery({ trackId }); - - if (error) throw error; - - // TODO: lyricsProvider 우선 순위 결정 - const lyricsProvider = track.lyricsProviders[0]; - - return ; -} diff --git a/apps/frontend/components/player/Player/PlayerContent.tsx b/apps/frontend/components/player/Player/PlayerContent.tsx index c45f250..47c4e69 100644 --- a/apps/frontend/components/player/Player/PlayerContent.tsx +++ b/apps/frontend/components/player/Player/PlayerContent.tsx @@ -1,40 +1,29 @@ -import type { LyricsDoc, ProviderDoc, TrackDetailDoc, TrackDoc } from "@lymo/schemas/doc"; -import { LyricsProvider } from "@lymo/schemas/shared"; +import { BaseStoryFields, GeneratedStoryFields, Track } from "@lymo/schemas/doc"; import { Stack } from "expo-router"; import { useMemo, useRef } from "react"; -import { ScrollView, View } from "react-native"; +import { ActivityIndicator, ScrollView, View } from "react-native"; import Lyrics from "@/components/player/Lyrics"; import MoveToCurrent from "@/components/player/MoveToCurrent"; -import ProviderInformation from "@/components/player/ProviderInformation"; import StartTrack from "@/components/player/StartTrack"; import Summary from "@/components/player/Summary"; import Header from "@/components/shared/Header"; +import { colors } from "@/constants/colors"; import useCoverColorQuery from "@/hooks/queries/useCoverColorQuery"; import useYOffsetInWindow from "@/hooks/useActiveSentenceY"; -import useScrollPositionPreservation from "@/hooks/useScrollPositionPreservation"; +import useProcessLyrics from "@/hooks/useProcessLyrics"; import useTracking from "@/hooks/useTracking"; import mixColors from "@/utils/mixColors"; -import processLyrics from "@/utils/processLyrics"; import { styles } from "./Player.styles"; -interface TrackPlayerProps { - track: TrackDoc; - lyrics: LyricsDoc["lyrics"]; - lyricsProvider: LyricsProvider; - provider?: ProviderDoc; - trackDetail: Omit & { lyricsProvider?: LyricsProvider }; +interface PlayerContentProps { + track?: Track; + story?: BaseStoryFields & Partial; } -export default function PlayerContent({ - track, - lyrics, - lyricsProvider, - provider, - trackDetail, -}: TrackPlayerProps) { - const { data: coverColor } = useCoverColorQuery(track.coverUrl); +export default function PlayerContent({ track, story }: PlayerContentProps) { + const { data: coverColor } = useCoverColorQuery(track?.albumArt); const headerBackgroundColor = useMemo( () => mixColors([coverColor ?? "#000000", "#000000CC"]), [coverColor] @@ -50,7 +39,6 @@ export default function PlayerContent({ const { isTrackingMode, scrollViewRef, - scrollYRef, handleScrollViewScroll, handleScrollEnd, handleMoveToCurrent, @@ -59,24 +47,8 @@ export default function PlayerContent({ track, }); - // 스크롤 위치 보존 로직 - const { contentRef: lyricsContainerRef, handleLayout: handleLyricsLayout } = - useScrollPositionPreservation({ - scrollViewRef, - scrollYRef, - }); - // 처리된 가사 데이터 - const processedLyrics = useMemo( - () => - processLyrics({ - rawLyrics: lyrics, - lyricsSplitIndices: trackDetail.lyricsSplitIndices, - translations: trackDetail.translations, - paragraphSummaries: trackDetail.paragraphSummaries, - }), - [lyrics, trackDetail] - ); + const processedLyrics = useProcessLyrics({ story, track }); return ( <> @@ -89,26 +61,31 @@ export default function PlayerContent({ > {/* 곡 메타데이터 및 설명 */} - {/* 제공자 정보 */} - - {/* 가사 */} - - + + + ) : ( + - + )} {/* 현재 가사로 이동 */} diff --git a/apps/frontend/components/player/Player/ProvidersQuery.tsx b/apps/frontend/components/player/Player/ProvidersQuery.tsx deleted file mode 100644 index 54f7392..0000000 --- a/apps/frontend/components/player/Player/ProvidersQuery.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { TrackDetailDoc, TrackDoc } from "@lymo/schemas/doc"; -import { LyricsProvider } from "@lymo/schemas/shared"; - -import { useSettingStore } from "@/contexts/useSettingStore"; -import useProvidersQuery from "@/hooks/queries/useProvidersQuery"; - -import DetailQuery from "./DetailQuery"; -import LyricsQuery from "./LyricsQuery"; - -interface ProvidersQueryProps { - track: TrackDoc; - trackId: string; - trackDetail?: TrackDetailDoc; - lyricsProvider: LyricsProvider; - providerId?: string; -} - -export default function ProvidersQuery({ - track, - trackId, - trackDetail, - lyricsProvider, - providerId, -}: ProvidersQueryProps) { - const { setting } = useSettingStore(); - const { data: providers, error } = useProvidersQuery({ trackId }); - - if (error) throw error; - - if (providers.length === 0) - return ( - - ); - - // 우선순위에 따라 provider 결정 - const provider = - providers.find((p) => p.id === providerId) ?? - providers.find((p) => p.id === setting.defaultLLMModel) ?? - providers[0]; - - return ( - - ); -} diff --git a/apps/frontend/components/player/Player/StoryRequest.tsx b/apps/frontend/components/player/Player/StoryRequest.tsx new file mode 100644 index 0000000..87ac7f7 --- /dev/null +++ b/apps/frontend/components/player/Player/StoryRequest.tsx @@ -0,0 +1,33 @@ +import { BaseStoryFields, GeneratedStoryFields, Track } from "@lymo/schemas/doc"; + +import { useSettingStore } from "@/contexts/useSettingStore"; +import useRequestTrack from "@/hooks/queries/useRequestStoryQuery"; + +import PlayerContent from "./PlayerContent"; + +type RequestTrackProps = ( + | { + trackId: string; + } + | { + title: string; + artist: string; + durationInSeconds: number; + } +) & { track?: Track }; + +export default function StoryRequest({ track, ...props }: RequestTrackProps) { + const { setting } = useSettingStore(); + const { data, error } = useRequestTrack({ ...props, language: setting.defaultLanguage }); + + if (error) throw error; + + // "IN_PROGRESS"이거나 "COMPLETED" 상태일 때만 story 데이터를 전달 + let story: (BaseStoryFields & Partial) | undefined = undefined; + if (data?.status === "IN_PROGRESS" || data?.status === "COMPLETED") { + const { status, ...storyData } = data; + story = storyData; + } + + return ; +} diff --git a/apps/frontend/components/player/Player/StreamingQuery.tsx b/apps/frontend/components/player/Player/StreamingQuery.tsx deleted file mode 100644 index 9528c26..0000000 --- a/apps/frontend/components/player/Player/StreamingQuery.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { LyricsDoc, TrackDoc } from "@lymo/schemas/doc"; -import { LyricsProvider } from "@lymo/schemas/shared"; - -import useGenerateDetailQuery from "@/hooks/queries/useGenerateDetailQuery"; - -import PlayerContent from "./PlayerContent"; -import ProvidersQuery from "./ProvidersQuery"; - -interface StreamingQueryProps { - track: TrackDoc; - trackId: string; - lyrics: LyricsDoc["lyrics"]; - lyricsProvider: LyricsProvider; -} - -export default function StreamingQuery({ - track, - trackId, - lyrics, - lyricsProvider, -}: StreamingQueryProps) { - const { data: generateDetailResult, error } = useGenerateDetailQuery(trackId, lyricsProvider); - - if (error) throw error; - if (!generateDetailResult) throw new Error("곡 상세 정보를 불러올 수 없습니다."); - - if (generateDetailResult.exists) - return ( - - ); - - return ( - - ); -} diff --git a/apps/frontend/components/player/Player/index.ts b/apps/frontend/components/player/Player/index.ts index f99174b..6402332 100644 --- a/apps/frontend/components/player/Player/index.ts +++ b/apps/frontend/components/player/Player/index.ts @@ -1,2 +1 @@ -export { default as DeviceTrackPlayer } from "./DeviceTrackPlayer"; -export { default as ManualTrackPlayer } from "./ManualTrackPlayer"; +export { default as StoryRequest } from "./StoryRequest"; diff --git a/apps/frontend/components/player/ProviderInformation/ProviderInformation.styles.ts b/apps/frontend/components/player/ProviderInformation/ProviderInformation.styles.ts deleted file mode 100644 index 0667b41..0000000 --- a/apps/frontend/components/player/ProviderInformation/ProviderInformation.styles.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { StyleSheet } from "react-native"; - -import { colors } from "@/constants/colors"; - -export const styles = StyleSheet.create({ - container: { - paddingHorizontal: 20, - display: "flex", - flexDirection: "row", - alignItems: "center", - gap: 12, - height: 40, - }, - - providerNameWrapper: { - borderRadius: 8, - display: "flex", - flexDirection: "row", - alignItems: "center", - gap: 8, - }, - - providerNameIcon: { - color: colors.onBackground, - }, - - providerNameText: { - fontSize: 16, - fontWeight: 700, - color: colors.onBackground, - }, - - divider: { - width: 2, - height: 2, - borderRadius: 1, - backgroundColor: colors.onBackgroundSubtle, - }, - - providerUpdatedAtText: { - fontSize: 16, - color: colors.onBackgroundSubtle, - }, -}); diff --git a/apps/frontend/components/player/ProviderInformation/ProviderInformation.tsx b/apps/frontend/components/player/ProviderInformation/ProviderInformation.tsx deleted file mode 100644 index e37e4eb..0000000 --- a/apps/frontend/components/player/ProviderInformation/ProviderInformation.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import MaterialIcons from "@expo/vector-icons/MaterialIcons"; -import { ProviderDoc } from "@lymo/schemas/doc"; -import { View, Text } from "react-native"; - -import Skeleton from "@/components/shared/Skeleton"; -import { formatRelativeTime } from "@/utils/formatRelativeTime"; - -import { styles } from "./ProviderInformation.styles"; - -interface ProviderInformationProps { - provider?: ProviderDoc; -} - -export default function ProviderInformation({ provider }: ProviderInformationProps) { - if (!provider) - return ( - - - - ); - - return ( - - - - {provider.providerName} 제공 - - - - - {`${formatRelativeTime( - provider.updatedAt - )} 전`} - - ); -} diff --git a/apps/frontend/components/player/ProviderInformation/index.ts b/apps/frontend/components/player/ProviderInformation/index.ts deleted file mode 100644 index 21bed03..0000000 --- a/apps/frontend/components/player/ProviderInformation/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ProviderInformation"; diff --git a/apps/frontend/components/player/Sentence/Sentence.tsx b/apps/frontend/components/player/Sentence/Sentence.tsx index c913a0a..849bdac 100644 --- a/apps/frontend/components/player/Sentence/Sentence.tsx +++ b/apps/frontend/components/player/Sentence/Sentence.tsx @@ -3,6 +3,7 @@ import { View, Animated } from "react-native"; import Skeleton from "@/components/shared/Skeleton"; import { colors } from "@/constants/colors"; +import { useTypingAnimation } from "@/hooks/useTypingAnimation"; import { styles } from "./Sentence.styles"; @@ -15,6 +16,7 @@ interface SentenceProps { const Sentence = memo(({ sentence, translation, active, ref }: SentenceProps) => { const progress = useRef(new Animated.Value(0)).current; + const displayedTranslation = useTypingAnimation(translation); useEffect(() => { Animated.timing(progress, { @@ -36,8 +38,10 @@ const Sentence = memo(({ sentence, translation, active, ref }: SentenceProps) => {translation === undefined && } {/* 번역 표시 */} - {translation && ( - {translation} + {!!displayedTranslation && ( + + {displayedTranslation} + )} ); diff --git a/apps/frontend/components/player/Summary/Summary.styles.ts b/apps/frontend/components/player/Summary/Summary.styles.ts index eda9f74..69f21f0 100644 --- a/apps/frontend/components/player/Summary/Summary.styles.ts +++ b/apps/frontend/components/player/Summary/Summary.styles.ts @@ -33,6 +33,7 @@ export const styles = StyleSheet.create({ right: 16, flexDirection: "column", flex: 1, + gap: 4, }, title: { @@ -46,21 +47,20 @@ export const styles = StyleSheet.create({ fontSize: 16, }, - summary: { + overview: { color: colors.onBackgroundSubtle, fontSize: 16, marginHorizontal: 16, lineHeight: 24, }, - summarySkeleton: { - display: "flex", + overviewSkeletonContainer: { + marginHorizontal: 16, flexDirection: "column", gap: 8, - paddingHorizontal: 16, }, - summaryButton: { + overviewButton: { paddingVertical: 8, paddingHorizontal: 16, flexDirection: "row", @@ -70,7 +70,7 @@ export const styles = StyleSheet.create({ alignSelf: "stretch", }, - summaryButtonContent: { + overviewButtonContent: { color: colors.onBackground, }, diff --git a/apps/frontend/components/player/Summary/Summary.tsx b/apps/frontend/components/player/Summary/Summary.tsx index 993377c..757d2fb 100644 --- a/apps/frontend/components/player/Summary/Summary.tsx +++ b/apps/frontend/components/player/Summary/Summary.tsx @@ -1,41 +1,46 @@ import MaterialIcons from "@expo/vector-icons/MaterialIcons"; import { LinearGradient } from "expo-linear-gradient"; import { useState } from "react"; -import { View, Image, Text, TouchableOpacity, type TextLayoutEvent } from "react-native"; +import { View, Image, Text, TouchableOpacity } from "react-native"; +import Skeleton from "@/components/shared/Skeleton"; +import { useTrackSourceStore } from "@/contexts/useTrackSourceStore"; +import { useTypingAnimation } from "@/hooks/useTypingAnimation"; import useWindowSize from "@/hooks/useWindowSize"; +import { DeviceMedia } from "@/types/mediaModule"; import getTrackDetailString from "@/utils/getTrackDetailString"; import { styles } from "./Summary.styles"; interface SummaryProps { - title: string; - artist: string[]; - album: string | null; - publishedAt: string | null; - summary: string; - coverUrl?: string; + title?: string; + artist?: string[]; + album?: string | null; + albumArt?: string; coverColor?: string; + publishedAt?: string | null; + overview?: string; } -export default function Summary({ - title, - artist, - album, - publishedAt, - summary, - coverUrl, - coverColor, -}: SummaryProps) { +export default function Summary(props: SummaryProps) { const { width: windowWidth } = useWindowSize(); - const [summaryLine, setSummaryLine] = useState(0); const [expanded, setExpanded] = useState(false); - const detailString = getTrackDetailString({ artist, album, publishedAt }); + // 디바이스에서 재생 중인 트랙 정보 병합 + const { trackSource } = useTrackSourceStore(); + const placeholderTrack: Partial = + trackSource?.from === "device" ? trackSource.track : {}; + const track = { ...props, ...placeholderTrack }; - const handleSummaryTextLayout = (e: TextLayoutEvent) => { - setSummaryLine(e.nativeEvent.lines.length); - }; + // 개요 문자열 타이핑 애니메이션 적용 + const displayedOverview = useTypingAnimation(track.overview); + + // 곡 메타데이터 문자열 생성 + const detailString = getTrackDetailString({ + artist: track.artist, + album: track.album, + publishedAt: track.publishedAt, + }); const handleExpand = () => { setExpanded(true); @@ -45,47 +50,61 @@ export default function Summary({ {/* 커버 이미지 */} - + {/* 그라데이션 오버레이 */} {/* 곡 정보 */} - - {title} - - - {detailString} - + {track.title ? ( + + {track.title} + + ) : ( + + )} + {detailString.length > 0 ? ( + + {detailString} + + ) : ( + + )} {/* 요약 */} - {summary && summary.length > 0 && ( - - {summary} - - )} + + {displayedOverview.length > 0 ? ( + + {displayedOverview} + + ) : ( + + + + + + + + + + + )} + - {/* 요약이 8줄 이상일 때만 자세히 보기 버튼 노출 */} - {summaryLine > 8 && !expanded && ( - - - 자세히 보기 + {/* 자세히 보기 상태가 아닐 때만 자세히 보기 버튼 노출 */} + {displayedOverview.length > 0 && !expanded && ( + + + 자세히 보기 )} - - {/* 높이 측정을 위한 안 보이는 요약 */} - - - {summary} - - ); } diff --git a/apps/frontend/components/player/Summary/SummarySkeleton.tsx b/apps/frontend/components/player/Summary/SummarySkeleton.tsx deleted file mode 100644 index 6adc05a..0000000 --- a/apps/frontend/components/player/Summary/SummarySkeleton.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { LinearGradient } from "expo-linear-gradient"; -import { View, Image, Text } from "react-native"; - -import Skeleton from "@/components/shared/Skeleton"; -import useCoverColorQuery from "@/hooks/queries/useCoverColorQuery"; -import useWindowSize from "@/hooks/useWindowSize"; -import getTrackDetailString from "@/utils/getTrackDetailString"; - -import { styles } from "./Summary.styles"; - -interface SummarySkeletonProps { - coverUrl: string; - title: string; - artist: string; - album: string | null; - publishedAt: string | null; - summary: string; -} - -export default function SummarySkeleton({ - coverUrl, - title, - artist, - album, - publishedAt, -}: Partial) { - const { width: windowWidth } = useWindowSize(); - const { data: coverColor } = useCoverColorQuery(coverUrl); - const detailString = getTrackDetailString({ artist: artist ? [artist] : [], album, publishedAt }); - - return ( - - - {/* 커버 이미지 */} - - - {/* 그라데이션 오버레이 */} - - - - {/* 곡 정보 */} - - {title ? ( - - {title} - - ) : ( - - )} - {detailString ? ( - - {detailString} - - ) : ( - - )} - - - - {/* 곡 설명 */} - - - - - - - ); -} diff --git a/apps/frontend/components/player/Summary/index.ts b/apps/frontend/components/player/Summary/index.ts index 47e4604..25a9e30 100644 --- a/apps/frontend/components/player/Summary/index.ts +++ b/apps/frontend/components/player/Summary/index.ts @@ -1,2 +1 @@ export { default } from "./Summary"; -export { default as SummarySkeleton } from "./SummarySkeleton"; diff --git a/apps/frontend/components/shared/SettingBottomSheet/Main.tsx b/apps/frontend/components/shared/SettingBottomSheet/Main.tsx index c034a18..fefa766 100644 --- a/apps/frontend/components/shared/SettingBottomSheet/Main.tsx +++ b/apps/frontend/components/shared/SettingBottomSheet/Main.tsx @@ -3,7 +3,6 @@ import { View } from "react-native"; import { useSettingStore } from "@/contexts/useSettingStore"; import useTrackKey from "@/hooks/useTrackKey"; -import { getProviderNameFromLLMModel } from "./Model/Model.helpers"; import type { SettingViews } from "./SettingBottomSheet"; import { styles } from "./SettingBottomSheet.styles"; import SettingButton from "./SettingButton"; @@ -39,14 +38,6 @@ export default function Main({ setView }: MainProps) { onPress={() => setView("translate")} /> - {/* 해석 모델 */} - setView("model")} - /> - {/* 문단 요약 보이기 */} {/* { - switch (model) { - case "gemini-2.5-flash": - return "Gemini 2.5 Flash"; - case "gemini-2.5-flash-lite": - return "Gemini 2.5 Flash Lite"; - } -}; diff --git a/apps/frontend/components/shared/SettingBottomSheet/Model/Model.styles.ts b/apps/frontend/components/shared/SettingBottomSheet/Model/Model.styles.ts deleted file mode 100644 index c526421..0000000 --- a/apps/frontend/components/shared/SettingBottomSheet/Model/Model.styles.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { StyleSheet } from "react-native"; - -import { colors } from "@/constants/colors"; - -export const styles = StyleSheet.create({ - content: { - display: "flex", - flexDirection: "column", - padding: 8, - alignItems: "stretch", - }, - - languageOption: { - paddingVertical: 12, - paddingHorizontal: 16, - borderRadius: 12, - display: "flex", - justifyContent: "center", - alignItems: "center", - position: "relative", - }, - - languageText: { - fontSize: 16, - color: colors.onBackground, - }, - - selected: { - backgroundColor: `${colors.onBackground}33`, - }, - - checkIcon: { - color: colors.onBackground, - position: "absolute", - right: 16, - }, -}); diff --git a/apps/frontend/components/shared/SettingBottomSheet/Model/Model.tsx b/apps/frontend/components/shared/SettingBottomSheet/Model/Model.tsx deleted file mode 100644 index ee01e5b..0000000 --- a/apps/frontend/components/shared/SettingBottomSheet/Model/Model.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import MaterialIcons from "@expo/vector-icons/MaterialIcons"; -import { LLMModel, LLMModelSchema } from "@lymo/schemas/shared"; -import { Text, TouchableOpacity, View } from "react-native"; - -import { useSettingStore } from "@/contexts/useSettingStore"; - -import { getProviderNameFromLLMModel } from "./Model.helpers"; -import { styles } from "./Model.styles"; - -const models = LLMModelSchema.options; - -export default function Model() { - const { setting, updateSetting } = useSettingStore(); - - const isSelected = (model: LLMModel) => { - return setting.defaultLLMModel === model; - }; - - const handleSelectModel = (model: LLMModel) => { - updateSetting((prev) => ({ ...prev, defaultLLMModel: model })); - }; - - return ( - - {models.map((model) => ( - handleSelectModel(model)} - > - {getProviderNameFromLLMModel(model)} - {isSelected(model) && } - - ))} - - ); -} diff --git a/apps/frontend/components/shared/SettingBottomSheet/Model/index.ts b/apps/frontend/components/shared/SettingBottomSheet/Model/index.ts deleted file mode 100644 index 045f998..0000000 --- a/apps/frontend/components/shared/SettingBottomSheet/Model/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./Model"; diff --git a/apps/frontend/components/shared/SettingBottomSheet/SettingBottomSheet.tsx b/apps/frontend/components/shared/SettingBottomSheet/SettingBottomSheet.tsx index 65f7860..48cf1c8 100644 --- a/apps/frontend/components/shared/SettingBottomSheet/SettingBottomSheet.tsx +++ b/apps/frontend/components/shared/SettingBottomSheet/SettingBottomSheet.tsx @@ -2,7 +2,6 @@ import { BottomSheetModal } from "@gorhom/bottom-sheet"; import { useState } from "react"; import Main from "./Main"; -import Model from "./Model"; import Sync from "./Sync"; import Translate from "./Translate"; import Wrapper from "./Wrapper"; @@ -29,8 +28,6 @@ export default function SettingBottomSheet({ ref }: SettingBottomSheetProps) { return ; case "translate": return ; - case "model": - return ; default: return null; } diff --git a/apps/frontend/contexts/useSettingStore.ts b/apps/frontend/contexts/useSettingStore.ts index 1fd98c7..781d39f 100644 --- a/apps/frontend/contexts/useSettingStore.ts +++ b/apps/frontend/contexts/useSettingStore.ts @@ -33,7 +33,6 @@ const [SettingContextProvider, _useSettingStore] = buildContext {}, @@ -63,7 +62,6 @@ function SettingProvider({ children }: { children: ReactNode }) { delayMap: new Map(), defaultLanguage: "ko", showParagraphSummary: true, - defaultLLMModel: "gemini-2.5-flash-lite", }); const [isLoading, setIsLoading] = useState(true); diff --git a/apps/frontend/contexts/useTrackSourceStore.ts b/apps/frontend/contexts/useTrackSourceStore.ts index 3743bde..bbfe008 100644 --- a/apps/frontend/contexts/useTrackSourceStore.ts +++ b/apps/frontend/contexts/useTrackSourceStore.ts @@ -1,4 +1,4 @@ -import type { Track } from "@lymo/schemas/shared"; +import { Track } from "@lymo/schemas/doc"; import { useState, ReactNode, createElement } from "react"; import { buildContext } from "react-simplikit"; @@ -7,14 +7,11 @@ import type { DeviceMedia } from "@/types/mediaModule"; export type TrackSource = | { from: "device"; - track: Pick< - DeviceMedia, - "title" | "artist" | "album" | "duration" | "coverUrl" - >; + track: DeviceMedia; } | { from: "manual"; - track: Pick; + track: Track & { id: string }; }; interface TrackSourceContextStates { @@ -32,19 +29,18 @@ interface TrackSourceContextActions { setTrackSource: (track?: TrackSource) => void; } -type TrackSourceContextValues = TrackSourceContextStates & - TrackSourceContextActions; +type TrackSourceContextValues = TrackSourceContextStates & TrackSourceContextActions; -const [TrackSourceContextProvider, _useTrackSourceStore] = - buildContext("TrackSourceContext", { +const [TrackSourceContextProvider, _useTrackSourceStore] = buildContext( + "TrackSourceContext", + { trackSource: undefined, setTrackSource: () => {}, - }); + } +); function TrackSourceProvider({ children }: { children: ReactNode }) { - const [trackSource, setTrackSource] = useState( - undefined - ); + const [trackSource, setTrackSource] = useState(undefined); // react-simplikit의 buildContext에서 생성된 Provider는 children을 props로 받도록 설계됨 // eslint-disable-next-line react/no-children-prop diff --git a/apps/frontend/core/firestore.ts b/apps/frontend/core/firestore.ts index 1b9da80..2e2fae4 100644 --- a/apps/frontend/core/firestore.ts +++ b/apps/frontend/core/firestore.ts @@ -1,5 +1,18 @@ -import { getFirestore } from "@react-native-firebase/firestore"; +import { connectFirestoreEmulator, getFirestore } from "@react-native-firebase/firestore"; +import expoConstants from "expo-constants"; -const db = getFirestore(undefined, "main"); +const db = getFirestore(); + +if (__DEV__) { + const debuggerHost = expoConstants.expoConfig?.hostUri; + const localhost = debuggerHost?.split(":")[0] ?? "localhost"; + console.log(`Connecting to Firestore Emulator at ${localhost}:8080`); + + try { + connectFirestoreEmulator(db, localhost, 8080); + } catch (e) { + console.error("Error connecting to emulator:", e); + } +} export default db; diff --git a/apps/frontend/core/functions.ts b/apps/frontend/core/functions.ts new file mode 100644 index 0000000..007324e --- /dev/null +++ b/apps/frontend/core/functions.ts @@ -0,0 +1,18 @@ +import { connectFunctionsEmulator, getFunctions } from "@react-native-firebase/functions"; +import expoConstants from "expo-constants"; + +const functions = getFunctions(); + +if (__DEV__) { + const debuggerHost = expoConstants.expoConfig?.hostUri; + const localhost = debuggerHost?.split(":")[0] ?? "localhost"; + console.log(`Connecting to Firebase Functions at ${localhost}:5001`); + + try { + connectFunctionsEmulator(functions, localhost, 5001); + } catch (e) { + console.error("Error connecting to emulator:", e); + } +} + +export default functions; diff --git a/apps/frontend/hooks/queries/useAddTrackQuery.ts b/apps/frontend/hooks/queries/useAddTrackQuery.ts deleted file mode 100644 index e36ba14..0000000 --- a/apps/frontend/hooks/queries/useAddTrackQuery.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useSuspenseQuery } from "@tanstack/react-query"; - -import addTrack from "@/apis/addTrack"; - -interface UseAddTrackProps { - title: string; - artist: string; - duration: number; -} - -/** - * @description 기기에서 재생 중인 미디어로 곡 정보를 가져오는 suspenseQuery 훅입니다. - * - * @returns suspenseQuery 결과 - */ -export default function useAddTrackQuery(props: UseAddTrackProps) { - const key = props; - - return useSuspenseQuery({ - queryKey: ["track", "stream", key], - - queryFn: async () => { - console.log("useAddTrackQuery called"); - const result = await addTrack(key); - if (result.notFound) throw new Error("곡을 찾을 수 없습니다."); - const { notFound, ...data } = result; - return data; - }, - staleTime: Infinity, - }); -} diff --git a/apps/frontend/hooks/queries/useCoverColorQuery.ts b/apps/frontend/hooks/queries/useCoverColorQuery.ts index 030aaad..7004abc 100644 --- a/apps/frontend/hooks/queries/useCoverColorQuery.ts +++ b/apps/frontend/hooks/queries/useCoverColorQuery.ts @@ -5,22 +5,22 @@ import { colors } from "@/constants/colors"; /** * @description 앨범 커버 이미지의 주요 색상을 가져오는 query 훅입니다. - * @param coverUrl 앨범 커버 이미지 URL + * @param albumArt 앨범 커버 이미지 URL * @returns query 결과 */ export default function useCoverColorQuery( - coverUrl?: string | null, + albumArt?: string | null, placeholderColor = colors.background ) { return useQuery({ - queryKey: ["cover-color", coverUrl], + queryKey: ["cover-color", albumArt], queryFn: async () => { - if (coverUrl == null || coverUrl === "") { + if (albumArt == null || albumArt === "") { return placeholderColor; } try { - const results = await getColors(coverUrl); + const results = await getColors(albumArt); if (results.platform === "ios") { return results.background; @@ -29,14 +29,14 @@ export default function useCoverColorQuery( } } catch (error) { console.error("[COVER_COLOR_ERROR]", { - coverUrl, + albumArt, error: error instanceof Error ? error.message : String(error), }); // 이미지 로딩 실패 시 기본 색상 반환 return placeholderColor; } }, - enabled: !!coverUrl, + enabled: !!albumArt, staleTime: Infinity, placeholderData: placeholderColor, }); diff --git a/apps/frontend/hooks/queries/useGenerateDetailQuery.ts b/apps/frontend/hooks/queries/useGenerateDetailQuery.ts deleted file mode 100644 index f4171c4..0000000 --- a/apps/frontend/hooks/queries/useGenerateDetailQuery.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { ProviderDoc, TrackDetailDoc } from "@lymo/schemas/doc"; -import { Lyrics, LyricsProvider } from "@lymo/schemas/shared"; -import { - experimental_streamedQuery as streamedQuery, - useQuery, - useQueryClient, -} from "@tanstack/react-query"; -import { useEffect, useMemo } from "react"; - -import generateDetail from "@/apis/generateDetail"; -import { useSettingStore } from "@/contexts/useSettingStore"; - -export type GenerateDetailResult = - | { - exists: false; - provider?: ProviderDoc; - providerId?: string; - trackDetail: Omit & { lyricsProvider?: LyricsProvider }; - lyrics: Lyrics; - } - | { - exists: true; - providerId: string; - }; - -/** - * @description 곡 정보를 생성하는 스트리밍 query 훅입니다. - * - * data가 undefined인 경우는 오류가 발생한 경우가 유일합니다. - * - * @returns query 결과 - */ -export default function useGenerateDetailQuery(trackId: string, lyricsProvider?: LyricsProvider) { - const { setting } = useSettingStore(); - - const key = useMemo( - () => ({ - id: trackId, - language: setting.defaultLanguage, - lyricsProvider, - model: setting.defaultLLMModel, - }), - [trackId, lyricsProvider, setting.defaultLanguage, setting.defaultLLMModel] - ); - - const query = useQuery({ - queryKey: ["track-stream", key], - - queryFn: streamedQuery({ - streamFn: async function* () { - console.log("useGenerateDetailQuery called"); - const flow = generateDetail(key); - - for await (const chunk of flow.stream) { - yield chunk; - } - - const output = await flow.output; - if (!output.success) throw new Error("곡 상세 정보를 생성하는 데 실패하였습니다."); - - if (output.exists) { - yield { event: "already_exists" as const, data: output.providerId }; - } - }, - - reducer: (acc, chunk) => { - const result = structuredClone(acc); - if (result.exists) return result; - - switch (chunk.event) { - case "lyrics_provider_set": - result.trackDetail.lyricsProvider = chunk.data.lyricsProvider; - break; - - case "translation_set": { - result.trackDetail.translations[chunk.data.sentenceIndex] = chunk.data.text; - break; - } - - case "lyrics_group": - result.trackDetail.lyricsSplitIndices = chunk.data; - break; - - case "summary_append": - result.trackDetail.summary += chunk.data.summary; - break; - - case "paragraph_summary_append": { - const summary = result.trackDetail.paragraphSummaries[chunk.data.paragraphIndex] || ""; - result.trackDetail.paragraphSummaries[chunk.data.paragraphIndex] = - summary + chunk.data.summary; - break; - } - - case "provider_set": { - const { providerId, ...provider } = chunk.data; - result.provider = provider; - result.providerId = providerId; - break; - } - - case "already_exists": - return { exists: true as const, providerId: chunk.data }; - } - - return result; - }, - - initialValue, - }), - - staleTime: Infinity, - placeholderData: initialValue, - }); - - // 스트리밍 도중 컴포넌트가 언마운트되면 부분적으로 쌓인 데이터를 무효화 - const queryClient = useQueryClient(); - useEffect(() => { - return () => { - if (!query.isSuccess) { - queryClient.removeQueries({ queryKey: ["track-stream", key] }); - } - }; - }, [query.isSuccess, queryClient, key]); - - return query; -} - -const initialValue: GenerateDetailResult = { - exists: false, - trackDetail: { - summary: "", - lyricsSplitIndices: [], - translations: [], - paragraphSummaries: [], - }, - lyrics: [], -}; diff --git a/apps/frontend/hooks/queries/useLyricsQuery.ts b/apps/frontend/hooks/queries/useLyricsQuery.ts deleted file mode 100644 index b4bbed2..0000000 --- a/apps/frontend/hooks/queries/useLyricsQuery.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { LyricsProvider } from "@lymo/schemas/shared"; -import { useSuspenseQuery } from "@tanstack/react-query"; - -import getLyrics from "@/apis/getLyrics"; - -interface UseLyricsQueryProps { - trackId: string; - lyricsProvider: LyricsProvider; -} - -/** - * @description 사용자가 직접 선택한 곡의 가사를 가져오는 suspenseQuery 훅입니다. - * - * @returns suspenseQuery 결과 - */ -export default function useLyricsQuery(props: UseLyricsQueryProps) { - const key = props; - - return useSuspenseQuery({ - queryKey: ["lyrics", key], - - queryFn: async () => { - console.log("useLyricsQuery called"); - if (!key.trackId) throw new Error("곡 ID가 제공되지 않았습니다."); - const lyricsDoc = await getLyrics(key); - return lyricsDoc.lyrics; - }, - - staleTime: Infinity, - }); -} diff --git a/apps/frontend/hooks/queries/useProvidersQuery.ts b/apps/frontend/hooks/queries/useProvidersQuery.ts deleted file mode 100644 index 8a7cbf0..0000000 --- a/apps/frontend/hooks/queries/useProvidersQuery.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useSuspenseQuery } from "@tanstack/react-query"; - -import getProviders from "@/apis/getProvider"; - -interface UseProvidersQueryProps { - trackId: string; -} - -/** - * @description 곡의 제공자 목록을 가져오는 suspenseQuery 훅입니다. - * - * @returns suspenseQuery 결과 - */ -export default function useProvidersQuery({ trackId }: UseProvidersQueryProps) { - return useSuspenseQuery({ - queryKey: ["providers", trackId], - queryFn: async () => { - console.log("useProvidersQuery called"); - const providers = await getProviders({ trackId }); - return providers; - }, - staleTime: Infinity, - }); -} diff --git a/apps/frontend/hooks/queries/useRequestStoryQuery.ts b/apps/frontend/hooks/queries/useRequestStoryQuery.ts new file mode 100644 index 0000000..6db0ab6 --- /dev/null +++ b/apps/frontend/hooks/queries/useRequestStoryQuery.ts @@ -0,0 +1,98 @@ +import { StoryRequest } from "@lymo/schemas/doc"; +import { RetrieveTrackInput } from "@lymo/schemas/functions"; +import { Language } from "@lymo/schemas/shared"; +import { + collection, + doc, + FirebaseFirestoreTypes, + onSnapshot, + Unsubscribe, +} from "@react-native-firebase/firestore"; +import { experimental_streamedQuery as streamedQuery, useQuery } from "@tanstack/react-query"; +import { useEffect, useRef } from "react"; + +import db from "@/core/firestore"; +import { createStreamChannel } from "@/utils/createStreamChannel"; + +type UseRequestStoryParams = RetrieveTrackInput & { language: Language }; + +/** + * 해석 생성을 요청하고 스냅샷을 구독하는 쿼리 훅입니다. + * @param params 요청 파라미터 + * @returns 요청 상태를 반환합니다. + */ +export default function useRequestStory(params: UseRequestStoryParams) { + const unsubscribe = useRef(null); + + useEffect(() => { + return () => unsubscribe.current?.(); + }, []); + + return useQuery({ + queryKey: ["request-story", params], + + queryFn: streamedQuery({ + streamFn: async function* () { + const { push, close, fail, iterator } = createStreamChannel(); + + (async () => { + try { + // 요청 문서 생성 + const storyRequestDocRef = doc( + storyRequestCollectionRef + ) as FirebaseFirestoreTypes.DocumentReference; + await storyRequestDocRef.set({ + ...params, + status: "PENDING", + }); + + // 기존 구독 해제 + unsubscribe.current?.(); + + // 스냅샷 구독 시작 + unsubscribe.current = onSnapshot( + storyRequestDocRef, + (snapshot) => { + const data = snapshot.data(); + if (!data) return; + push(data); + + // status가 COMPLETED이면 완료 처리 + if (data.status === "COMPLETED") close(); + }, + (err) => { + console.error("Error in snapshot listener:", err); + fail(err); + } + ); + } catch (error) { + if (!(error instanceof Error)) throw error; + fail(error); + } + })(); + + try { + yield* iterator(); + } finally { + unsubscribe.current?.(); + } + }, + + reducer: (_acc, chunk) => { + return chunk; + }, + + initialValue: { ...params, status: "PENDING" }, + }), + + refetchOnMount: false, + refetchOnReconnect: false, + refetchOnWindowFocus: false, + retry: false, + }); +} + +const storyRequestCollectionRef = collection( + db, + "storyRequests" +) as FirebaseFirestoreTypes.CollectionReference; diff --git a/apps/frontend/hooks/queries/useRetrieveTrack.ts b/apps/frontend/hooks/queries/useRetrieveTrack.ts new file mode 100644 index 0000000..ec66226 --- /dev/null +++ b/apps/frontend/hooks/queries/useRetrieveTrack.ts @@ -0,0 +1,20 @@ +import { RetrieveTrackInput } from "@lymo/schemas/functions"; +import { useQuery } from "@tanstack/react-query"; + +import { retrieveTrack } from "@/apis/retrieveTrack"; + +/** + * @description retrieveTrack를 호출하는 쿼리 훅입니다. + * @returns 쿼리 결과 + */ +export default function useRetrieveTrack(params: RetrieveTrackInput) { + return useQuery({ + queryKey: ["retrieve-track", params], + queryFn: async () => retrieveTrack(params), + select: (res) => { + if (res.data.success) return res.data.data; + throw new Error(res.data.message || res.data.error); + }, + throwOnError: true, + }); +} diff --git a/apps/frontend/hooks/queries/useStoryQuery.ts b/apps/frontend/hooks/queries/useStoryQuery.ts new file mode 100644 index 0000000..4da3ead --- /dev/null +++ b/apps/frontend/hooks/queries/useStoryQuery.ts @@ -0,0 +1,29 @@ +import { Language } from "@lymo/schemas/shared"; +import { useQuery } from "@tanstack/react-query"; + +import getStoryByTrackId from "@/apis/getStoryByTrackId"; + +interface UseTrackAndStoryQueryParams { + trackId?: string; + language?: Language; + enabled?: boolean; +} + +/** + * @description 곡 해석을 가져오는 쿼리 훅입니다. + * @returns 쿼리 결과 + */ +export default function useStoryQuery({ + trackId, + language, + enabled = true, +}: UseTrackAndStoryQueryParams) { + return useQuery({ + queryKey: ["story", { language, trackId }], + queryFn: async () => { + if (!trackId || !language) return null; + return getStoryByTrackId({ trackId, language }); + }, + enabled, + }); +} diff --git a/apps/frontend/hooks/queries/useTrackDetailQuery.ts b/apps/frontend/hooks/queries/useTrackDetailQuery.ts deleted file mode 100644 index b48b66d..0000000 --- a/apps/frontend/hooks/queries/useTrackDetailQuery.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Language } from "@lymo/schemas/shared"; -import { useSuspenseQuery } from "@tanstack/react-query"; - -import getTrackDetail from "@/apis/getTrackDetail"; - -interface UseTrackDetailQueryProps { - trackId: string; - providerId: string; - language: Language; -} - -/** - * @description 곡의 상세 정보를 가져오는 suspenseQuery 훅입니다. - * - * @returns suspenseQuery 결과 - */ -export default function useTrackDetailQuery(props: UseTrackDetailQueryProps) { - return useSuspenseQuery({ - queryKey: ["detail", props], - queryFn: async () => { - console.log("useTrackDetailQuery called"); - const trackDetailDoc = await getTrackDetail(props); - return trackDetailDoc; - }, - staleTime: Infinity, - }); -} diff --git a/apps/frontend/hooks/queries/useTrackQuery.ts b/apps/frontend/hooks/queries/useTrackQuery.ts deleted file mode 100644 index 6b08bef..0000000 --- a/apps/frontend/hooks/queries/useTrackQuery.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useSuspenseQuery } from "@tanstack/react-query"; - -import getTrack from "@/apis/getTrack"; - -interface UseTrackQuery { - trackId: string; -} - -/** - * @description 곡 정보를 가져오는 suspenseQuery 훅입니다. - * - * @returns suspenseQuery 결과 - */ -export default function useTrackQuery({ trackId }: UseTrackQuery) { - return useSuspenseQuery({ - queryKey: ["track", trackId], - queryFn: async () => { - console.log("useTrackQuery called"); - const trackDoc = await getTrack({ trackId }); - return trackDoc; - }, - staleTime: Infinity, - }); -} diff --git a/apps/frontend/hooks/useProcessLyrics.ts b/apps/frontend/hooks/useProcessLyrics.ts new file mode 100644 index 0000000..a9c64e5 --- /dev/null +++ b/apps/frontend/hooks/useProcessLyrics.ts @@ -0,0 +1,46 @@ +import { BaseStoryFields, GeneratedStoryFields, Track } from "@lymo/schemas/doc"; +import { useMemo } from "react"; + +import groupLyricsIntoSections from "@/utils/groupLyricsIntoSections"; + +interface UseProcessLyricsParams { + track?: Track; + story?: BaseStoryFields & Partial; +} + +export default function useProcessLyrics({ track, story }: UseProcessLyricsParams) { + return useMemo(() => { + if (!track) return; + + // 해석 정보가 없는 경우 + if (!story || !story.lyricTranslations || !story.sectionBreaks || !story.sectionNotes) { + const lyrics = Object.values(track.lyrics)[0]; + if (!lyrics) return; + + // 가사 처리 + return groupLyricsIntoSections({ + lyrics, + sectionBreaks: [], + lyricTranslations: [], + sectionNotes: [], + }); + } + + // 해석 정보가 있는 경우 + else { + // 가사 관련 데이터가 모두 존재하는지 검증 + const lyrics = track.lyrics[story.lyricsProvider]; + const { sectionBreaks, lyricTranslations, sectionNotes } = story; + if ( + lyrics === undefined || + sectionBreaks === undefined || + lyricTranslations === undefined || + sectionNotes === undefined + ) + return; + + // 가사 처리 + return groupLyricsIntoSections({ lyrics, sectionBreaks, lyricTranslations, sectionNotes }); + } + }, [track, story]); +} diff --git a/apps/frontend/hooks/useScrollPositionPreservation.ts b/apps/frontend/hooks/useScrollPositionPreservation.ts deleted file mode 100644 index 03208f1..0000000 --- a/apps/frontend/hooks/useScrollPositionPreservation.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import { ScrollView, View } from "react-native"; - -interface UseScrollPositionPreservationParams { - scrollViewRef: React.RefObject; - scrollYRef: React.RefObject; -} - -interface UseScrollPositionPreservationReturn { - contentRef: React.RefObject; - handleLayout: () => void; -} - -/** - * @description 스크롤뷰의 위치가 동적으로 변할 때 현재 보이는 콘텐츠의 위치를 유지하는 훅입니다. - * 스트리밍 데이터로 인해 상단 컴포넌트가 확장될 때, 사용자가 보고 있던 콘텐츠가 아래로 밀리지 않도록 스크롤 위치를 자동으로 조정합니다. - * - * @param scrollViewRef - ScrollView의 ref - * @param scrollYRef - ScrollView의 현재 스크롤 Y 값을 추적하는 ref - * @returns contentRef: 위치를 추적할 컨테이너의 ref, handleLayout: onLayout 이벤트 핸들러 - */ -export default function useScrollPositionPreservation({ - scrollViewRef, - scrollYRef, -}: UseScrollPositionPreservationParams): UseScrollPositionPreservationReturn { - const contentRef = useRef(null); - const [contentY, setContentY] = useState(null); - const prevContentYRef = useRef(null); - - // 콘텐츠 위치가 변경되었을 때 스크롤 위치 조정 - useEffect(() => { - if (contentY === null || prevContentYRef.current === null) { - prevContentYRef.current = contentY; - return; - } - - // 콘텐츠 위치의 변화량 계산 - const deltaY = contentY - prevContentYRef.current; - - // 위치가 변경되었을 때만 스크롤 조정 - if (deltaY !== 0 && scrollViewRef.current) { - const newScrollY = scrollYRef.current + deltaY; - scrollViewRef.current.scrollTo({ - y: newScrollY, - animated: false, - }); - scrollYRef.current = newScrollY; - } - - prevContentYRef.current = contentY; - }, [contentY, scrollViewRef, scrollYRef]); - - // 콘텐츠 컨테이너의 레이아웃 측정 - const handleLayout = () => { - if (contentRef.current && scrollViewRef.current) { - contentRef.current.measureLayout( - scrollViewRef.current as unknown as number, - (_left, top) => { - setContentY(top); - }, - () => { - // 측정 실패 시 무시 - } - ); - } - }; - - return { - contentRef, - handleLayout, - }; -} diff --git a/apps/frontend/hooks/useTracking.ts b/apps/frontend/hooks/useTracking.ts index 2939a90..64892df 100644 --- a/apps/frontend/hooks/useTracking.ts +++ b/apps/frontend/hooks/useTracking.ts @@ -1,10 +1,10 @@ -import { TrackDoc } from "@lymo/schemas/doc"; +import { Track } from "@lymo/schemas/doc"; import { useCallback, useEffect, useRef, useState } from "react"; import { NativeScrollEvent, NativeSyntheticEvent, ScrollView } from "react-native"; interface UseTrackingParams { currentY: number; - track: TrackDoc; + track?: Track; } export interface UseTrackingReturn { diff --git a/apps/frontend/hooks/useTypingAnimation.ts b/apps/frontend/hooks/useTypingAnimation.ts new file mode 100644 index 0000000..b9ea344 --- /dev/null +++ b/apps/frontend/hooks/useTypingAnimation.ts @@ -0,0 +1,69 @@ +import { useState, useRef, useEffect } from "react"; + +/** + * 텍스트가 변경될 때 한 글자씩 타이핑되는 효과를 주는 훅입니다. + * 기존 텍스트에 새로운 텍스트가 덧붙여지는 경우에만 타이핑 효과가 발생합니다. + * + * @param text 표시할 전체 텍스트 + * @param speed 타이핑 속도 (ms) + * @returns 현재 타이핑 진행 중인 텍스트 + */ +export const useTypingAnimation = (text?: string | null, speed: number = 10) => { + const [displayedText, setDisplayedText] = useState(text || ""); + const currentTextRef = useRef(text || ""); + const targetTextRef = useRef(text || ""); + const timeoutRef = useRef | null>(null); + + useEffect(() => { + targetTextRef.current = text || ""; + + // 텍스트가 없으면 초기화 + if (!text) { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + currentTextRef.current = ""; + setDisplayedText(""); + return; + } + + const animate = () => { + const current = currentTextRef.current; + const target = targetTextRef.current; + + // 목표 텍스트에 도달했으면 종료 + if (current === target) { + timeoutRef.current = null; + return; + } + + // 기존 텍스트가 목표 텍스트의 시작부분과 일치하면 (덧붙여지는 경우) + if (target.startsWith(current)) { + const nextChar = target[current.length]; + currentTextRef.current = current + nextChar; + setDisplayedText(currentTextRef.current); + timeoutRef.current = setTimeout(animate, speed); + } else { + // 텍스트가 완전히 바뀌었으면 바로 변경 + currentTextRef.current = target; + setDisplayedText(target); + timeoutRef.current = null; + } + }; + + if (!timeoutRef.current) { + animate(); + } + }, [text, speed]); + + useEffect(() => { + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + }; + }, []); + + return displayedText; +}; diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 35cc324..ece7309 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -7,8 +7,7 @@ "android": "expo run:android", "ios": "expo run:ios", "web": "expo start --web", - "lint": "expo lint", - "postinstall": "cd ../../ && npm run schemas:build" + "lint": "expo lint" }, "dependencies": { "@algolia/client-search": "^5.37.0", @@ -18,14 +17,15 @@ "@lymo/schemas": "*", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-community/slider": "5.0.1", - "@react-native-firebase/app": "^23.4.0", - "@react-native-firebase/firestore": "^23.4.0", + "@react-native-firebase/app": "^23.5.0", + "@react-native-firebase/firestore": "^23.5.0", + "@react-native-firebase/functions": "^23.5.0", "@react-navigation/bottom-tabs": "^7.4.0", "@react-navigation/elements": "^2.6.3", "@react-navigation/native": "^7.1.8", "@tanstack/react-query": "^5.90.2", "expo": "54.0.23", - "expo-constants": "~18.0.9", + "expo-constants": "^18.0.10", "expo-dev-client": "~6.0.13", "expo-font": "~14.0.8", "expo-haptics": "~15.0.7", @@ -38,11 +38,9 @@ "expo-symbols": "~1.0.7", "expo-system-ui": "~6.0.7", "expo-web-browser": "~15.0.8", - "genkit": "^1.22.0", "react": "19.1.0", "react-dom": "19.1.0", "react-error-boundary": "^6.0.0", - "react-icons": "^5.5.0", "react-native": "0.81.5", "react-native-gesture-handler": "~2.28.0", "react-native-image-colors": "^2.5.0", @@ -52,8 +50,7 @@ "react-native-svg": "15.12.1", "react-native-web": "~0.21.0", "react-native-worklets": "^0.5.1", - "react-simplikit": "^0.0.46", - "styled-components": "^6.1.19" + "react-simplikit": "^0.0.46" }, "devDependencies": { "@types/colorthief": "^2.6.0", diff --git a/apps/frontend/tsconfig.json b/apps/frontend/tsconfig.json index ce27fee..40bbb7d 100644 --- a/apps/frontend/tsconfig.json +++ b/apps/frontend/tsconfig.json @@ -3,7 +3,8 @@ "compilerOptions": { "strict": true, "paths": { - "@/*": ["./*"] + "@/*": ["./*"], + "@lymo/schemas/*": ["../../packages/schemas/src/*"] } }, "include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"] diff --git a/apps/frontend/types/mediaModule.ts b/apps/frontend/types/mediaModule.ts index a1fbdc3..f140412 100644 --- a/apps/frontend/types/mediaModule.ts +++ b/apps/frontend/types/mediaModule.ts @@ -39,5 +39,5 @@ export type DeviceMedia = { album: string | null; duration: number; isPlaying: boolean; - coverUrl: string; // Base64 문자열 + albumArt: string; // Base64 문자열 }; diff --git a/apps/frontend/types/setting.ts b/apps/frontend/types/setting.ts index 0cc64b2..98e126c 100644 --- a/apps/frontend/types/setting.ts +++ b/apps/frontend/types/setting.ts @@ -1,4 +1,4 @@ -import { Language, LLMModel } from "@lymo/schemas/shared"; +import { Language } from "@lymo/schemas/shared"; export interface Setting { /** @@ -15,9 +15,4 @@ export interface Setting { * 문단 요약 표시 여부 */ showParagraphSummary: boolean; - - /** - * 기본 LLM 모델 - */ - defaultLLMModel: LLMModel; } diff --git a/apps/frontend/types/shared.ts b/apps/frontend/types/shared.ts deleted file mode 100644 index c209a39..0000000 --- a/apps/frontend/types/shared.ts +++ /dev/null @@ -1 +0,0 @@ -export type WithId = T & { id: string }; diff --git a/apps/frontend/types/track.ts b/apps/frontend/types/track.ts new file mode 100644 index 0000000..7158242 --- /dev/null +++ b/apps/frontend/types/track.ts @@ -0,0 +1,6 @@ +import { Lyric } from "@lymo/schemas/shared"; + +export interface Section { + lyrics: (Lyric & { translation?: string | null })[]; + note: string | null; +} diff --git a/apps/frontend/utils/createStreamChannel.ts b/apps/frontend/utils/createStreamChannel.ts new file mode 100644 index 0000000..c5eba0d --- /dev/null +++ b/apps/frontend/utils/createStreamChannel.ts @@ -0,0 +1,58 @@ +/** + * 비동기적으로 데이터를 푸시할 수 있는 스트림 채널을 생성합니다. + * @returns 스트림 채널 객체 + */ +export function createStreamChannel() { + const queue: T[] = []; + let resolveNext: ((result: IteratorResult) => void) | null = null; + let error: Error | null = null; + let isClosed = false; + + const push = (data: T) => { + if (isClosed) return; + if (resolveNext) { + resolveNext({ value: data, done: false }); + resolveNext = null; + } else { + queue.push(data); + } + }; + + const fail = (err: Error) => { + if (isClosed) return; + error = err; + if (resolveNext) { + resolveNext({ value: undefined, done: true }); + resolveNext = null; + } + }; + + const close = () => { + if (isClosed) return; + isClosed = true; + if (resolveNext) { + resolveNext({ value: undefined, done: true }); + resolveNext = null; + } + }; + + const iterator = async function* () { + while (!isClosed || queue.length > 0) { + if (error) throw error; + if (queue.length > 0) { + yield queue.shift()!; + } else { + const result = await new Promise>((resolve) => { + resolveNext = resolve; + }); + if (result.done) { + if (error) throw error; + break; + } + yield result.value; + } + } + }; + + return { push, fail, close, iterator }; +} diff --git a/apps/frontend/utils/getProviderIdFromLLMModel.ts b/apps/frontend/utils/getProviderIdFromLLMModel.ts deleted file mode 100644 index b86f700..0000000 --- a/apps/frontend/utils/getProviderIdFromLLMModel.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { LLMModel } from "@lymo/schemas/shared"; - -/** - * @description LLM 모델명으로부터 제공자 아이디를 반환합니다. - * @param model LLM 모델명 - * @returns 제공자 아이디 - */ -export default function getProviderIdFromLLMModel(model: LLMModel) { - switch (model) { - case "gemini-2.5-flash": - return "ai-gemini-2.5-flash"; - case "gemini-2.5-flash-lite": - return "ai-gemini-2.5-flash-lite"; - } -} diff --git a/apps/frontend/utils/getTrackDetailString.ts b/apps/frontend/utils/getTrackDetailString.ts index a2a1f0b..fb6d1f6 100644 --- a/apps/frontend/utils/getTrackDetailString.ts +++ b/apps/frontend/utils/getTrackDetailString.ts @@ -1,5 +1,5 @@ interface GetTrackDetailStringProps { - artist?: string[]; + artist?: string[] | string; album?: string | null; publishedAt?: string | null; } @@ -15,5 +15,7 @@ export default function getTrackDetailString({ publishedAt, }: GetTrackDetailStringProps) { const year = publishedAt ? new Date(publishedAt).getFullYear() : null; - return [artist?.join(", "), album, year].filter(Boolean).join(" • "); + return [Array.isArray(artist) ? artist.join(", ") : artist, album, year] + .filter(Boolean) + .join(" • "); } diff --git a/apps/frontend/utils/groupLyricsIntoSections.ts b/apps/frontend/utils/groupLyricsIntoSections.ts new file mode 100644 index 0000000..02b98e8 --- /dev/null +++ b/apps/frontend/utils/groupLyricsIntoSections.ts @@ -0,0 +1,54 @@ +import { Lyric } from "@lymo/schemas/shared"; + +import { Section } from "@/types/track"; + +interface ProcessLyricsParams { + lyrics: Lyric[]; + /** + * lyrics[i]와 lyrics[i+1] 사이에 문단 구분이 있음을 의미하는 인덱스 배열 + */ + sectionBreaks: number[]; + lyricTranslations: (string | null)[]; + sectionNotes: (string | null)[]; +} + +/** + * @description 주어진 가사 데이터를 가사 문단 및 문장 구조로 처리합니다. + * @param rawLyrics 원본 가사 배열 + * @param sectionBreaks 문단 구분 인덱스 배열 (각 i는 i번째와 i+1번째 문장 사이에 단락 구분이 있음을 의미) + * @param lyricTranslations 문장별 번역 배열 + * @param sectionNotes 문단별 요약 배열 + * @returns 처리된 가사 구조 + */ +export default function groupLyricsIntoSections({ + lyrics: rawLyrics, + sectionBreaks, + lyricTranslations, + sectionNotes, +}: ProcessLyricsParams) { + // groupLyrics가 반환한 인덱스(i)는 rawLyrics[i]와 rawLyrics[i+1] 사이 경계를 의미하므로 + // 이를 문단 시작 인덱스로 변환하기 위해 +1 해준다. + const paragraphStartIndices = [0, ...sectionBreaks.map((i) => i + 1), rawLyrics.length]; + const sections: Section[] = []; + + for (let p = 0; p < paragraphStartIndices.length - 1; p++) { + const startIdx = paragraphStartIndices[p]; + const endIdx = paragraphStartIndices[p + 1]; + + // 각 문단의 문장들 구성 + const lyrics = rawLyrics.slice(startIdx, endIdx).map((lyric, idx) => { + const globalIdx = startIdx + idx; + return { + text: lyric.text, + translation: lyricTranslations[globalIdx], + start: lyric.start, + end: lyric.end, + }; + }); + + const section: Section = { lyrics, note: sectionNotes[p] ?? null }; + sections.push(section); + } + + return sections; +} diff --git a/apps/frontend/utils/processLyrics.ts b/apps/frontend/utils/processLyrics.ts deleted file mode 100644 index f342707..0000000 --- a/apps/frontend/utils/processLyrics.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { LyricsSentence } from "@lymo/schemas/shared"; - -export type PostLyricsResult = { - sentences: LyricsSentence[]; - summary: string | null; -}[]; - -interface ProcessLyricsProps { - rawLyrics: { text: string; start: number; end: number }[]; - /** - * Indices i indicating a paragraph break BETWEEN rawLyrics[i] and rawLyrics[i+1]. - * (Returned by groupLyrics tool). Each value 0 <= i < rawLyrics.length - 1. - */ - lyricsSplitIndices: number[]; - translations: (string | null)[]; - paragraphSummaries: (string | null)[]; -} - -/** - * @description 주어진 가사 데이터를 가사 문단 및 문장 구조로 처리합니다. - * @param rawLyrics 원본 가사 배열 - * @param lyricsSplitIndices 문단 구분 인덱스 배열 (각 i는 i번째와 i+1번째 문장 사이에 단락 구분이 있음을 의미) - * @param translations 문장별 번역 배열 - * @param paragraphSummaries 문단별 요약 배열 - * @returns 처리된 가사 구조 - */ -export default function processLyrics({ - rawLyrics, - lyricsSplitIndices, - translations, - paragraphSummaries, -}: ProcessLyricsProps): PostLyricsResult { - // groupLyrics가 반환한 인덱스(i)는 rawLyrics[i]와 rawLyrics[i+1] 사이 경계를 의미하므로 - // 이를 문단 시작 인덱스로 변환하기 위해 +1 해준다. - const paragraphStartIndices = [0, ...lyricsSplitIndices.map((i) => i + 1), rawLyrics.length]; - const lyrics: PostLyricsResult = []; - - for (let p = 0; p < paragraphStartIndices.length - 1; p++) { - const startIdx = paragraphStartIndices[p]; - const endIdx = paragraphStartIndices[p + 1]; - - // 각 문단의 문장들 구성 - const sentences = rawLyrics.slice(startIdx, endIdx).map((lyric, idx) => { - const globalIdx = startIdx + idx; - return { - text: lyric.text, - translation: translations[globalIdx], - start: lyric.start, - end: lyric.end, - }; - }); - - lyrics.push({ sentences, summary: paragraphSummaries[p] ?? null }); - } - - return lyrics; -} diff --git a/apps/functions/.gitignore b/apps/functions/.gitignore index d383d70..3f219f6 100644 --- a/apps/functions/.gitignore +++ b/apps/functions/.gitignore @@ -10,4 +10,4 @@ node_modules/ *.local .genkit/ -serviceAccountKey.json \ No newline at end of file +serviceAccount.json \ No newline at end of file diff --git a/apps/functions/package.json b/apps/functions/package.json index 68dc83d..5981012 100644 --- a/apps/functions/package.json +++ b/apps/functions/package.json @@ -2,32 +2,27 @@ "name": "@lymo/functions", "scripts": { "build": "tsc && tsc-alias", - "serve": "npm run build && firebase emulators:start --only functions", - "shell": "npm run build && firebase functions:shell", - "start": "npm run shell", + "build:watch": "concurrently \"tsc -w\" \"tsc-alias -w\"", "deploy": "firebase deploy --only functions", - "logs": "firebase functions:log", "genkit:start": "genkit start -- npx tsx --watch src/index.ts" }, "engines": { "node": "22" }, - "main": "lib/index.js", + "main": "lib/apps/functions/src/index.js", "dependencies": { "@genkit-ai/google-genai": "^1.19.2", "@google-cloud/firestore": "^7.11.6", - "@lymo/schemas": "*", "axios": "^1.13.2", "fastest-levenshtein": "^1.0.16", "firebase-admin": "^13.5.0", - "firebase-functions": "^6.4.0", + "firebase-functions": "^7.0.0", "franc-min": "^6.2.0", - "genkit": "^1.19.2", + "genkit": "^1.24.0", "spotify-web-api-node": "^5.0.2", "syllable": "^5.0.1" }, "devDependencies": { - "@types/handlebars": "^4.0.40", "@types/spotify-web-api-node": "^5.0.11", "firebase-functions-test": "^3.1.0", "tsc-alias": "^1.8.16", @@ -35,4 +30,4 @@ "typescript": "^5.9.2" }, "private": true -} \ No newline at end of file +} diff --git a/apps/functions/src/core/admin.ts b/apps/functions/src/core/admin.ts index b05466b..77a79df 100644 --- a/apps/functions/src/core/admin.ts +++ b/apps/functions/src/core/admin.ts @@ -1,14 +1,9 @@ import * as admin from "firebase-admin"; +import { applicationDefault } from "firebase-admin/app"; import { setGlobalOptions } from "firebase-functions"; -import firebaseAccountCredentials from "@/serviceAccountKey.json"; - -const serviceAccount = firebaseAccountCredentials as admin.ServiceAccount; - admin.initializeApp({ - credential: admin.credential.cert(serviceAccount), + credential: applicationDefault(), }); -admin.firestore().settings({ databaseId: "main" }); - setGlobalOptions({ maxInstances: 10 }); diff --git a/apps/functions/src/core/init.ts b/apps/functions/src/core/init.ts index 5e83e4c..b555b39 100644 --- a/apps/functions/src/core/init.ts +++ b/apps/functions/src/core/init.ts @@ -3,34 +3,19 @@ import { log } from "firebase-functions/logger"; import { defineSecret } from "firebase-functions/params"; import { initAi } from "./genkit"; -import { initSpotify } from "./spotify"; const geminiApiKey = defineSecret("GEMINI_API_KEY"); -const spotifyClientSecret = defineSecret("SPOTIFY_CLIENT_SECRET"); const initializeDev = async () => { - await initSpotify( - "f81a68e0a9054564b75668f7dcb3cb39", - spotifyClientSecret.value() - ); - log("Initialized development services"); }; const initializeProd = async () => { initAi(geminiApiKey.value()); - await initSpotify( - "f81a68e0a9054564b75668f7dcb3cb39", - spotifyClientSecret.value() - ); - log("Initialized production services"); }; -if ( - process.env.GENKIT_ENV === "dev" || - process.env.FUNCTIONS_EMULATOR === "true" -) { +if (process.env.GENKIT_ENV === "dev" || process.env.FUNCTIONS_EMULATOR === "true") { initializeDev(); } else { onInit(initializeProd); diff --git a/apps/functions/src/core/spotify.ts b/apps/functions/src/core/spotify.ts index 9ecffb2..3eeebe2 100644 --- a/apps/functions/src/core/spotify.ts +++ b/apps/functions/src/core/spotify.ts @@ -1,10 +1,6 @@ import SpotifyWebApi from "spotify-web-api-node"; const spotify = new SpotifyWebApi(); - -export const initSpotify = async (clientId: string, clientSecret: string) => { - spotify.setClientId(clientId); - spotify.setClientSecret(clientSecret); -}; +spotify.setClientId("f81a68e0a9054564b75668f7dcb3cb39"); export default spotify; diff --git a/apps/functions/src/flows/translateLyrics.flow.ts b/apps/functions/src/features/generate/flows/generateLyricTranslations/flow.ts similarity index 72% rename from apps/functions/src/flows/translateLyrics.flow.ts rename to apps/functions/src/features/generate/flows/generateLyricTranslations/flow.ts index e433437..bd18ce1 100644 --- a/apps/functions/src/flows/translateLyrics.flow.ts +++ b/apps/functions/src/features/generate/flows/generateLyricTranslations/flow.ts @@ -1,40 +1,19 @@ -import { TranslationSetEventSchema } from "@lymo/schemas/event"; -import { LanguageSchema } from "@lymo/schemas/shared"; import { logger } from "firebase-functions"; -import { z } from "genkit"; import ai from "@/core/genkit"; -import calculateSimilarity from "@/utils/calculateSimilarity"; -import detectLanguage from "@/utils/detectLanguage"; - -export const TranslateLyricsInputSchema = z.object({ - title: z.string().describe("The title of the song"), - artist: z.string().describe("The artist of the song"), - album: z.string().nullable().describe("The album of the song"), - lyrics: z - .array( - z.object({ - start: z.number().describe("The start time of the sentence in seconds"), - end: z.number().describe("The end time of the sentence in seconds"), - text: z.string().describe("The text of the sentence"), - }) - ) - .describe("The lyrics of the song"), - language: LanguageSchema.describe("The target language for translation"), -}); - -export const TranslateLyricsOutputSchema = z.array( - z.string().nullable().describe("The translated text of the sentence") -); +import calculateSimilarity from "@/features/shared/utils/calculateSimilarity"; + +import { InputSchema, StreamSchema, OutputSchema } from "./schemas"; +import { detectLanguage } from "./utils"; -export const translateLyricsFlow = ai.defineFlow( +export const generateLyricsTranslationsFlow = ai.defineFlow( { - name: "translateLyricsFlow", - inputSchema: TranslateLyricsInputSchema, - streamSchema: TranslationSetEventSchema, - outputSchema: TranslateLyricsOutputSchema, + name: "generateLyricsTranslationsFlow", + inputSchema: InputSchema, + streamSchema: StreamSchema, + outputSchema: OutputSchema, }, - async ({ title, artist, album, lyrics, language }, { sendChunk }) => { + async ({ trackInfo: track, lyrics, config: { language } }, { sendChunk }) => { // 1) 이미 목표 언어인 문장 필터링 const needsTranslation = lyrics.map((lyric) => { const detectedLang = detectLanguage(lyric.text); @@ -102,22 +81,18 @@ export const translateLyricsFlow = ai.defineFlow( \`\`\` `, model: "googleai/gemini-2.5-flash-lite", - prompt: JSON.stringify({ - title, - artist, - album, - lyrics, - targetLanguage: language, - }), + prompt: JSON.stringify({ track, lyrics, targetLanguage: language }), output: { - schema: TranslateLyricsOutputSchema, + schema: OutputSchema, }, config: { - temperature: 0.3, + // 재시도 시 temperature 점진적 증가 + temperature: retry * 0.2 + 0.3, }, }); // 3) 스트리밍 처리 + // 현재 처리 중인 문장의 인덱스 let sentenceIndex = 0; @@ -132,12 +107,10 @@ export const translateLyricsFlow = ai.defineFlow( const translation = translations[sentenceIndex]; const validatedTranslation = validateTranslation(translation, sentenceIndex); + // 번역 결과 스트리밍 전송 sendChunk({ - event: "translation_set", - data: { - sentenceIndex, - text: validatedTranslation, - }, + sentenceIndex, + translation: validatedTranslation, }); // 마지막 문장까지 처리했으면 종료 @@ -149,19 +122,25 @@ export const translateLyricsFlow = ai.defineFlow( (await response).output?.map((item) => (item?.trim() === "null" ? null : item)) ?? null; // 4) 결과 검증 및 반환 + // 번역 문장 개수가 입력된 문장 개수와 일치하는지 확인 if (result !== null && result.length === lyrics.length) { // 최종 결과에도 동일한 검증 로직 적용 return result.map((translation, index) => validateTranslation(translation, index)); - } else retry++; + } + + // 불일치하는 경우 재시도 + else { + retry++; + } } // 3회 재시도 후에도 실패한 경우 마지막 결과 반환 - logger.warn(`translateLyricsFlow: translation count mismatch after retries.`, { + logger.warn(`generateLyricsTranslationsFlow: translation count mismatch after retries.`, { expected: lyrics.length, actual: result?.length ?? 0, retries: retry, - track: { title, artist, album }, + track, }); return result ?? []; } diff --git a/apps/functions/src/features/generate/flows/generateLyricTranslations/index.ts b/apps/functions/src/features/generate/flows/generateLyricTranslations/index.ts new file mode 100644 index 0000000..a8eeccf --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateLyricTranslations/index.ts @@ -0,0 +1 @@ +export { generateLyricsTranslationsFlow } from "./flow"; diff --git a/apps/functions/src/features/generate/flows/generateLyricTranslations/schemas.ts b/apps/functions/src/features/generate/flows/generateLyricTranslations/schemas.ts new file mode 100644 index 0000000..87e02c2 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateLyricTranslations/schemas.ts @@ -0,0 +1,33 @@ +import { LanguageSchema } from "@lymo/schemas/shared"; +import { z } from "genkit"; + +export const InputSchema = z.object({ + trackInfo: z.object({ + title: z.string().describe("The title of the song"), + artists: z.string().array().describe("The artists of the song"), + album: z.string().nullable().describe("The album of the song"), + }), + + lyrics: z + .array( + z.object({ + start: z.number().describe("The start time of the sentence in seconds"), + end: z.number().describe("The end time of the sentence in seconds"), + text: z.string().describe("The text of the sentence"), + }) + ) + .describe("The lyrics of the song"), + + config: z.object({ + language: LanguageSchema.describe("The target language for translation"), + }), +}); + +export const StreamSchema = z.object({ + sentenceIndex: z.number().describe("The index of the translated sentence"), + translation: z.string().nullable().describe("The translated text of the sentence"), +}); + +export const OutputSchema = z.array( + z.string().nullable().describe("The translated text of the sentence") +); diff --git a/apps/functions/src/utils/detectLanguage.ts b/apps/functions/src/features/generate/flows/generateLyricTranslations/utils.ts similarity index 64% rename from apps/functions/src/utils/detectLanguage.ts rename to apps/functions/src/features/generate/flows/generateLyricTranslations/utils.ts index 9cf393d..0c7cb3a 100644 --- a/apps/functions/src/utils/detectLanguage.ts +++ b/apps/functions/src/features/generate/flows/generateLyricTranslations/utils.ts @@ -6,20 +6,16 @@ import { franc } from "franc-min"; * @param text 언어를 감지할 텍스트 * @returns 감지된 언어 (Language 타입) 또는 null (감지 실패 시) */ -export default function detectLanguage(text: string): Language | null { +export function detectLanguage(text: string): Language | null { // franc는 ISO 639-3 코드를 반환 (예: "eng", "kor") const detected = franc(text, { minLength: 3 }); - // franc의 결과를 Language 타입으로 매핑 switch (detected) { - case "eng": // English + case "eng": return "en"; - case "kor": // Korean + case "kor": return "ko"; - case "und": // 감지 불가 - return null; default: - // 지원하지 않는 언어는 null 반환 return null; } } diff --git a/apps/functions/src/features/generate/flows/generateSectionBreaks/flow.ts b/apps/functions/src/features/generate/flows/generateSectionBreaks/flow.ts new file mode 100644 index 0000000..5ca6b80 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateSectionBreaks/flow.ts @@ -0,0 +1,96 @@ +import { logger } from "firebase-functions"; +import { z } from "genkit"; + +import ai from "@/core/genkit"; + +import { InputSchema, OutputSchema } from "./schemas"; + +export const generateSectionBreaksFlow = ai.defineFlow( + { + name: "generateSectionBreaksFlow", + inputSchema: InputSchema, + outputSchema: OutputSchema, + }, + async ({ lyrics }) => { + if (lyrics.length <= 1) return []; + + let retry = 0; + let breakIndices: number[] | null = null; + + while (retry < 3) { + const response = await ai.generate({ + system: ` + ### Role + You are an Expert Lyric Paragraph Organizer. Your goal is to structure raw song lyrics into logical paragraphs (stanzas) to improve readability and synchronization. + + ### Task + Analyze the provided list of lyric lines (including indices, timestamps, and text) and determine the optimal indices to insert paragraph breaks. + + ### Input Format + You will receive a list of lines formatted as: + \`Index {i} | Time: {start}~{end} | Text: "{content}"\` + + ### Step-by-Step Analysis Strategy + 1. **Calculate Time Gaps**: For each line \`i\`, calculate the silence gap before the next line starts: \`Gap = Line[i+1].start - Line[i].end\`. + - *High Priority*: If \`Gap\` > 2.0 seconds, this is a very strong signal for a paragraph break. + - *Medium Priority*: If \`Gap\` is between 1.0 and 2.0 seconds, check if the semantic context also shifts. + 2. **Analyze Semantic Flow**: Look for natural pauses in the narrative, changes in rhyme scheme, or transitions between song sections (e.g., Verse -> Chorus). + 3. **Balance Paragraph Length**: + - Aim for paragraphs of **4 to 8 lines**. + - Avoid creating very short paragraphs (1-2 lines) unless there is a massive time gap or a distinct exclamation. + - Avoid overly long paragraphs (10+ lines) even if the time gaps are short. + + ### Constraints & Rules + - **No Empty Results**: Unless the input has fewer than 4 lines, you MUST return at least one break index. + - **Zero-based Indexing**: The output indices represent the line *after which* the paragraph ends. + - Example: If you return \`[3]\`, it means the first paragraph is lines 0-3, and the second paragraph starts at line 4. + - **Ascending Order**: The indices in the array must be sorted. + + ### Output Schema Requirement + You must output a JSON object with two fields: + 1. \`reasoning\` (string): Briefly explain the logic. Mention specific time gaps you found (e.g., "Found 3s gap after line 3") and semantic reasons. + 2. \`breakIndices\` (array of numbers): The final list of indices. + `, + model: "googleai/gemini-2.5-flash-lite", + + // 가사 데이터를 LLM에 전달하기 위해 가공 + prompt: JSON.stringify( + lyrics.map( + (sentence, index) => + `Index ${index} | Time: ${sentence.start.toFixed(2)}~${sentence.end.toFixed( + 2 + )} | Text: "${sentence.text}"` + ) + ), + + // 출력 스키마 정의 + output: { + schema: z.object({ + reasoning: z.string().describe("The reasoning behind the chosen paragraph breaks"), + breakIndices: OutputSchema, + }), + }, + config: { temperature: 0.3 }, + }); + + breakIndices = response.output?.breakIndices ?? null; + + // 인덱스가 유효한 범위 내에 있는지 확인 + if (breakIndices !== null) { + const isValid = breakIndices.every( + (breakIndex) => breakIndex >= 0 && breakIndex < lyrics.length - 1 + ); + + if (isValid) return breakIndices; + } + + retry++; + } + + // 3회 재시도 후에도 실패한 경우 빈 배열 반환 + logger.warn( + `generateSectionBreaksFlow: failed to generate valid paragraph breaks after retries.` + ); + return []; + } +); diff --git a/apps/functions/src/features/generate/flows/generateSectionBreaks/index.ts b/apps/functions/src/features/generate/flows/generateSectionBreaks/index.ts new file mode 100644 index 0000000..5bd7afd --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateSectionBreaks/index.ts @@ -0,0 +1 @@ +export { generateSectionBreaksFlow } from "./flow"; diff --git a/apps/functions/src/features/generate/flows/generateSectionBreaks/schemas.ts b/apps/functions/src/features/generate/flows/generateSectionBreaks/schemas.ts new file mode 100644 index 0000000..2108810 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateSectionBreaks/schemas.ts @@ -0,0 +1,15 @@ +import { z } from "genkit"; + +export const InputSchema = z.object({ + lyrics: z + .array( + z.object({ + start: z.number().describe("The start time of the sentence in seconds"), + end: z.number().describe("The end time of the sentence in seconds"), + text: z.string().describe("The text of the sentence"), + }) + ) + .describe("The lyrics of the song"), +}); + +export const OutputSchema = z.array(z.number().describe("An index where paragraphs should break")); diff --git a/apps/functions/src/features/generate/flows/generateSectionNotes/flow.ts b/apps/functions/src/features/generate/flows/generateSectionNotes/flow.ts new file mode 100644 index 0000000..21b6dac --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateSectionNotes/flow.ts @@ -0,0 +1,88 @@ +import { logger } from "firebase-functions"; +import { z } from "genkit"; + +import ai from "@/core/genkit"; + +import { InputSchema, OutputSchema, StreamSchema } from "./schemas"; + +export const generateSectionNotesFlow = ai.defineFlow( + { + name: "generateSectionNotesFlow", + inputSchema: InputSchema, + streamSchema: StreamSchema, + outputSchema: OutputSchema, + }, + async ({ trackInfo: track, lyrics, config: { language } }, { sendChunk }) => { + let retry = 0; + let result: (string | null)[] | null = null; + + while (retry < 3) { + const { stream, response } = ai.generateStream({ + system: ` + ### Role + Expert Lyric Analyst + + ### Lyrics Analysis Guidelines + - The given lyrics are separated by sections. + - Write an analysis for each section. + - The analysis must concisely summarize the core content of the respective section. + - The analysis must be written as a single section. + + ### Output Format + - All summaries must be written in the given target language. + - Output an array containing the summaries corresponding to each section. + - Treat sections that do not require analysis as null. + + ### Output Example + ["Summary of the first section", "Summary of the second section", null, "Summary of the fourth section"] + `, + prompt: JSON.stringify({ track, lyrics, targetLanguage: language }), + output: { schema: z.string().nullable().array() }, + config: { + // 재시도 시 temperature 점진적 증가 + temperature: retry * 0.2 + 0.3, + }, + }); + + let p = 0, + s = 0; + for await (const chunk of stream) { + const summaries = + chunk.output?.map((item) => (item?.trim() === "null" ? null : item)) ?? null; + if (summaries === null) continue; + for (; p < summaries.length; p++, s = 0) { + const summary = summaries[p]; + + // 요약이 null인 경우 + if (summary === null) { + sendChunk({ type: "update", text: null, sectionIndex: p }); + continue; + } + + // 요약이 null이 아닌 경우 + sendChunk({ type: "append", text: summary.slice(s, summary.length), sectionIndex: p }); + s = summary.length; + + // 마지막 섹션인 경우 루프 종료 + if (p === summaries.length - 1) break; + } + } + + result = + (await response).output?.map((item) => (item?.trim() === "null" ? null : item)) ?? null; + + // 문단 요약 개수가 입력된 문단 개수와 일치하면 결과 반환 + if (result !== null && result.length === lyrics.length) return result; + else retry++; + } + + // 3회 재시도 후에도 실패한 경우 마지막 결과 반환 + logger.warn(`generateSectionNotesFlow: summary count mismatch after retries.`, { + expected: lyrics.length, + actual: result?.length ?? 0, + retries: retry, + track, + }); + return result ?? []; + } +); diff --git a/apps/functions/src/features/generate/flows/generateSectionNotes/index.ts b/apps/functions/src/features/generate/flows/generateSectionNotes/index.ts new file mode 100644 index 0000000..8d56b60 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateSectionNotes/index.ts @@ -0,0 +1 @@ +export { generateSectionNotesFlow as generateSectionNotes } from "./flow"; diff --git a/apps/functions/src/features/generate/flows/generateSectionNotes/schemas.ts b/apps/functions/src/features/generate/flows/generateSectionNotes/schemas.ts new file mode 100644 index 0000000..4d56651 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateSectionNotes/schemas.ts @@ -0,0 +1,38 @@ +import { LanguageSchema } from "@lymo/schemas/shared"; +import { z } from "genkit"; + +export const InputSchema = z.object({ + trackInfo: z.object({ + title: z.string().describe("The title of the song"), + artists: z.string().array().describe("The artists of the song"), + album: z.string().nullable().describe("The album of the song"), + }), + lyrics: z + .array( + z.array(z.string().describe("A sentence in the lyrics")).describe("A section in the lyrics") + ) + .describe("The lyrics of the song, organized by sections"), + config: z.object({ + language: LanguageSchema.describe("The target language of the summaries"), + }), +}); + +export const StreamSchema = z.union([ + z.object({ + type: z.literal("append"), + text: z.string().describe("The appended text to the current section summary"), + sectionIndex: z.number().describe("The index of the section being summarized"), + }), + + z.object({ + type: z.literal("update"), + text: z.string().nullable().describe("The updated full text of the current section summary"), + sectionIndex: z.number().describe("The index of the section being summarized"), + }), +]); + +export const OutputSchema = z + .string() + .nullable() + .describe("The summarized text of the section") + .array(); diff --git a/apps/functions/src/features/generate/flows/generateStory/flow.ts b/apps/functions/src/features/generate/flows/generateStory/flow.ts new file mode 100644 index 0000000..2b10728 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateStory/flow.ts @@ -0,0 +1,149 @@ +import { GeneratedStoryFields } from "@lymo/schemas/doc"; +import { ERROR_CODES } from "@lymo/schemas/error"; + +import ai from "@/core/genkit"; + +import { generateLyricsTranslationsFlow } from "../generateLyricTranslations"; +import { generateSectionBreaksFlow } from "../generateSectionBreaks"; +import { generateSectionNotesFlow } from "../generateSectionNotes/flow"; +import { generateTrackOverviewFlow } from "../generateTrackOverview"; + +import { InputSchema, OutputSchema, StreamSchema } from "./schemas"; + +export const generateStoryFlow = ai.defineFlow( + { + name: "generateStoryFlow", + inputSchema: InputSchema, + streamSchema: StreamSchema, + outputSchema: OutputSchema, + }, + async ({ track, config: { lyricsProvider, language } }, { sendChunk }) => { + // 1) 데이터 준비 + const lyrics = track.lyrics[lyricsProvider]; + if (!lyrics) throw new Error(ERROR_CODES.LYRICS_NOT_FOUND); + + const result: GeneratedStoryFields = { + overview: "", + sectionBreaks: [], + sectionNotes: [], + lyricTranslations: [], + }; + + await Promise.all([ + // 2) 섹션 구분 및 섹션 해석 생성 + (async () => { + const sectionedLyrics: string[][] = []; + + // 2-1) 섹션 구분 생성 + { + // 2-1-1) generateSectionBreaksFlow 실행 + const { output } = generateSectionBreaksFlow.stream({ + lyrics, + }); + const sectionBreaks = await output; + + // 2-1-2) 섹션 구분에 따라 가사 분할 + let lastSectionBreak = -1; + for (const sectionBreak of [...sectionBreaks, lyrics.length - 1]) { + sectionedLyrics.push( + lyrics.slice(lastSectionBreak + 1, sectionBreak + 1).map((lyric) => lyric.text) + ); + lastSectionBreak = sectionBreak; + } + + // 2-1-3) 결과 처리 + result.sectionBreaks = sectionBreaks; + sendChunk({ sectionBreaks }); + } + + // 2-2) 섹션 해석 생성 + { + // 2-2-1) generateSectionNotesFlow 실행 + const { output, stream } = generateSectionNotesFlow.stream({ + trackInfo: { title: track.title, artists: track.artists, album: track.album }, + lyrics: sectionedLyrics, + config: { language }, + }); + let sectionNotes: (string | null)[] = []; + + // 2-2-2) 스트림 처리 + for await (const chunk of stream) { + // type이 append인 경우 + if (chunk.type === "append") { + const { sectionIndex, text } = chunk; + if (typeof sectionNotes[sectionIndex] === "string") + sectionNotes[sectionIndex] += text; + else sectionNotes[sectionIndex] = text; + } + + // type이 update인 경우 + else if (chunk.type === "update") { + const { sectionIndex, text } = chunk; + sectionNotes[sectionIndex] = text; + } + + sendChunk({ sectionNotes }); + } + + // 2-2-3) 결과 처리 + sectionNotes = await output; + result.sectionNotes = sectionNotes; + sendChunk({ sectionNotes }); + } + })(), + + // 3) 가사 해석 생성 + (async () => { + // 3-1) generateLyricsTranslationsFlow 실행 + const { output, stream } = generateLyricsTranslationsFlow.stream({ + trackInfo: { title: track.title, artists: track.artists, album: track.album }, + lyrics, + config: { language }, + }); + + let lyricTranslations: (string | null)[] = []; + + // 3-2) 스트림 처리 + for await (const chunk of stream) { + const { sentenceIndex, translation } = chunk; + if (typeof lyricTranslations[sentenceIndex] === "string") + lyricTranslations[sentenceIndex] += translation; + else lyricTranslations[sentenceIndex] = translation; + + sendChunk({ lyricTranslations }); + } + + // 3-3) 결과 처리 + lyricTranslations = await output; + result.lyricTranslations = lyricTranslations; + sendChunk({ lyricTranslations }); + })(), + + // 4) 곡 개요 생성 + (async () => { + // 4-1) generateTrackOverviewFlow 실행 + const { output, stream } = generateTrackOverviewFlow.stream({ + trackInfo: { title: track.title, artists: track.artists, album: track.album }, + lyrics: lyrics.map((lyric) => lyric.text), + config: { language }, + }); + + let overview: string = ""; + + // 4-2) 스트림 처리 + for await (const chunk of stream) { + overview += chunk; + sendChunk({ overview }); + } + + // 4-3) 결과 처리 + overview = await output; + result.overview = overview; + sendChunk({ overview }); + })(), + ]); + + // 5) 최종 결과 반환 + return result; + } +); diff --git a/apps/functions/src/features/generate/flows/generateStory/index.ts b/apps/functions/src/features/generate/flows/generateStory/index.ts new file mode 100644 index 0000000..11dfc9f --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateStory/index.ts @@ -0,0 +1 @@ +export { generateStoryFlow } from "./flow"; diff --git a/apps/functions/src/features/generate/flows/generateStory/schemas.ts b/apps/functions/src/features/generate/flows/generateStory/schemas.ts new file mode 100644 index 0000000..5c54ad1 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateStory/schemas.ts @@ -0,0 +1,15 @@ +import { GeneratedStoryFieldsSchema, TrackSchema } from "@lymo/schemas/doc"; +import { LanguageSchema, LyricsProviderSchema } from "@lymo/schemas/shared"; +import { z } from "genkit"; + +export const InputSchema = z.object({ + track: TrackSchema, + config: z.object({ + lyricsProvider: LyricsProviderSchema, + language: LanguageSchema, + }), +}); + +export const StreamSchema = GeneratedStoryFieldsSchema.partial(); + +export const OutputSchema = GeneratedStoryFieldsSchema; diff --git a/apps/functions/src/features/generate/flows/generateTrackOverview/flow.ts b/apps/functions/src/features/generate/flows/generateTrackOverview/flow.ts new file mode 100644 index 0000000..5c8bc95 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateTrackOverview/flow.ts @@ -0,0 +1,41 @@ +import ai from "@/core/genkit"; + +import { InputSchema, StreamSchema, OutputSchema } from "./schemas"; + +export const generateTrackOverviewFlow = ai.defineFlow( + { + name: "generateTrackOverviewFlow", + inputSchema: InputSchema, + streamSchema: StreamSchema, + outputSchema: OutputSchema, + }, + async ({ trackInfo, lyrics, config: { language } }, { sendChunk }) => { + const { stream, response } = ai.generateStream({ + system: ` + ### Role + Based on the provided lyrics and metadata of a song, summarize the song's content. + + ### Goal + - Include the song's theme, message, and core storyline. + - Utilize web search to include the social context at the time of the song's release, its genre characteristics, and the artist's background. + - May also include behind-the-scenes stories, production process, and public reception. + + ### Constraints + - The summary must consist of 2 to 3 sections. + - Sections must be separated by two newline characters. + - The summary must be written in the given target language. + `, + prompt: JSON.stringify({ track: trackInfo, lyrics, targetLanguage: language }), + config: { + temperature: 0.3, + }, + }); + + for await (const chunk of stream) { + sendChunk(chunk.text); + } + + const result = (await response).text; + return result; + } +); diff --git a/apps/functions/src/features/generate/flows/generateTrackOverview/index.ts b/apps/functions/src/features/generate/flows/generateTrackOverview/index.ts new file mode 100644 index 0000000..ddccef3 --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateTrackOverview/index.ts @@ -0,0 +1 @@ +export { generateTrackOverviewFlow } from "./flow"; diff --git a/apps/functions/src/features/generate/flows/generateTrackOverview/schemas.ts b/apps/functions/src/features/generate/flows/generateTrackOverview/schemas.ts new file mode 100644 index 0000000..700201c --- /dev/null +++ b/apps/functions/src/features/generate/flows/generateTrackOverview/schemas.ts @@ -0,0 +1,20 @@ +import { LanguageSchema } from "@lymo/schemas/shared"; +import { z } from "genkit"; + +export const InputSchema = z.object({ + trackInfo: z.object({ + title: z.string().describe("The title of the song"), + artists: z.string().array().describe("The artists of the song"), + album: z.string().nullable().describe("The album of the song"), + }), + lyrics: z + .array(z.string().describe("A sentence from the lyrics")) + .describe("The lyrics of the song"), + config: z.object({ + language: LanguageSchema.describe("The language for the summary"), + }), +}); + +export const StreamSchema = z.string().describe("The summary append event"); + +export const OutputSchema = z.string().describe("A chunk of the summary for the song"); diff --git a/apps/functions/src/features/generate/tools/copyStoryDoc.ts b/apps/functions/src/features/generate/tools/copyStoryDoc.ts new file mode 100644 index 0000000..b140d27 --- /dev/null +++ b/apps/functions/src/features/generate/tools/copyStoryDoc.ts @@ -0,0 +1,33 @@ +import { StoryRequest, StorySchema } from "@lymo/schemas/doc"; +import admin from "firebase-admin"; +import { DocumentReference } from "firebase-admin/firestore"; +import { z } from "genkit"; + +import ai from "@/core/genkit"; + +const InputSchema = z.object({ + story: StorySchema, + requestId: z.string(), +}); + +const OutputSchema = z.void(); + +export const copyStoryDoc = ai.defineTool( + { + name: "copyStoryDoc", + inputSchema: InputSchema, + outputSchema: OutputSchema, + description: "Copy a story document into a storyRequest document`", + }, + async ({ story, requestId }) => { + const storyRequestRef = admin + .firestore() + .collection("storyRequests") + .doc(requestId) as DocumentReference; + + storyRequestRef.set({ + ...story, + status: "COMPLETED", + }); + } +); diff --git a/apps/functions/src/features/generate/tools/getStoryDoc.ts b/apps/functions/src/features/generate/tools/getStoryDoc.ts new file mode 100644 index 0000000..b071531 --- /dev/null +++ b/apps/functions/src/features/generate/tools/getStoryDoc.ts @@ -0,0 +1,44 @@ +import { Story, StorySchema } from "@lymo/schemas/doc"; +import { LanguageSchema } from "@lymo/schemas/shared"; +import admin from "firebase-admin"; +import { CollectionReference } from "firebase-admin/firestore"; +import { z } from "genkit"; + +import ai from "@/core/genkit"; + +const InputSchema = z.object({ + trackId: z.string(), + userId: z.string(), + language: LanguageSchema, +}); + +const OutputSchema = z + .object({ + id: z.string(), + data: StorySchema, + }) + .nullable(); + +export const getStoryDoc = ai.defineTool( + { + name: "getStoryDoc", + inputSchema: InputSchema, + outputSchema: OutputSchema, + description: "Retrieve a story document from DB", + }, + async ({ trackId, userId, language }) => { + const storyCollectionRef = admin + .firestore() + .collection("stories") as CollectionReference; + const q = storyCollectionRef + .where("trackId", "==", trackId) + .where("userId", "==", userId) + .where("language", "==", language) + .limit(1); + + const story = (await q.get()).docs[0]; + + if (story?.exists) return { id: story.id, data: story.data() }; + return null; + } +); diff --git a/apps/functions/src/features/generate/triggers/onStoryRequestCreate/helpers.ts b/apps/functions/src/features/generate/triggers/onStoryRequestCreate/helpers.ts new file mode 100644 index 0000000..82f8ad9 --- /dev/null +++ b/apps/functions/src/features/generate/triggers/onStoryRequestCreate/helpers.ts @@ -0,0 +1,69 @@ +import { Track } from "@lymo/schemas/doc"; +import { ERROR_CODES } from "@lymo/schemas/error"; +import { Language } from "@lymo/schemas/shared"; + +import { generateStoryFlow } from "../../flows/generateStory"; +import { copyStoryDoc } from "../../tools/copyStoryDoc"; +import { getStoryDoc } from "../../tools/getStoryDoc"; + +import { StoryUpdater } from "./utils"; + +interface SaveGeneratedStoryParams { + track: Track; + trackId: string; + requestId: string; + language: Language; +} + +/** + * 봇 계정으로 곡 해석을 생성하고 Firestore에 저장합니다. + * + * 이미 해당 언어의 봇 곡 해석이 존재하면 생성을 건너뜁니다. + * + * @param params - 곡 해석 생성 파라미터 + * @param params.track - 곡 정보 + * @param params.trackId - Firestore 곡 문서 ID + * @param params.requestId - 요청 문서 ID + * @param params.language - 생성할 곡 해석의 언어 + * + * @returns 곡 해석이 새로 생성되었으면 `true`, 이미 존재하면 `false` + */ +export async function ensureDefaultStory({ + track, + trackId, + requestId, + language, +}: SaveGeneratedStoryParams) { + // 1) 이미 봇 계정의 곡 해석이 존재하는지 확인 + const story = await getStoryDoc({ trackId, language, userId: "bot" }); + + // 1-1) 존재하면 복사 + if (story) { + await copyStoryDoc({ requestId, story: story.data }); + return false; + } + + // 2) 가사 제공자 결정하기 + const lyricsProvider = Object.keys(track.lyrics)[0] as keyof typeof track.lyrics | undefined; + if (!lyricsProvider) throw new Error(ERROR_CODES.LYRICS_NOT_FOUND); + + // 3) StoryUpdater 인스턴스 생성 + const storyUpdater = new StoryUpdater({ + track, + trackId, + requestId, + config: { language, lyricsProvider }, + }); + + // 4) generateStoryFlow 실행 + const { stream, output } = generateStoryFlow.stream({ + track, + config: { lyricsProvider, language }, + }); + + // 5) 스트림 및 최종 결과 처리 + for await (const chunk of stream) await storyUpdater.update(chunk); + await storyUpdater.complete(await output); + + return true; +} diff --git a/apps/functions/src/features/generate/triggers/onStoryRequestCreate/index.ts b/apps/functions/src/features/generate/triggers/onStoryRequestCreate/index.ts new file mode 100644 index 0000000..889046a --- /dev/null +++ b/apps/functions/src/features/generate/triggers/onStoryRequestCreate/index.ts @@ -0,0 +1 @@ +export { onStoryRequestCreate } from "./trigger"; diff --git a/apps/functions/src/features/generate/triggers/onStoryRequestCreate/trigger.ts b/apps/functions/src/features/generate/triggers/onStoryRequestCreate/trigger.ts new file mode 100644 index 0000000..c4a938e --- /dev/null +++ b/apps/functions/src/features/generate/triggers/onStoryRequestCreate/trigger.ts @@ -0,0 +1,39 @@ +import { StoryRequestSchema } from "@lymo/schemas/doc"; +import { ERROR_CODES } from "@lymo/schemas/error"; +import { logger } from "firebase-functions"; +import { onDocumentCreated } from "firebase-functions/firestore"; + +import CommonError from "@/features/shared/errors/CommonError"; +import { getOrCreateTrack } from "@/features/shared/tools/getOrCreateTrack"; + +import { ensureDefaultStory } from "./helpers"; + +export const onStoryRequestCreate = onDocumentCreated( + "storyRequests/{requestId}", + async (event) => { + try { + if (!event.data) return; + + const requestId = event.data.id; + const request = event.data.data(); + const input = StoryRequestSchema.parse(request); + + if (input.status !== "PENDING") throw new CommonError(ERROR_CODES.INVALID_INPUT); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { language, status, ...trackParams } = input; + + // 2) 트랙 조회 또는 생성 + const track = await getOrCreateTrack(trackParams); + + // 3) 곡 해석 생성 및 저장 + await ensureDefaultStory({ track: track.data, trackId: track.id, requestId, language }); + } catch (error) { + if (error instanceof CommonError) { + logger.error(`An error occurred in \`onStoryRequestCreate\`: ${error.code}`, error); + return; + } + + logger.error(`An unexpected error occurred in \`onStoryRequestCreate\``, error); + } + } +); diff --git a/apps/functions/src/features/generate/triggers/onStoryRequestCreate/utils.ts b/apps/functions/src/features/generate/triggers/onStoryRequestCreate/utils.ts new file mode 100644 index 0000000..aceb77b --- /dev/null +++ b/apps/functions/src/features/generate/triggers/onStoryRequestCreate/utils.ts @@ -0,0 +1,155 @@ +import { + GeneratedStoryFields, + GeneratedStoryFieldsSchema, + Story, + StoryRequest, + Track, +} from "@lymo/schemas/doc"; +import { ERROR_CODES } from "@lymo/schemas/error"; +import { Language, LyricsProvider } from "@lymo/schemas/shared"; +import admin from "firebase-admin"; +import { DocumentReference } from "firebase-admin/firestore"; + +const MIN_DELAY_BETWEEN_WRITES = 500; + +interface StoryUpdaterParams { + track: Track; + trackId: string; + requestId: string; + config: { + language: Language; + lyricsProvider: LyricsProvider; + }; +} + +/** + * `stories` 해석 문서와 `storyRequests/{requestId}` 문서를 업데이트하는 유틸리티 클래스 + */ +export class StoryUpdater { + track: Track; + trackId: string; + language: Language; + lyricsProvider: LyricsProvider; + + // story 본 문서 + storyDocRef: DocumentReference; + // storyRequests/{requestId} 문서 + storyRequestDocRef: DocumentReference; + + lastWrittenAt: number = 0; + pendingData: Partial = {}; + + constructor({ + track, + trackId, + requestId, + config: { language, lyricsProvider }, + }: StoryUpdaterParams) { + // 필드 초기화 + this.track = track; + this.trackId = trackId; + this.language = language; + this.lyricsProvider = lyricsProvider; + + // 문서 참조 생성 + this.storyDocRef = admin.firestore().collection("stories").doc() as DocumentReference; + this.storyRequestDocRef = admin + .firestore() + .collection("storyRequests") + .doc(requestId) as DocumentReference; + + // story preview 문서 초기화 + this.storyRequestDocRef.set({ + ...this.baseFields, + status: "PENDING", + }); + } + + /** + * 스로틀링이 적용된 업데이트 메서드 + * @param data 업데이트할 데이터 + * @returns 업데이트가 실제로 수행되었는지 여부 + */ + async update(data: Partial) { + // 업데이트할 데이터를 누적 + this.pendingData = { ...this.pendingData, ...data }; + + // 가장 마지막에 업데이트한 지 일정 시간이 지났을 때에만 업데이트 수행 + const nowTimestamp = Date.now(); + if (nowTimestamp - this.lastWrittenAt < MIN_DELAY_BETWEEN_WRITES) return false; + + // story preview 문서 업데이트 수행 + const now = new Date().toISOString(); + await this.storyRequestDocRef.update({ + ...this.pendingData, + updatedAt: now, + status: "IN_PROGRESS", + }); + + // 마지막 업데이트 시간 갱신 + this.lastWrittenAt = nowTimestamp; + + return true; + } + + /** + * 완료 처리 메서드 + * + * `data`가 제공되지 않은 경우, 마지막으로 스로틀링된 데이터를 사용하여 완료 처리합니다. + * @param data 완료 처리할 데이터 (선택 사항) + * @returns 완료 처리된 문서 + */ + async complete(data?: GeneratedStoryFields) { + const now = new Date().toISOString(); + const finalData = data ?? this.pendingData; + + try { + // finalData가 완성형인지 확인 + const parsedFinalData = GeneratedStoryFieldsSchema.parse(finalData); + + await Promise.all([ + // preview 문서 업데이트 + this.storyRequestDocRef.update({ + ...parsedFinalData, + status: "COMPLETED", + updatedAt: now, + }), + + // 본 문서 업데이트 + this.storyDocRef.set({ ...this.baseFields, ...parsedFinalData, updatedAt: now }), + ]); + } catch (error) { + // 검증 실패 시 story preview 문서의 상태를 FAILED로 업데이트 + await this.storyRequestDocRef.set({ + status: "FAILED", + errorCode: ERROR_CODES.STORY_SAVE_FAILED, + }); + + throw error; + } + } + + /** + * story 및 story preview 문서에 공통으로 들어가는 필드들 + */ + private get baseFields() { + const now = new Date().toISOString(); + + return { + trackId: this.trackId, + trackTitle: this.track.title, + trackArtists: this.track.artists, + trackAlbum: this.track.album, + trackAlbumArt: this.track.albumArt, + userId: "bot", + userName: "__BOT__", + userAvatar: null, + + language: this.language, + lyricsProvider: this.lyricsProvider, + + stats: { favoriteCount: 0, viewCount: 0 }, + updatedAt: now, + }; + } +} diff --git a/apps/functions/src/features/retrieve/flows/retrieveTrack/flow.ts b/apps/functions/src/features/retrieve/flows/retrieveTrack/flow.ts new file mode 100644 index 0000000..67bac09 --- /dev/null +++ b/apps/functions/src/features/retrieve/flows/retrieveTrack/flow.ts @@ -0,0 +1,27 @@ +import { + RetrieveTrackInputSchema as InputSchema, + RetrieveTrackOutputSchema as OutputSchema, +} from "@lymo/schemas/functions"; + +import ai from "@/core/genkit"; +import CommonError from "@/features/shared/errors/CommonError"; +import { getOrCreateTrack } from "@/features/shared/tools/getOrCreateTrack"; + +export const retrieveTrack = ai.defineFlow( + { + name: "retrieveTrack", + inputSchema: InputSchema, + outputSchema: OutputSchema, + }, + async (input) => { + try { + const track = await getOrCreateTrack(input); + return { success: true as const, data: track }; + } catch (error) { + if (error instanceof CommonError) { + return { success: false as const, error: error.code, message: error.message }; + } + throw error; + } + } +); diff --git a/apps/functions/src/features/retrieve/flows/retrieveTrack/handler.ts b/apps/functions/src/features/retrieve/flows/retrieveTrack/handler.ts new file mode 100644 index 0000000..94fc380 --- /dev/null +++ b/apps/functions/src/features/retrieve/flows/retrieveTrack/handler.ts @@ -0,0 +1,14 @@ +import { onCallGenkit } from "firebase-functions/https"; +import { defineSecret } from "firebase-functions/params"; + +import { retrieveTrack as retrieveTrackFlow } from "./flow"; + +const spotifyClientSecret = defineSecret("SPOTIFY_CLIENT_SECRET"); + +export const retrieveTrack = onCallGenkit( + { + cors: true, + secrets: [spotifyClientSecret], + }, + retrieveTrackFlow +); diff --git a/apps/functions/src/features/retrieve/flows/retrieveTrack/index.ts b/apps/functions/src/features/retrieve/flows/retrieveTrack/index.ts new file mode 100644 index 0000000..a9f93c6 --- /dev/null +++ b/apps/functions/src/features/retrieve/flows/retrieveTrack/index.ts @@ -0,0 +1 @@ +export { retrieveTrack } from "./handler"; diff --git a/apps/functions/src/features/shared/errors/CommonError.ts b/apps/functions/src/features/shared/errors/CommonError.ts new file mode 100644 index 0000000..7dd03b4 --- /dev/null +++ b/apps/functions/src/features/shared/errors/CommonError.ts @@ -0,0 +1,11 @@ +import { ErrorCode } from "@lymo/schemas/error"; + +export default class CommonError extends Error { + code: ErrorCode; + + constructor(errorCode: ErrorCode, message?: string) { + super(message); + this.name = "CommonError"; + this.code = errorCode; + } +} diff --git a/apps/functions/src/features/shared/helpers/getLyricsFromLRCLIB.ts b/apps/functions/src/features/shared/helpers/getLyricsFromLRCLIB.ts new file mode 100644 index 0000000..80ef8a5 --- /dev/null +++ b/apps/functions/src/features/shared/helpers/getLyricsFromLRCLIB.ts @@ -0,0 +1,53 @@ +import { searchLRCLib } from "@/features/shared/tools/searchLRCLib"; +import getCombinations from "@/features/shared/utils/getCombinations"; + +export interface LRCLIBResult { + lyrics: { + start: number; + end: number; + text: string; + }[]; + title: string; + artist: string; + album: string; + duration: number; +} + +interface GetLyricsFromLRCLIBParams { + title: string; + artists: string[]; + duration: number; +} + +/** + * @description LRCLIB에서 가사를 검색하는 헬퍼 함수 + * @param title 노래 제목 + * @param artists 아티스트 이름 배열 + * @param duration 노래 길이 (초) + * @returns lyricsProvider와 가사 데이터로 구성된 객체 또는 null (가사를 찾지 못한 경우) + */ +export default async function getLyricsFromLRCLIB({ + title, + artists, + duration, +}: GetLyricsFromLRCLIBParams) { + let lrcLibResult: LRCLIBResult | null = null; + for (let r = 1; r <= artists.length; r++) { + const artistStringCandidates = getCombinations(artists, r); + + for (const artistString of artistStringCandidates) { + const lrcLibResultCandidate = await searchLRCLib({ + title: title, + artist: artistString.join(" "), + duration: duration, + }); + + if (lrcLibResultCandidate) { + lrcLibResult = lrcLibResultCandidate; + break; + } + } + } + + return lrcLibResult; +} diff --git a/apps/functions/src/features/shared/tools/createTrackDoc.ts b/apps/functions/src/features/shared/tools/createTrackDoc.ts new file mode 100644 index 0000000..414d3dc --- /dev/null +++ b/apps/functions/src/features/shared/tools/createTrackDoc.ts @@ -0,0 +1,31 @@ +import { Track, TrackSchema } from "@lymo/schemas/doc"; +import admin from "firebase-admin"; +import { DocumentReference } from "firebase-admin/firestore"; +import { z } from "genkit"; + +import ai from "@/core/genkit"; + +const InputSchema = z.object({ + track: TrackSchema, + trackId: z.string(), +}); + +const OutputSchema = z.void(); + +export const createTrackDoc = ai.defineTool( + { + name: "createTrackDoc", + inputSchema: InputSchema, + outputSchema: OutputSchema, + description: "Create a track document in DB", + }, + async ({ track, trackId }) => { + // trackId 전달 시 + const trackRequestRef = admin + .firestore() + .collection("tracks") + .doc(trackId) as DocumentReference; + + await trackRequestRef.set(track); + } +); diff --git a/apps/functions/src/features/shared/tools/getOrCreateTrack.ts b/apps/functions/src/features/shared/tools/getOrCreateTrack.ts new file mode 100644 index 0000000..5945586 --- /dev/null +++ b/apps/functions/src/features/shared/tools/getOrCreateTrack.ts @@ -0,0 +1,83 @@ +import { Track, TrackSchema } from "@lymo/schemas/doc"; +import { ERROR_CODES } from "@lymo/schemas/error"; +import { z } from "genkit"; + +import ai from "@/core/genkit"; +import CommonError from "@/features/shared/errors/CommonError"; +import getLyricsFromLRCLIB from "@/features/shared/helpers/getLyricsFromLRCLIB"; +import { createTrackDoc } from "@/features/shared/tools/createTrackDoc"; +import { getTrackDoc } from "@/features/shared/tools/getTrackDoc"; +import { searchSpotify } from "@/features/shared/tools/searchSpotify"; + +export const InputSchema = z.union([ + z.object({ + trackId: z.string(), + }), + + z.object({ + title: z.string(), + artist: z.string(), + durationInSeconds: z.number(), + }), +]); + +export const OutputSchema = z.object({ + id: z.string(), + data: TrackSchema, +}); + +export const getOrCreateTrack = ai.defineTool( + { + name: "getOrCreateTrack", + inputSchema: InputSchema, + outputSchema: OutputSchema, + description: "Retrieve a track from the database or create it if it doesn't exist", + }, + async (input) => { + // 1) title, artist, durationInSeconds를 전달한 경우 트랙 검색 + if ("title" in input && "artist" in input && "durationInSeconds" in input) { + // 1-1) DB에서 먼저 조회 + const trackResult = await getTrackDoc(input); + if (trackResult) return trackResult; + + // 1-2) DB에 없는 경우 외부 API에서 조회 + const spotifyResult = await searchSpotify(input); + if (!spotifyResult) throw new CommonError(ERROR_CODES.EXTERNAL_TRACK_NOT_FOUND); + const trackId = spotifyResult.id; + + // 1-3) LRCLIB에서 가사 검색 + const lrclibResult = await getLyricsFromLRCLIB({ + title: spotifyResult.title, + artists: spotifyResult.artists, + duration: spotifyResult.durationInSeconds, + }); + if (!lrclibResult) throw new CommonError(ERROR_CODES.LYRICS_NOT_FOUND); + + // 1-4) 곡 데이터 준비 + const now = new Date().toISOString(); + const track: Track = { + title: spotifyResult.title, + artists: spotifyResult.artists, + album: spotifyResult.album, + albumArt: spotifyResult.albumArt, + durationInSeconds: spotifyResult.durationInSeconds, + publishedAt: spotifyResult.publishedAt, + lyrics: { lrclib: lrclibResult.lyrics }, + createdAt: now, + stats: { storyCount: 0, viewCount: 0 }, + }; + + // 1-5) 문서 생성 및 반환 + await createTrackDoc({ trackId, track }); + return { id: trackId, data: track }; + } + + // 2) trackId를 전달한 경우 + else { + const trackQuery = await getTrackDoc(input); + if (trackQuery) return trackQuery; + + throw new CommonError(ERROR_CODES.TRACK_NOT_FOUND); + } + } +); diff --git a/apps/functions/src/features/shared/tools/getTrackDoc.ts b/apps/functions/src/features/shared/tools/getTrackDoc.ts new file mode 100644 index 0000000..fe2f1c0 --- /dev/null +++ b/apps/functions/src/features/shared/tools/getTrackDoc.ts @@ -0,0 +1,64 @@ +import { Track, TrackSchema } from "@lymo/schemas/doc"; +import admin from "firebase-admin"; +import { CollectionReference, DocumentReference } from "firebase-admin/firestore"; +import { z } from "genkit"; + +import ai from "@/core/genkit"; + +const InputSchema = z.union([ + z.object({ + trackId: z.string(), + }), + + z.object({ + title: z.string(), + artist: z.string(), + durationInSeconds: z.number(), + }), +]); + +export const OutputSchema = z + .object({ + id: z.string(), + data: TrackSchema, + }) + .nullable(); + +export const getTrackDoc = ai.defineTool( + { + name: "getTrackDoc", + inputSchema: InputSchema, + outputSchema: OutputSchema, + description: "Retrieve a track document from DB using its track ID", + }, + async (input) => { + // 1) trackId를 전달한 경우 + if ("trackId" in input) { + const trackDocRef = admin + .firestore() + .collection("tracks") + .doc(input.trackId) as DocumentReference; + + const trackSnap = await trackDocRef.get(); + const track = trackSnap.data(); + if (trackSnap.exists && track) return { id: trackSnap.id, data: track }; + } + + // 2) title, artist, durationInSeconds를 전달한 경우 + else { + const trackCollectionRef = admin + .firestore() + .collection("tracks") as CollectionReference; + const q = trackCollectionRef + .where("title", "==", input.title) + .where("artist", "==", input.artist) + .where("durationInSeconds", "==", input.durationInSeconds) + .limit(1); + + const trackSnap = (await q.get()).docs[0]; + if (trackSnap?.exists) return { id: trackSnap.id, data: trackSnap.data() }; + } + + return null; + } +); diff --git a/apps/functions/src/tools/searchLRCLib.ts b/apps/functions/src/features/shared/tools/searchLRCLib.ts similarity index 77% rename from apps/functions/src/tools/searchLRCLib.ts rename to apps/functions/src/features/shared/tools/searchLRCLib.ts index 2a260f1..7650d71 100644 --- a/apps/functions/src/tools/searchLRCLib.ts +++ b/apps/functions/src/features/shared/tools/searchLRCLib.ts @@ -2,8 +2,7 @@ import axios from "axios"; import { z } from "genkit"; import ai from "@/core/genkit"; -import type { RawLRCLIBResult } from "@/types/lrclib"; -import parseLyrics from "@/utils/parseLyrics"; +import parseLyrics from "@/features/shared/utils/parseLyrics"; export const SearchLRCLibInputSchema = z.object({ title: z.string().describe("The title of the song"), @@ -27,7 +26,17 @@ export const SearchLRCLibOutputSchema = z }) .nullable(); -type LRCLibSearchResponse = RawLRCLIBResult[]; +export interface LRCLIBSearchItem { + id: number; + name: string; + trackName: string; + artistName: string; + albumName: string; + duration: number; + instrumental: boolean; + plainLyrics: string; + syncedLyrics: string | null; +} export const searchLRCLib = ai.defineTool( { @@ -38,7 +47,7 @@ export const searchLRCLib = ai.defineTool( "Fetch the lyrics, title, artist and album of a song given its title, artist and duration in seconds from LRCLib", }, async ({ title, artist, duration }) => { - const response = await axios.get("https://lrclib.net/api/search", { + const response = await axios.get("https://lrclib.net/api/search", { params: { track_name: title, artist_name: artist }, }); @@ -48,7 +57,7 @@ export const searchLRCLib = ai.defineTool( const songs = response.data; // 후보 검증 - let song: RawLRCLIBResult | null = null; + let song: LRCLIBSearchItem | null = null; for (const candidate of songs) { if (Math.abs(candidate.duration - duration) > 2) continue; const { syncedLyrics: lyricsString } = candidate; @@ -63,7 +72,9 @@ export const searchLRCLib = ai.defineTool( } // 형식 변환 - const lyrics = parseLyrics(song.syncedLyrics!, duration); + const { syncedLyrics } = song; + if (!syncedLyrics) throw new Error("Synced lyrics not found"); + const lyrics = parseLyrics(syncedLyrics, duration); return { lyrics, diff --git a/apps/functions/src/tools/searchSpotify.ts b/apps/functions/src/features/shared/tools/searchSpotify.ts similarity index 67% rename from apps/functions/src/tools/searchSpotify.ts rename to apps/functions/src/features/shared/tools/searchSpotify.ts index 5ceeec4..94298b3 100644 --- a/apps/functions/src/tools/searchSpotify.ts +++ b/apps/functions/src/features/shared/tools/searchSpotify.ts @@ -1,24 +1,27 @@ +import { defineSecret } from "firebase-functions/params"; import { z } from "genkit"; import ai from "@/core/genkit"; import spotify from "@/core/spotify"; -import calculateSimilarity from "@/utils/calculateSimilarity"; +import calculateSimilarity from "@/features/shared/utils/calculateSimilarity"; + +const spotifyClientSecret = defineSecret("SPOTIFY_CLIENT_SECRET"); export const SearchSpotifyInputSchema = z.object({ title: z.string().describe("The title of the song"), artist: z.string().describe("The artist of the song"), - duration: z.number().describe("The duration of the song in seconds"), + durationInSeconds: z.number().describe("The duration of the song in seconds"), }); export const SearchSpotifyOutputSchema = z .object({ id: z.string().describe("The ID of the song"), title: z.string().describe("The title of the song"), - artist: z.array(z.string()).describe("The artists of the song"), + artists: z.string().array().describe("The artists of the song"), album: z.string().nullable().describe("The album of the song"), - coverUrl: z.string().describe("The cover URL of the song"), + albumArt: z.string().describe("The cover URL of the song"), publishedAt: z.string().describe("The published date of the song").nullable(), - duration: z.number().describe("The duration of the song in seconds"), + durationInSeconds: z.number().describe("The duration of the song in seconds"), }) .nullable(); @@ -30,7 +33,8 @@ export const searchSpotify = ai.defineTool( description: "Fetch the official title, artist, album, cover URL, published date and summary of a song given its title and artist from Spotify", }, - async ({ title, artist, duration }) => { + async ({ title, artist, durationInSeconds }) => { + spotify.setClientSecret(spotifyClientSecret.value()); const credentialsResponse = await spotify.clientCredentialsGrant(); spotify.setAccessToken(credentialsResponse.body["access_token"]); @@ -43,21 +47,23 @@ export const searchSpotify = ai.defineTool( let mostAccurateTrack: SpotifyApi.TrackObjectFull = tracks[0]; let highestScore = -1; for (const track of tracks) { - const score = getAccurationScore(track, { title, artist, duration }); + const score = getAccurationScore(track, { title, artist, durationInSeconds }); if (score > highestScore) { highestScore = score; mostAccurateTrack = track; } } + const id = mostAccurateTrack.external_ids.isrc ?? mostAccurateTrack.id; + return { - id: mostAccurateTrack.id, + id, title: mostAccurateTrack.name, - artist: mostAccurateTrack.artists.map((a) => a.name), + artists: mostAccurateTrack.artists.map((a) => a.name), album: mostAccurateTrack.album.name || null, - coverUrl: mostAccurateTrack.album.images[0]?.url || "", + albumArt: mostAccurateTrack.album.images[0]?.url || "", publishedAt: mostAccurateTrack.album.release_date || null, - duration: Math.floor(mostAccurateTrack.duration_ms / 1000), + durationInSeconds: Math.floor(mostAccurateTrack.duration_ms / 1000), }; } ); @@ -65,12 +71,12 @@ export const searchSpotify = ai.defineTool( const SCORE_WEIGHTS = { title: 0.3, artist: 0.2, - duration: 0.5, + durationInSeconds: 0.5, }; function getAccurationScore( track: SpotifyApi.TrackObjectFull, - query: { title: string; artist: string; duration: number } + query: { title: string; artist: string; durationInSeconds: number } ): number { // 1. 제목 const title = track.name.toLowerCase().replace(/\(.*?\)/g, ""); @@ -85,14 +91,14 @@ function getAccurationScore( // 3. 재생 시간 점수 const durationScore = Math.max( 0, - 1 - Math.abs(track.duration_ms / 1000 - query.duration) / query.duration + 1 - Math.abs(track.duration_ms / 1000 - query.durationInSeconds) / query.durationInSeconds ); - // 4. 가중치를 적용하여 최종 점수를 합산합니다. + // 4. 가중치를 적용하여 최종 점수 계산 const finalScore = titleScore * SCORE_WEIGHTS.title + artistScore * SCORE_WEIGHTS.artist + - durationScore * SCORE_WEIGHTS.duration; + durationScore * SCORE_WEIGHTS.durationInSeconds; return finalScore; } diff --git a/apps/functions/src/utils/calculateSimilarity.ts b/apps/functions/src/features/shared/utils/calculateSimilarity.ts similarity index 100% rename from apps/functions/src/utils/calculateSimilarity.ts rename to apps/functions/src/features/shared/utils/calculateSimilarity.ts diff --git a/apps/functions/src/utils/getCombinations.ts b/apps/functions/src/features/shared/utils/getCombinations.ts similarity index 100% rename from apps/functions/src/utils/getCombinations.ts rename to apps/functions/src/features/shared/utils/getCombinations.ts diff --git a/apps/functions/src/utils/parseLyrics.ts b/apps/functions/src/features/shared/utils/parseLyrics.ts similarity index 84% rename from apps/functions/src/utils/parseLyrics.ts rename to apps/functions/src/features/shared/utils/parseLyrics.ts index 4c8357d..5774a3d 100644 --- a/apps/functions/src/utils/parseLyrics.ts +++ b/apps/functions/src/features/shared/utils/parseLyrics.ts @@ -1,18 +1,11 @@ -interface Sentence { - start: number; - end: number; - text: string; -} +import { Lyric } from "@lymo/schemas/shared"; /** * `[MM:SS.SS] 가사` 형식의 문자열을 문장별로 분리하여 시작 시간, 종료 시간, 가사 텍스트를 포함하는 객체 배열로 변환합니다. * @param lyricsString - 변환할 원본 가사 문자열 * @returns 변환된 가사 배열 */ -export default function parseLyrics( - lyricsString: string, - duration: number -): Sentence[] { +export default function parseLyrics(lyricsString: string, duration: number): Lyric[] { // 1. 문자열을 줄바꿈(\n) 기준으로 나눕니다. const lines = lyricsString.split("\n"); @@ -55,8 +48,8 @@ export default function parseLyrics( parsedData[parsedData.length - 1].end = duration; } - const result: Sentence[] = parsedData.filter((item): item is Sentence => { - return item.start !== undefined && item.text !== undefined; + const result: Lyric[] = parsedData.filter((item): item is Lyric => { + return item.start !== undefined && item.end !== undefined && item.text !== undefined; }); return result; diff --git a/apps/functions/src/flows/addTrack.flow.ts b/apps/functions/src/flows/addTrack.flow.ts deleted file mode 100644 index 775ae0a..0000000 --- a/apps/functions/src/flows/addTrack.flow.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { LyricsDoc, TrackDoc } from "@lymo/schemas/doc"; -import { AddTrackFlowInputSchema, AddTrackFlowOutputSchema } from "@lymo/schemas/function"; -import { LyricsProvider } from "@lymo/schemas/shared"; -import admin from "firebase-admin"; -import { DocumentReference } from "firebase-admin/firestore"; -import { logger } from "genkit/logging"; - -import ai from "@/core/genkit"; -import getLyricsFromLRCLIB from "@/helpers/addTrack/getLyricsFromLRCLIB"; -import getLyricsFromDB from "@/helpers/shared/getLyricsFromDB"; -import getTrackFromDB from "@/helpers/shared/getTrackFromDB"; -import { searchSpotify } from "@/tools/searchSpotify"; - -/** - * @description 음악 제목과 아티스트명을 입력받아 메타데이터와 가사 원문을 가져오고 DB에 저장하는 플로우 - * - * DB에 이미 존재하는 트랙인 경우, 기존 데이터를 반환합니다. - */ -export const addTrackFlow = ai.defineFlow( - { - name: "addTrackFlow", - inputSchema: AddTrackFlowInputSchema, - outputSchema: AddTrackFlowOutputSchema, - }, - async (input) => { - try { - // 1) title과 arist가 둘 다 빈 문자열인 경우 - if (input.title.trim() === "" && input.artist.trim() === "") - return { notFound: true as const }; - - // 2) Spotify에서 곡 검색 - const spotifyResult = await searchSpotify({ - title: input.title, - artist: input.artist, - duration: input.duration, - }); - if (spotifyResult === null) return { notFound: true as const }; - const trackId = spotifyResult.id; - - // 3) 중복 확인 - const existingTrack = await getTrackFromDB(trackId); - if (existingTrack) { - const existingLyrics = await getLyricsFromDB(trackId); - - // 3-1) 기존에 가사 상세 정보가 모두 있는 경우 바로 반환 - if (existingLyrics) { - return { - id: trackId, - track: { - ...existingTrack, - play: existingTrack.play ?? 0, // for legacy data - }, - lyrics: existingLyrics.lyrics, - lyricsProvider: existingLyrics.provider, - notFound: false as const, - }; - } - } - - // 4) LRCLIB에서 곡 검색 - const lrclibResult = await getLyricsFromLRCLIB( - spotifyResult.title, - spotifyResult.artist, - spotifyResult.duration - ); - if (!lrclibResult) return { notFound: true as const }; - const lyricsProvider: LyricsProvider = "lrclib"; - - // 5) 트랙 및 가사 정보를 DB에 저장 - const trackDocRef = admin - .firestore() - .collection("tracks") - .doc(trackId) as DocumentReference; - const lyricsDocRef = trackDocRef - .collection("lyrics") - .doc(lyricsProvider) as DocumentReference; - - const track: TrackDoc = { - album: spotifyResult.album, - artist: spotifyResult.artist, - coverUrl: spotifyResult.coverUrl, - duration: spotifyResult.duration, - publishedAt: spotifyResult.publishedAt, - title: spotifyResult.title, - createdAt: new Date().toISOString(), - lyricsProviders: [lyricsProvider], - play: 0, - }; - - await admin.firestore().runTransaction(async (transaction) => { - transaction.set(trackDocRef, track); - transaction.set(lyricsDocRef, { - lyrics: lrclibResult.lyrics, - }); - }); - - // 6) 트랙 및 가사 정보 반환 - return { - id: trackId, - track, - lyrics: lrclibResult.lyrics, - lyricsProvider, - notFound: false as const, - }; - } catch (error) { - logger.error("An error occurred in addTrackFlow", error); - return { notFound: true as const }; - } - } -); diff --git a/apps/functions/src/flows/addTrack.handler.ts b/apps/functions/src/flows/addTrack.handler.ts deleted file mode 100644 index ead1fb5..0000000 --- a/apps/functions/src/flows/addTrack.handler.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { onCallGenkit } from "firebase-functions/v2/https"; - -import { addTrackFlow } from "./addTrack.flow"; - -const addTrack = onCallGenkit( - { - cors: true, - timeoutSeconds: 300, - region: "asia-northeast3", - }, - addTrackFlow -); - -export default addTrack; diff --git a/apps/functions/src/flows/generateDetail.flow.ts b/apps/functions/src/flows/generateDetail.flow.ts deleted file mode 100644 index cbd07d7..0000000 --- a/apps/functions/src/flows/generateDetail.flow.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { ProviderDoc, TrackDetailDoc } from "@lymo/schemas/doc"; -import { - GenerateDetailFlowInputSchema, - GenerateDetailFlowOutputSchema, - GenerateDetailFlowStreamSchema, -} from "@lymo/schemas/function"; -import { LLMModel, Lyrics } from "@lymo/schemas/shared"; -import admin from "firebase-admin"; -import { DocumentReference } from "firebase-admin/firestore"; -import { logger } from "genkit/logging"; - -import ai from "@/core/genkit"; -import getTrackDetailFromDB from "@/helpers/generateDetail/getTrackDetailFromDB"; -import getLyricsFromDB from "@/helpers/shared/getLyricsFromDB"; -import getProviderNameFromLLMModel from "@/helpers/shared/getProviderNameFromLLMModel"; -import getTrackFromDB from "@/helpers/shared/getTrackFromDB"; - -import { groupLyricsFlow } from "./groupLyrics.flow"; -import { summarizeParagraphFlow } from "./summarizeParagraph.flow"; -import { summarizeSongFlow } from "./summarizeSong.flow"; -import { translateLyricsFlow } from "./translateLyrics.flow"; - -/** - * @description 트랙 상세 정보를 생성하는 플로우 - */ -export const generateDetailFlow = ai.defineFlow( - { - name: "generateDetailFlow", - inputSchema: GenerateDetailFlowInputSchema, - streamSchema: GenerateDetailFlowStreamSchema, - outputSchema: GenerateDetailFlowOutputSchema, - }, - async (input, sendChunk) => { - try { - // 1) 중복 확인 - const llmModel: LLMModel = input.model ?? "gemini-2.5-flash-lite"; - const providerName = getProviderNameFromLLMModel(llmModel); - const existingDetailDoc = await getTrackDetailFromDB({ - trackId: input.id, - language: input.language, - providerId: llmModel, - }); - if (existingDetailDoc) { - sendChunk({ event: "complete", data: null }); - return { success: true as const, exists: true as const, providerId: llmModel }; - } - - // 2) 곡 및 가사 문서 확인 - const [track, rawLyrics] = [ - await getTrackFromDB(input.id), - await getLyricsFromDB(input.id, input.lyricsProvider), - ]; - if (!track || !rawLyrics) { - sendChunk({ event: "complete", data: null }); - return { success: false as const, exists: false as const }; - } - - sendChunk({ - event: "lyrics_provider_set", - data: { lyricsProvider: rawLyrics.provider }, - }); - - // 3) 데이터 준비 - const baseData = { - title: track.title, - artist: track.artist.join(", "), - album: track.album, - language: input.language, - }; - - // 4) 가사 번역 생성 및 스트림 - const { stream: translateLyricsStream, output: translateLyricsOutput } = - translateLyricsFlow.stream({ ...baseData, lyrics: rawLyrics.lyrics }); - for await (const chunk of translateLyricsStream) { - sendChunk(chunk); - } - const translations = await translateLyricsOutput; - - // 4) 문단 나누기 - const breaks = await groupLyricsFlow({ - lyrics: rawLyrics.lyrics, - }); - sendChunk({ event: "lyrics_group", data: breaks }); - - // 5) 문단별 가사 구조 생성 - const lyrics: Lyrics = []; - let lastBreak = -1; - for (const breakIndex of breaks) { - lyrics.push({ - sentences: rawLyrics.lyrics - .slice(lastBreak + 1, breakIndex + 1) - .map((s) => ({ ...s, translation: null })), - summary: null, - }); - lastBreak = breakIndex; - } - lyrics.push({ - sentences: rawLyrics.lyrics.slice(lastBreak + 1).map((s) => ({ ...s, translation: null })), - summary: "", - }); - - // 6) 곡 요약 생성 - const { stream: summarizeSongStream, output: summarizeSongOutput } = summarizeSongFlow.stream( - { - ...baseData, - lyrics: rawLyrics.lyrics.map((sentence) => sentence.text), - } - ); - - // 7) 문단 요약 생성 - const { stream: summarizeParagraphStream, output: summarizeParagraphOutput } = - summarizeParagraphFlow.stream({ - ...baseData, - lyrics: lyrics.map((paragraph) => paragraph.sentences.map((sentence) => sentence.text)), - }); - - // 8) 스트림 처리 - await Promise.all( - [summarizeSongStream, summarizeParagraphStream].map((stream) => - (async () => { - for await (const chunk of stream) { - sendChunk(chunk); - } - })() - ) - ); - - // 7) 최종 결과 가져오기 - const [summary, paragraphSummaries] = await Promise.all([ - summarizeSongOutput, - summarizeParagraphOutput, - ]); - - // 10) 최종 결과 DB에 저장하기 - const providerDocRef = admin - .firestore() - .collection("tracks") - .doc(input.id) - .collection("providers") - .doc(llmModel) as DocumentReference; - const trackDetailDocRef = providerDocRef - .collection("details") - .doc(input.language) as DocumentReference; - - const date = new Date().toISOString(); - - admin.firestore().runTransaction(async (transaction) => { - // 11-1) 제공자 문서 생성 - transaction.set(providerDocRef, { - createdAt: date, - updatedAt: date, - providerName, - }); - - // 11-2) 트랙 상세 정보 저장 - transaction.set(trackDetailDocRef, { - summary, - lyricsSplitIndices: breaks, - lyricsProvider: rawLyrics.provider, - translations, - paragraphSummaries, - }); - }); - - sendChunk({ - event: "provider_set", - data: { createdAt: date, updatedAt: date, providerName, providerId: llmModel }, - }); - - sendChunk({ event: "complete", data: null }); - - // 12) 최종 결과 반환 - return { success: true as const, exists: false as const }; - } catch (error) { - logger.error("An error occurred in generateDetailFlow", error); - sendChunk({ event: "complete", data: null }); - return { success: false as const, exists: false as const }; - } - } -); diff --git a/apps/functions/src/flows/generateDetail.handler.ts b/apps/functions/src/flows/generateDetail.handler.ts deleted file mode 100644 index ce5a5b6..0000000 --- a/apps/functions/src/flows/generateDetail.handler.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { defineSecret } from "firebase-functions/params"; -import { onCallGenkit } from "firebase-functions/v2/https"; - -import { generateDetailFlow } from "./generateDetail.flow"; - -const spotifyClientSecret = defineSecret("SPOTIFY_CLIENT_SECRET"); -const geminiApiKey = defineSecret("GEMINI_API_KEY"); - -const generateDetail = onCallGenkit( - { - cors: true, - timeoutSeconds: 300, - secrets: [spotifyClientSecret, geminiApiKey], - region: "asia-northeast3", - }, - generateDetailFlow -); - -export default generateDetail; diff --git a/apps/functions/src/flows/groupLyrics.flow.ts b/apps/functions/src/flows/groupLyrics.flow.ts deleted file mode 100644 index 344eb49..0000000 --- a/apps/functions/src/flows/groupLyrics.flow.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { logger } from "firebase-functions"; -import { z } from "genkit"; - -import ai from "@/core/genkit"; - -export const GroupLyricsInputSchema = z.object({ - lyrics: z - .array( - z.object({ - start: z.number().describe("The start time of the sentence in seconds"), - end: z.number().describe("The end time of the sentence in seconds"), - text: z.string().describe("The text of the sentence"), - }) - ) - .describe("The lyrics of the song"), -}); - -export const GroupLyricsOutputSchema = z.array( - z.number().describe("An index where paragraphs should break") -); - -export const groupLyricsFlow = ai.defineFlow( - { - name: "groupLyricsFlow", - inputSchema: GroupLyricsInputSchema, - outputSchema: GroupLyricsOutputSchema, - }, - async ({ lyrics }) => { - if (lyrics.length <= 1) return []; - - let retry = 0; - let result: number[] | null = null; - - while (retry < 3) { - const response = await ai.generate({ - system: ` - ### Role - Expert Lyric Paragraph Organizer - - ### Task - Analyze the given song lyrics and determine where paragraph breaks should occur. - - ### Guidelines - - Consider the semantic meaning and flow of the lyrics. - - Consider the timing information (start/end times) of each line. - - Group lines that belong to the same thematic or narrative unit. - - Aim for paragraphs with 4-7 lines each, but prioritize semantic coherence over strict length. - - Do not create breaks at positions where the flow would be awkward. - - ### Output Format - - Return an array of indices (0-based) where paragraph breaks should occur. - - Each index represents the position AFTER which a new paragraph should start. - - For example, [2, 5] means: break after line 2 (so line 3 starts a new paragraph) and break after line 5 (so line 6 starts a new paragraph). - - The indices must be in ascending order. - - Return an empty array if no breaks are needed. - - ### Output Example - Input: 10 lines of lyrics - Output: [2, 5, 8] (creates 4 paragraphs: lines 0-2, 3-5, 6-8, 9) - `, - model: "googleai/gemini-2.5-flash-lite", - prompt: JSON.stringify({ lyrics }), - output: { - schema: GroupLyricsOutputSchema, - }, - config: { - temperature: 0.3, - }, - }); - - result = response.output ?? null; - - // 결과 검증: 인덱스가 유효한 범위 내에 있고 오름차순인지 확인 - if (result !== null) { - const isValid = result.every( - (idx, i, arr) => idx >= 0 && idx < lyrics.length - 1 && (i === 0 || idx > arr[i - 1]) - ); - - if (isValid) return result; - } - - retry++; - } - - // 3회 재시도 후에도 실패한 경우 빈 배열 반환 - logger.warn(`groupLyricsFlow: failed to generate valid paragraph breaks after retries.`); - return []; - } -); diff --git a/apps/functions/src/flows/summarizeParagraph.flow.ts b/apps/functions/src/flows/summarizeParagraph.flow.ts deleted file mode 100644 index cf229a1..0000000 --- a/apps/functions/src/flows/summarizeParagraph.flow.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { ParagraphSummaryAppendEventSchema } from "@lymo/schemas/event"; -import { LanguageSchema } from "@lymo/schemas/shared"; -import { logger } from "firebase-functions"; -import { z } from "genkit"; - -import ai from "@/core/genkit"; - -export const SummarizeParagraphInputSchema = z.object({ - title: z.string().describe("The title of the song"), - artist: z.string().describe("The artist of the song"), - album: z.string().nullable().describe("The album of the song"), - lyrics: z - .array( - z.array(z.string().describe("A sentence in the lyrics")).describe("A paragraph in the lyrics") - ) - .describe("The lyrics of the song, organized by paragraphs"), - language: LanguageSchema.describe("The target language of the summaries"), -}); - -export const SummarizeParagraphOutputSchema = z.array(z.string().nullable()); - -export const summarizeParagraphFlow = ai.defineFlow( - { - name: "summarizeParagraphFlow", - inputSchema: SummarizeParagraphInputSchema, - streamSchema: ParagraphSummaryAppendEventSchema, - outputSchema: SummarizeParagraphOutputSchema, - }, - async ({ title, artist, album, lyrics, language }, { sendChunk }) => { - let retry = 0; - let result: (string | null)[] | null = null; - - while (retry < 3) { - const { stream, response } = ai.generateStream({ - system: ` - ### Role - Expert Lyric Analyst - - ### Lyrics Analysis Guidelines - - The given lyrics are separated by paragraphs. - - Write an analysis for each paragraph. - - The analysis must concisely summarize the core content of the respective paragraph. - - The analysis must be written as a single paragraph. - - ### Output Format - - All summaries must be written in the given target language. - - Output an array containing the summaries corresponding to each paragraph. - - Treat paragraphs that do not require analysis as null. - - ### Output Example - ["Summary of the first paragraph", "Summary of the second paragraph", null, "Summary of the fourth paragraph"] - `, - prompt: JSON.stringify({ - title, - artist, - album, - lyrics, - targetLanguage: language, - }), - output: { - schema: z.array(z.string().nullable()), - }, - config: { - temperature: 0.3, - }, - }); - - let p = 0, - s = 0; - for await (const chunk of stream) { - const summaries = - chunk.output?.map((item) => (item?.trim() === "null" ? null : item)) ?? null; - if (summaries === null) continue; - for (; p < summaries.length; p++, s = 0) { - const summary = summaries[p]; - if (summary === null) continue; - sendChunk({ - event: "paragraph_summary_append", - data: { - paragraphIndex: p, - summary: summary.slice(s, summary.length), - }, - }); - s = summary.length; - - if (p === summaries.length - 1) break; - } - } - - result = - (await response).output?.map((item) => (item?.trim() === "null" ? null : item)) ?? null; - - // 문단 요약 개수가 입력된 문단 개수와 일치하면 결과 반환 - if (result !== null && result.length === lyrics.length) return result; - else retry++; - } - - // 3회 재시도 후에도 실패한 경우 마지막 결과 반환 - logger.warn(`summarizeParagraphFlow: summary count mismatch after retries.`, { - expected: lyrics.length, - actual: result?.length ?? 0, - retries: retry, - track: { title, artist, album }, - }); - return result ?? []; - } -); diff --git a/apps/functions/src/flows/summarizeSong.flow.ts b/apps/functions/src/flows/summarizeSong.flow.ts deleted file mode 100644 index fedc330..0000000 --- a/apps/functions/src/flows/summarizeSong.flow.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { SummaryAppendEventSchema } from "@lymo/schemas/event"; -import { LanguageSchema } from "@lymo/schemas/shared"; -import { z } from "genkit"; - -import ai from "@/core/genkit"; - -export const SummarizeSongInputSchema = z.object({ - title: z.string().describe("The title of the song"), - artist: z.string().describe("The artist of the song"), - album: z.string().nullable().describe("The album of the song"), - lyrics: z - .array(z.string().describe("A sentence from the lyrics")) - .describe("The lyrics of the song"), - language: LanguageSchema.describe("The language for the summary"), -}); - -export const SummarizeSongOutputSchema = z.string().describe("The summary of the song"); - -export const summarizeSongFlow = ai.defineFlow( - { - name: "summarizeSongFlow", - inputSchema: SummarizeSongInputSchema, - streamSchema: SummaryAppendEventSchema, - outputSchema: SummarizeSongOutputSchema, - }, - async ({ title, artist, album, lyrics, language }, { sendChunk }) => { - const { stream, response } = ai.generateStream({ - system: ` - ### Role - Based on the provided lyrics and metadata of a song, summarize the song's content. - - ### Goal - - Include the song's theme, message, and core storyline. - - Utilize web search to include the social context at the time of the song's release, its genre characteristics, and the artist's background. - - May also include behind-the-scenes stories, production process, and public reception. - - ### Constraints - - The summary must consist of 2 to 3 paragraphs. - - Paragraphs must be separated by two newline characters. - - The summary must be written in the given target language. - `, - prompt: JSON.stringify({ - title, - artist, - album, - lyrics, - targetLanguage: language, - }), - config: { - temperature: 0.3, - }, - }); - - for await (const chunk of stream) { - sendChunk({ - event: "summary_append", - data: { summary: chunk.text }, - }); - } - - const result = (await response).text; - return result; - } -); diff --git a/apps/functions/src/handlebars.d.ts b/apps/functions/src/handlebars.d.ts new file mode 100644 index 0000000..977c1f1 --- /dev/null +++ b/apps/functions/src/handlebars.d.ts @@ -0,0 +1,5 @@ +declare module "handlebars/dist/cjs/handlebars.js" { + import * as Handlebars from "handlebars"; + const handlebars: typeof Handlebars; + export default handlebars; +} diff --git a/apps/functions/src/helpers/addTrack/getLyricsFromLRCLIB.ts b/apps/functions/src/helpers/addTrack/getLyricsFromLRCLIB.ts deleted file mode 100644 index 61c10c2..0000000 --- a/apps/functions/src/helpers/addTrack/getLyricsFromLRCLIB.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { searchLRCLib } from "@/tools/searchLRCLib"; -import { LRCLIBResult } from "@/types/lrclib"; -import getCombinations from "@/utils/getCombinations"; - -export default async function getLyricsFromLRCLIB( - title: string, - artists: string[], - duration: number -) { - let lrcLibResult: LRCLIBResult | null = null; - for (let r = 1; r <= artists.length; r++) { - const artistStringCandidates = getCombinations(artists, r); - - for (const artistString of artistStringCandidates) { - const lrcLibResultCandidate = await searchLRCLib({ - title: title, - artist: artistString.join(" "), - duration: duration, - }); - - if (lrcLibResultCandidate) { - lrcLibResult = lrcLibResultCandidate; - break; - } - } - } - - return lrcLibResult; -} diff --git a/apps/functions/src/helpers/generateDetail/getTrackDetailFromDB.ts b/apps/functions/src/helpers/generateDetail/getTrackDetailFromDB.ts deleted file mode 100644 index fd9c531..0000000 --- a/apps/functions/src/helpers/generateDetail/getTrackDetailFromDB.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { TrackDetailDoc } from "@lymo/schemas/doc"; -import type { Language } from "@lymo/schemas/shared"; -import admin from "firebase-admin"; -import { DocumentReference } from "firebase-admin/firestore"; - -export default async function getTrackDetailFromDB({ - trackId, - language, - providerId, -}: { - trackId: string; - language: Language; - providerId: string; -}) { - const detailCollection = admin - .firestore() - .collection("tracks") - .doc(trackId) - .collection("providers") - .doc(providerId) - .collection("details") - .doc(language) as DocumentReference; - - const detailData = (await detailCollection.get()).data(); - return detailData ?? null; -} diff --git a/apps/functions/src/helpers/shared/getLyricsFromDB.ts b/apps/functions/src/helpers/shared/getLyricsFromDB.ts deleted file mode 100644 index 3e99d0d..0000000 --- a/apps/functions/src/helpers/shared/getLyricsFromDB.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { LyricsDoc } from "@lymo/schemas/doc"; -import type { LyricsProvider } from "@lymo/schemas/shared"; -import admin from "firebase-admin"; -import { DocumentReference } from "firebase-admin/firestore"; - -/** - * @description 특정 trackId에 해당하는 Lyrics 문서를 DB에서 가져옵니다. - * @param trackId 가져올 트랙의 ID - * @param lyricsProvider (선택 사항) 특정 가사 제공자를 지정합니다. 지정하지 않으면 정해진 우선 순위에 따라 첫 번째로 발견된 문서를 반환합니다. - * @returns 가사 제공자와 Lyrics 문서 데이터로 이루어진 객체, 또는 null (존재하지 않는 경우) - */ -export default async function getLyricsFromDB(trackId: string, lyricsProvider?: LyricsProvider) { - const lyricsCollectionRef = admin - .firestore() - .collection("tracks") - .doc(trackId) - .collection("lyrics"); - - // 특정 가사 제공자가 지정된 경우 - if (lyricsProvider) { - const lyricsDocRef = lyricsCollectionRef.doc(lyricsProvider) as DocumentReference; - const lyricsData = (await lyricsDocRef.get()).data()?.lyrics; - if (lyricsData) return { lyrics: lyricsData, provider: lyricsProvider }; - } - - // 가사 제공자가 지정되지 않은 경우, 우선 순위에 따라 첫 번째로 발견된 문서를 반환 - const lyricsProviders: LyricsProvider[] = ["lrclib", "none"]; - - let result: { lyrics: LyricsDoc["lyrics"]; provider: LyricsProvider } | null = null; - for (const provider of lyricsProviders) { - const lyricsDocRef = lyricsCollectionRef.doc(provider) as DocumentReference; - const lyricsData = (await lyricsDocRef.get()).data()?.lyrics; - - if (lyricsData) { - result = { lyrics: lyricsData, provider }; - break; - } - } - - return result; -} diff --git a/apps/functions/src/helpers/shared/getProviderNameFromLLMModel.ts b/apps/functions/src/helpers/shared/getProviderNameFromLLMModel.ts deleted file mode 100644 index 5e98f32..0000000 --- a/apps/functions/src/helpers/shared/getProviderNameFromLLMModel.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { LLMModel } from "@lymo/schemas/shared"; - -export default function getProviderNameFromLLMModel(model: LLMModel) { - switch (model) { - case "gemini-2.5-flash": - return "Gemini 2.5 Flash"; - case "gemini-2.5-flash-lite": - return "Gemini 2.5 Flash Lite"; - } -} diff --git a/apps/functions/src/helpers/shared/getTrackFromDB.ts b/apps/functions/src/helpers/shared/getTrackFromDB.ts deleted file mode 100644 index 528cd71..0000000 --- a/apps/functions/src/helpers/shared/getTrackFromDB.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { TrackDoc } from "@lymo/schemas/doc"; -import admin from "firebase-admin"; -import { DocumentReference } from "firebase-admin/firestore"; - -/** - * @description 특정 trackId에 해당하는 Track 문서를 DB에서 가져옵니다. - * @param trackId 가져올 트랙의 ID - * @returns Track 문서 데이터 또는 null (존재하지 않는 경우) - */ -export default async function getTrackFromDB(trackId: string) { - const trackDocRef = admin - .firestore() - .collection("tracks") - .doc(trackId) as DocumentReference; - const trackData = (await trackDocRef.get()).data(); - - return trackData ?? null; -} diff --git a/apps/functions/src/index.ts b/apps/functions/src/index.ts index 9752353..d903021 100644 --- a/apps/functions/src/index.ts +++ b/apps/functions/src/index.ts @@ -1,9 +1,5 @@ import "@/core/init"; import "@/core/admin"; -export { default as addTrack } from "@/flows/addTrack.handler"; -export { default as generateDetail } from "@/flows/generateDetail.handler"; -export { searchLastfm } from "@/tools/searchLastfm"; -export { searchLRCLib } from "@/tools/searchLRCLib"; -export { searchSpotify } from "@/tools/searchSpotify"; -export { groupLyricsFlow } from "@/flows/groupLyrics.flow"; +export { onStoryRequestCreate } from "./features/generate/triggers/onStoryRequestCreate"; +export { retrieveTrack } from "./features/retrieve/flows/retrieveTrack"; diff --git a/apps/functions/src/tools/groupLyrics.ts b/apps/functions/src/tools/groupLyrics.ts deleted file mode 100644 index 5489260..0000000 --- a/apps/functions/src/tools/groupLyrics.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { logger } from "firebase-functions"; -import { z } from "genkit"; - -import ai from "@/core/genkit"; - -export const GroupLyricsInputSchema = z.object({ - lyrics: z - .array( - z.object({ - start: z.number().describe("The start time of the sentence in seconds"), - end: z.number().describe("The end time of the sentence in seconds"), - text: z.string().describe("The text of the sentence"), - }) - ) - .describe("The lyrics of the song"), -}); - -export const GroupLyricsOutputSchema = z.array( - z.number().describe("An index where paragraphs should break") -); - -export const groupLyricsFlow = ai.defineFlow( - { - name: "groupLyricsFlow", - inputSchema: GroupLyricsInputSchema, - outputSchema: GroupLyricsOutputSchema, - }, - async ({ lyrics }) => { - if (lyrics.length <= 1) return []; - - let retry = 0; - let result: number[] | null = null; - - while (retry < 3) { - const response = await ai.generate({ - system: ` - ### Role - Expert Lyric Paragraph Organizer - - ### Task - Analyze the given song lyrics and determine where paragraph breaks should occur. - - ### Guidelines - - Consider the semantic meaning and flow of the lyrics. - - Consider the timing information (start/end times) of each line. - - Group lines that belong to the same thematic or narrative unit. - - Aim for paragraphs with 4-7 lines each, but prioritize semantic coherence over strict length. - - Do not create breaks at positions where the flow would be awkward. - - ### Output Format - - Return an array of indices (0-based) where paragraph breaks should occur. - - Each index represents the position AFTER which a new paragraph should start. - - For example, [2, 5] means: break after line 2 (so line 3 starts a new paragraph) and break after line 5 (so line 6 starts a new paragraph). - - The indices must be in ascending order. - - Return an empty array if no breaks are needed. - - ### Output Example - Input: 10 lines of lyrics - Output: [2, 5, 8] (creates 4 paragraphs: lines 0-2, 3-5, 6-8, 9) - `, - prompt: JSON.stringify({ lyrics }), - output: { - schema: GroupLyricsOutputSchema, - }, - config: { - temperature: 0.3, - }, - }); - - result = response.output ?? null; - - // 결과 검증: 인덱스가 유효한 범위 내에 있고 오름차순인지 확인 - if (result !== null) { - const isValid = result.every( - (idx, i, arr) => idx >= 0 && idx < lyrics.length - 1 && (i === 0 || idx > arr[i - 1]) - ); - if (isValid) return result; - } - - retry++; - } - - // 3회 재시도 후에도 실패한 경우 빈 배열 반환 - logger.warn(`groupLyricsFlow: failed to generate valid paragraph breaks after retries.`); - return []; - } -); diff --git a/apps/functions/src/tools/searchLastfm.ts b/apps/functions/src/tools/searchLastfm.ts deleted file mode 100644 index e62461b..0000000 --- a/apps/functions/src/tools/searchLastfm.ts +++ /dev/null @@ -1,87 +0,0 @@ -import axios from "axios"; -import { defineSecret } from "firebase-functions/params"; -import { z } from "genkit"; - -import ai from "@/core/genkit"; - -const lastfmApiKey = defineSecret("LASTFM_API_KEY"); - -export const SearchLastfmInputSchema = z.object({ - title: z.string().describe("The title of the song"), - artist: z.string().describe("The artist of the song"), -}); - -export const SearchLastfmOutputSchema = z - .object({ - title: z.string().describe("The title of the song"), - artist: z.string().describe("The artist of the song"), - album: z.string().nullable().describe("The album of the song"), - coverUrl: z.string().describe("The cover URL of the song"), - publishedAt: z.string().describe("The published date of the song").nullable(), - summary: z.string().describe("The summary of the song").nullable(), - }) - .nullable(); - -type LastfmSearchResponse = { - track?: { - name: string; - artist: { - name: string; - }; - album?: { - title: string; - image: { "#text": string; size: string }[]; - }; - wiki?: { - published: string; - content: string; - }; - }; -}; - -export const searchLastfm = ai.defineTool( - { - name: "searchLastfm", - inputSchema: SearchLastfmInputSchema, - outputSchema: SearchLastfmOutputSchema, - description: - "Fetch the official title, artist, album, cover URL, published date and summary of a song given its title and artist from Last.fm", - }, - async ({ title, artist }) => { - const response = await axios.get( - "https://ws.audioscrobbler.com/2.0/?method=track.getInfo", - { - params: { - api_key: lastfmApiKey.value(), - track: title, - artist, - format: "json", - }, - } - ); - - if (response.status !== 200) throw new Error("Failed to fetch lyrics from Last.fm"); - - const track = response.data.track; - if (!track) { - return null; - } - - const coverUrl = track.album?.image.find((img) => img.size === "extralarge")?.["#text"] ?? ""; - const publishedAt = track.wiki?.published || null; - let summary = track.wiki?.content || null; - if (summary) { - summary = summary.replace(/<[^>]+>/g, ""); - summary = summary.replace(/\s+/g, " ").trim(); - } - - return { - title: track.name, - artist: track.artist.name, - album: track.album?.title ?? null, - coverUrl, - publishedAt, - summary, - }; - } -); diff --git a/apps/functions/src/types/lrclib.ts b/apps/functions/src/types/lrclib.ts deleted file mode 100644 index 6499fbf..0000000 --- a/apps/functions/src/types/lrclib.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface RawLRCLIBResult { - id: number; - name: string; - trackName: string; - artistName: string; - albumName: string; - duration: number; - instrumental: boolean; - plainLyrics: string; - syncedLyrics: string | null; -} - -export interface LRCLIBResult { - lyrics: { - start: number; - end: number; - text: string; - }[]; - title: string; - artist: string; - album: string; - duration: number; -} diff --git a/apps/functions/src/types/spotify.ts b/apps/functions/src/types/spotify.ts deleted file mode 100644 index b92553b..0000000 --- a/apps/functions/src/types/spotify.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface SpotifyResult { - id: string; - title: string; - artist: string[]; - album: string | null; - coverUrl: string; - publishedAt: string | null; - duration: number; -} diff --git a/apps/functions/src/utils/averageEmbeddings.ts b/apps/functions/src/utils/averageEmbeddings.ts deleted file mode 100644 index 74cc803..0000000 --- a/apps/functions/src/utils/averageEmbeddings.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default function averageEmbeddings(embeddings: number[][]): number[] { - if (embeddings.length === 0) return []; - const vectorLength = embeddings[0].length; - const sumVector = new Array(vectorLength).fill(0); - - for (const embedding of embeddings) { - for (let i = 0; i < vectorLength; i++) { - sumVector[i] += embedding[i]; - } - } - return sumVector.map((val) => val / embeddings.length); -} diff --git a/apps/functions/src/utils/calculateCosineDistance.ts b/apps/functions/src/utils/calculateCosineDistance.ts deleted file mode 100644 index 458aacb..0000000 --- a/apps/functions/src/utils/calculateCosineDistance.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * 코사인 유사도를 계산하는 함수입니다. - * @param vecA 벡터 A - * @param vecB 벡터 B - * @returns 코사인 거리 (0 ~ 1) - */ -export default function calculateCosineDistance( - vecA: number[], - vecB: number[] -): number { - const dotProduct = vecA.reduce((sum, a, i) => sum + a * vecB[i], 0); - const magnitudeA = Math.sqrt(vecA.reduce((sum, val) => sum + val * val, 0)); - const magnitudeB = Math.sqrt(vecB.reduce((sum, val) => sum + val * val, 0)); - - if (magnitudeA === 0 || magnitudeB === 0) return 1; // 제로 벡터는 의미가 없으므로 최대 거리로 처리 - - const similarity = dotProduct / (magnitudeA * magnitudeB); - return 1 - similarity; -} diff --git a/apps/functions/src/utils/convertLanguageTag.ts b/apps/functions/src/utils/convertLanguageTag.ts deleted file mode 100644 index 5052f93..0000000 --- a/apps/functions/src/utils/convertLanguageTag.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Language } from "@lymo/schemas/shared"; - -export default function convertLanguageTag(language: Language) { - switch (language) { - case "ko": - return "Korean"; - case "en": - return "English"; - default: - return "English"; - } -} diff --git a/apps/functions/src/utils/findIndex.ts b/apps/functions/src/utils/findIndex.ts deleted file mode 100644 index 74e27fc..0000000 --- a/apps/functions/src/utils/findIndex.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 주어진 2차원 배열에서 전체 인덱스 `i`에 해당하는 위치를 찾아 반환합니다. - * @param arr 2차원 배열 - * @param i 전체 인덱스 - * @returns 바깥 및 안쪽 인덱스 객체 또는 null (범위 벗어남) - */ -export default function findIndex( - arr: T[][], - i: number -): { outer: number; inner: number } | null { - let currentIndex = 0; - - // 바깥쪽 배열 순회 - for (let outerIndex = 0; outerIndex < arr.length; outerIndex++) { - const innerArray = arr[outerIndex]; - - // i가 현재 내부 배열의 범위 내에 있는지 확인 - if (i < currentIndex + innerArray.length) { - const innerIndex = i - currentIndex; - return { outer: outerIndex, inner: innerIndex }; - } - - // 다음 배열을 위해 현재 배열의 길이를 더함 - currentIndex += innerArray.length; - } - - // i가 배열의 총 길이를 벗어나는 경우 - return null; -} diff --git a/apps/functions/src/utils/getSyllableCount.ts b/apps/functions/src/utils/getSyllableCount.ts deleted file mode 100644 index 352af0d..0000000 --- a/apps/functions/src/utils/getSyllableCount.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { syllable } from "syllable"; - -/** - * 한글과 영어로 이루어진 텍스트의 음절 수를 계산합니다. - * @param text 음절 수를 계산할 텍스트 - * @returns 텍스트의 음절 수 - */ - -export default function getSyllableCount(text: string): number { - // 한글과 영어 분리 - const koreanRegex = /[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]+/g; - const englishRegex = /[a-zA-Z]+/g; - const koreanParts = text.match(koreanRegex) || []; - const englishParts = text.match(englishRegex) || []; - - // 한글 음절 수 계산 - const koreanSyllableCount = koreanParts.reduce((acc, part) => { - return acc + part.length; - }, 0); - // 영어 음절 수 계산 - const englishSyllableCount = englishParts.reduce((acc, part) => { - return acc + syllable(part); - }, 0); - - return koreanSyllableCount + englishSyllableCount; -} diff --git a/apps/functions/src/utils/normalize.ts b/apps/functions/src/utils/normalize.ts deleted file mode 100644 index 274a3c8..0000000 --- a/apps/functions/src/utils/normalize.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * 숫자 배열을 0과 1 사이로 정규화합니다. - * @param scores 숫자 배열 - * @returns 정규화된 숫자 배열 - */ -export default function normalize(scores: number[]): number[] { - const min = Math.min(...scores); - const max = Math.max(...scores); - if (max === min) return scores.map(() => 0); // 모든 값이 같으면 0으로 처리 - return scores.map((score) => (score - min) / (max - min)); -} diff --git a/apps/functions/src/utils/parseDuration.ts b/apps/functions/src/utils/parseDuration.ts deleted file mode 100644 index bd11985..0000000 --- a/apps/functions/src/utils/parseDuration.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * MM:SS 형식의 기간 문자열을 초 단위로 변환합니다. - * @param duration MM:SS 형식의 기간 문자열 (예: "2:03") - * @returns 초 단위로 변환된 기간 (예: 123) - */ -export default function parseDuration(duration: string): number { - const parts = duration.split(":").map(Number); - if (parts.length !== 2 && parts.length !== 3) { - throw new Error("Invalid duration format"); - } - let seconds = 0; - if (parts.length === 3) { - // HH:MM:SS 형식 - seconds += parts[0] * 3600; // 시간 - seconds += parts[1] * 60; // 분 - seconds += parts[2]; // 초 - } else { - // MM:SS 형식 - seconds += parts[0] * 60; // 분 - seconds += parts[1]; // 초 - } - return seconds; -} diff --git a/apps/functions/tsconfig.json b/apps/functions/tsconfig.json index de247a6..28f494b 100644 --- a/apps/functions/tsconfig.json +++ b/apps/functions/tsconfig.json @@ -10,9 +10,10 @@ "strict": true, "target": "es2017", "paths": { - "@/*": ["./src/*"] + "@/*": ["./src/*"], + "@lymo/schemas/*": ["../../packages/schemas/src/*"] } }, "compileOnSave": true, - "include": ["src"] + "include": ["**/*.ts", "**/*.tsx"] } diff --git a/eslint.config.js b/eslint.config.js index 83da456..7369712 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -60,6 +60,7 @@ export default defineConfig([ }, node: { extensions: [".js", ".jsx", ".ts", ".tsx"], + paths: ["."], }, }, }, diff --git a/firebase.json b/firebase.json index ba3d66e..e1dc36b 100644 --- a/firebase.json +++ b/firebase.json @@ -5,28 +5,34 @@ "codebase": "default", "ignore": [ "node_modules", + ".genkit", ".git", "firebase-debug.log", - "firebase-debug.*.log" + "firebase-debug.*.log", + "serviceAccount.json", + ".env" ], - "predeploy": [ - "node ./scripts/predeploy.js" - ], - "postdeploy": [ - "node ./scripts/postdeploy.js" - ] + "predeploy": ["npm --prefix \"$RESOURCE_DIR\" run build"] } ], + "firestore": { + "rules": "firestore.rules" + }, "emulators": { + "firestore": { + "port": 8080, + "host": "0.0.0.0" + }, "functions": { - "port": 5001 + "port": 5001, + "host": "0.0.0.0" }, "ui": { "enabled": true }, - "singleProjectMode": true, - "firestore": { - "port": 8080 - } + "singleProjectMode": true + }, + "react-native": { + "android_bypass_emulator_url_remap": true } } diff --git a/firestore.rules b/firestore.rules new file mode 100644 index 0000000..d929ffc --- /dev/null +++ b/firestore.rules @@ -0,0 +1,16 @@ +rules_version = '2'; +service cloud.firestore { + match /databases/{database}/documents { + match /storyRequests/{requestId} { + allow get, create: if true; + } + + match /stories/{storyId} { + allow read: if true; + } + + match /tracks/{trackId} { + allow read: if true; + } + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0f6c80d..549dd94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "lymo", "version": "1.0.0", + "hasInstallScript": true, "workspaces": [ "packages/*", "apps/*" @@ -14,18 +15,19 @@ "devDependencies": { "@typescript-eslint/eslint-plugin": "^8.46.3", "@typescript-eslint/parser": "^8.46.3", + "concurrently": "^9.2.1", "eslint": "^9.25.0", "eslint-config-expo": "~10.0.0", "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.32.0", "eslint-plugin-react": "^7.37.5", + "patch-package": "^8.0.1", "typescript-eslint": "^8.44.1" } }, "apps/frontend": { "name": "@lymo/frontend", "version": "1.0.0", - "hasInstallScript": true, "dependencies": { "@algolia/client-search": "^5.37.0", "@expo/metro-runtime": "~6.1.2", @@ -34,14 +36,15 @@ "@lymo/schemas": "*", "@react-native-async-storage/async-storage": "2.2.0", "@react-native-community/slider": "5.0.1", - "@react-native-firebase/app": "^23.4.0", - "@react-native-firebase/firestore": "^23.4.0", + "@react-native-firebase/app": "^23.5.0", + "@react-native-firebase/firestore": "^23.5.0", + "@react-native-firebase/functions": "^23.5.0", "@react-navigation/bottom-tabs": "^7.4.0", "@react-navigation/elements": "^2.6.3", "@react-navigation/native": "^7.1.8", "@tanstack/react-query": "^5.90.2", "expo": "54.0.23", - "expo-constants": "~18.0.9", + "expo-constants": "^18.0.10", "expo-dev-client": "~6.0.13", "expo-font": "~14.0.8", "expo-haptics": "~15.0.7", @@ -54,11 +57,9 @@ "expo-symbols": "~1.0.7", "expo-system-ui": "~6.0.7", "expo-web-browser": "~15.0.8", - "genkit": "^1.22.0", "react": "19.1.0", "react-dom": "19.1.0", "react-error-boundary": "^6.0.0", - "react-icons": "^5.5.0", "react-native": "0.81.5", "react-native-gesture-handler": "~2.28.0", "react-native-image-colors": "^2.5.0", @@ -68,8 +69,7 @@ "react-native-svg": "15.12.1", "react-native-web": "~0.21.0", "react-native-worklets": "^0.5.1", - "react-simplikit": "^0.0.46", - "styled-components": "^6.1.19" + "react-simplikit": "^0.0.46" }, "devDependencies": { "@types/colorthief": "^2.6.0", @@ -100,18 +100,16 @@ "dependencies": { "@genkit-ai/google-genai": "^1.19.2", "@google-cloud/firestore": "^7.11.6", - "@lymo/schemas": "*", "axios": "^1.13.2", "fastest-levenshtein": "^1.0.16", "firebase-admin": "^13.5.0", - "firebase-functions": "^6.4.0", + "firebase-functions": "^7.0.0", "franc-min": "^6.2.0", - "genkit": "^1.19.2", + "genkit": "^1.24.0", "spotify-web-api-node": "^5.0.2", "syllable": "^5.0.1" }, "devDependencies": { - "@types/handlebars": "^4.0.40", "@types/spotify-web-api-node": "^5.0.11", "firebase-functions-test": "^3.1.0", "tsc-alias": "^1.8.16", @@ -224,7 +222,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -1724,7 +1721,8 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@colors/colors": { "version": "1.6.0", @@ -1736,6 +1734,18 @@ "node": ">=0.1.90" } }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", + "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@so-ric/colorspace": "^1.1.6", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@egjs/hammerjs": { "version": "2.0.17", "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", @@ -1782,27 +1792,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", - "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", - "license": "MIT", - "dependencies": { - "@emotion/memoize": "^0.8.1" - } - }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", - "license": "MIT" - }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", - "license": "MIT" - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", @@ -3643,7 +3632,6 @@ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.4.tgz", "integrity": "sha512-pUxEGmR+uu21OG/icAovjlu1fcYJzyVhhT0rsCrn+zi+nHtrS43Bp9KPn9KGa4NMspCUE++nkyiqziuIvJdwzw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@firebase/component": "0.7.0", "@firebase/logger": "0.5.0", @@ -3710,7 +3698,6 @@ "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.4.tgz", "integrity": "sha512-T7ifGmb+awJEcp542Ek4HtNfBxcBrnuk1ggUdqyFEdsXHdq7+wVlhvE6YukTL7NS8hIkEfL7TMAPx/uCNqt30g==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@firebase/app": "0.14.4", "@firebase/component": "0.7.0", @@ -3726,8 +3713,7 @@ "version": "0.9.3", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==", - "license": "Apache-2.0", - "peer": true + "license": "Apache-2.0" }, "node_modules/@firebase/auth": { "version": "1.11.0", @@ -4178,7 +4164,6 @@ "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.1.0" }, @@ -4193,12 +4178,12 @@ "license": "Apache-2.0" }, "node_modules/@genkit-ai/ai": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.22.0.tgz", - "integrity": "sha512-TDKO+zWyM5YI8zE4a0IlqlpgHuLB4B4islzgWDvzdQlbjtyJp0ayODAMFhS2ruQ6+a/UdXDySRrOX/RcqF4yjA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/ai/-/ai-1.24.0.tgz", + "integrity": "sha512-Rv2eZqvJA8awIfLKiZL+P1hlBPGFiBFk1r01hRk0BSp1HmpZmlzSx+MM+X2H54xMgRXBRAelzU6xUXXzN5U57Q==", "license": "Apache-2.0", "dependencies": { - "@genkit-ai/core": "1.22.0", + "@genkit-ai/core": "1.24.0", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.11.19", "colorette": "^2.0.20", @@ -4211,9 +4196,9 @@ } }, "node_modules/@genkit-ai/ai/node_modules/@types/node": { - "version": "20.19.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.24.tgz", - "integrity": "sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==", + "version": "20.19.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", + "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -4257,9 +4242,9 @@ } }, "node_modules/@genkit-ai/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.22.0.tgz", - "integrity": "sha512-etVlpwJkPoy91xR6H5+S/AWZPJMeovb7N35+B90md1+6xWcodQF7WZ3chKcH31Xamlz+jTIvd3riiZGY9RFumg==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/core/-/core-1.24.0.tgz", + "integrity": "sha512-JGmwdcC066OpbwShXeOOwvinj9b4yA0BKfKjPrVqqbWt9hvu81I60UNNiZC5y8dx+TvEhdEPUAXRvoOup2vC0w==", "license": "Apache-2.0", "dependencies": { "@opentelemetry/api": "^1.9.0", @@ -4302,761 +4287,482 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@genkit-ai/core/node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } + "node_modules/@genkit-ai/core/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, - "node_modules/@genkit-ai/core/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", + "node_modules/@genkit-ai/firebase": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/firebase/-/firebase-1.24.0.tgz", + "integrity": "sha512-6DZ612qNV4OUsAa0L40gYx0rIzcANAjv3u9R08wGK/twdOvANJuMOUWBRTIVPA0IZL2WiHLcm6Ss+GOdZOdvpg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "safe-buffer": "5.2.1" + "@genkit-ai/google-cloud": "^1.24.0" }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@genkit-ai/core/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "peerDependencies": { + "@google-cloud/firestore": "^7.11.0", + "firebase": ">=11.5.0", + "firebase-admin": ">=12.2", + "genkit": "^1.24.0" + }, + "peerDependenciesMeta": { + "firebase": { + "optional": true + } } }, - "node_modules/@genkit-ai/core/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/@genkit-ai/core/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", + "node_modules/@genkit-ai/google-cloud": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/google-cloud/-/google-cloud-1.24.0.tgz", + "integrity": "sha512-SrNCuo7UC1c7BRRk4F6IRAM9ZSBbpLUUWgpP9xUUQ3sozVzPwWwI5Eps32WCa52ljrbhSiQQRi4sRm36glDBiA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "ms": "2.0.0" + "@google-cloud/logging-winston": "^6.0.0", + "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.19.0", + "@google-cloud/opentelemetry-cloud-trace-exporter": "^2.4.1", + "@google-cloud/opentelemetry-resource-util": "^2.4.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/auto-instrumentations-node": "^0.49.1", + "@opentelemetry/core": "~1.25.0", + "@opentelemetry/instrumentation": "^0.52.0", + "@opentelemetry/instrumentation-pino": "^0.41.0", + "@opentelemetry/instrumentation-winston": "^0.39.0", + "@opentelemetry/resources": "~1.25.0", + "@opentelemetry/sdk-metrics": "~1.25.0", + "@opentelemetry/sdk-node": "^0.52.0", + "@opentelemetry/sdk-trace-base": "~1.25.0", + "google-auth-library": "^9.6.3", + "node-fetch": "^3.3.2", + "winston": "^3.12.0" + }, + "peerDependencies": { + "genkit": "^1.24.0" } }, - "node_modules/@genkit-ai/core/node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "node_modules/@genkit-ai/google-cloud/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "license": "MIT", + "optional": true, "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" }, "engines": { - "node": ">= 0.10.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://opencollective.com/node-fetch" } }, - "node_modules/@genkit-ai/core/node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", + "node_modules/@genkit-ai/google-genai": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@genkit-ai/google-genai/-/google-genai-1.22.0.tgz", + "integrity": "sha512-Bdzjy15zWBt5GGRmzjSh2jp73fyFt3X0la9jvECmxzn1zjVl68/OU3WJAoAD+z3N4F258NmXzsMh6t5QA9INFQ==", + "license": "Apache-2.0", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "google-auth-library": "^9.14.2" + }, + "peerDependencies": { + "genkit": "^1.22.0" + } + }, + "node_modules/@google-cloud/common": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-5.0.2.tgz", + "integrity": "sha512-V7bmBKYQyu0eVG2BFejuUjlBt+zrya6vtsKdY+JxMM/dNntPF41vZ9+LhOshEUH01zOHEqBSvI7Dad7ZS6aUeA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "^4.0.0", + "arrify": "^2.0.1", + "duplexify": "^4.1.1", + "extend": "^3.0.2", + "google-auth-library": "^9.0.0", + "html-entities": "^2.5.2", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=14.0.0" } }, - "node_modules/@genkit-ai/core/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", + "node_modules/@google-cloud/firestore": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.6.tgz", + "integrity": "sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0", + "fast-deep-equal": "^3.1.1", + "functional-red-black-tree": "^1.0.1", + "google-gax": "^4.3.3", + "protobufjs": "^7.2.6" + }, "engines": { - "node": ">= 0.6" + "node": ">=14.0.0" } }, - "node_modules/@genkit-ai/core/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", + "node_modules/@google-cloud/logging": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.2.1.tgz", + "integrity": "sha512-2h9HBJG3OAsvzXmb81qXmaTPfXYU7KJTQUxunoOKFGnY293YQ/eCkW1Y5mHLocwpEqeqQYT/Qvl6Tk+Q7PfStw==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "@google-cloud/common": "^5.0.0", + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "4.0.0", + "@opentelemetry/api": "^1.7.0", + "arrify": "^2.0.1", + "dot-prop": "^6.0.0", + "eventid": "^2.0.0", + "extend": "^3.0.2", + "gcp-metadata": "^6.0.0", + "google-auth-library": "^9.0.0", + "google-gax": "^4.0.3", + "on-finished": "^2.3.0", + "pumpify": "^2.0.1", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=14.0.0" } }, - "node_modules/@genkit-ai/core/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/@genkit-ai/core/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", + "node_modules/@google-cloud/logging-winston": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/logging-winston/-/logging-winston-6.0.1.tgz", + "integrity": "sha512-tgA/qe/aGZITMrJ/5Tuykv234pLb/Qo6iDZ8SDkjbsiIy69mLQmbphrUd/IqnE17BSDfrwDUckvWdghiy8b+Qg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@google-cloud/logging": "^11.0.0", + "google-auth-library": "^9.0.0", + "lodash.mapvalues": "^4.6.0", + "winston-transport": "^4.3.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=14.0.0" + }, + "peerDependencies": { + "winston": ">=3.2.1" } }, - "node_modules/@genkit-ai/core/node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "node_modules/@google-cloud/logging/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/@genkit-ai/core/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" + "node_modules/@google-cloud/opentelemetry-cloud-monitoring-exporter": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@google-cloud/opentelemetry-cloud-monitoring-exporter/-/opentelemetry-cloud-monitoring-exporter-0.19.0.tgz", + "integrity": "sha512-5SOPXwC6RET4ZvXxw5D97dp8fWpqWEunHrzrUUGXhG4UAeedQe1KvYV8CK+fnaAbN2l2ha6QDYspT6z40TVY0g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@google-cloud/opentelemetry-resource-util": "^2.3.0", + "@google-cloud/precise-date": "^4.0.0", + "google-auth-library": "^9.0.0", + "googleapis": "^137.0.0" }, "engines": { - "node": ">=4" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0", + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/resources": "^1.0.0", + "@opentelemetry/sdk-metrics": "^1.0.0" } }, - "node_modules/@genkit-ai/core/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/@genkit-ai/core/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/@genkit-ai/core/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", + "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@google-cloud/opentelemetry-cloud-trace-exporter/-/opentelemetry-cloud-trace-exporter-2.4.1.tgz", + "integrity": "sha512-Dq2IyAyA9PCjbjLOn86i2byjkYPC59b5ic8k/L4q5bBWH0Jro8lzMs8C0G5pJfqh2druj8HF+oAIAlSdWQ+Z9Q==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "side-channel": "^1.0.6" + "@google-cloud/opentelemetry-resource-util": "^2.4.0", + "@grpc/grpc-js": "^1.1.8", + "@grpc/proto-loader": "^0.7.0", + "google-auth-library": "^9.0.0" }, "engines": { - "node": ">=0.6" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@opentelemetry/api": "^1.0.0", + "@opentelemetry/core": "^1.0.0", + "@opentelemetry/resources": "^1.0.0", + "@opentelemetry/sdk-trace-base": "^1.0.0" } }, - "node_modules/@genkit-ai/core/node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", + "node_modules/@google-cloud/opentelemetry-resource-util": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@google-cloud/opentelemetry-resource-util/-/opentelemetry-resource-util-2.4.0.tgz", + "integrity": "sha512-/7ujlMoKtDtrbQlJihCjQnm31n2s2RTlvJqcSbt2jV3OkCzPAdo3u31Q13HNugqtIRUSk7bUoLx6AzhURkhW4w==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "@opentelemetry/semantic-conventions": "^1.22.0", + "gcp-metadata": "^6.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/resources": "^1.0.0" } }, - "node_modules/@genkit-ai/core/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", + "node_modules/@google-cloud/paginator": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", + "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "arrify": "^2.0.0", + "extend": "^3.0.2" }, "engines": { - "node": ">= 0.8.0" + "node": ">=14.0.0" } }, - "node_modules/@genkit-ai/core/node_modules/send/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", + "node_modules/@google-cloud/precise-date": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-4.0.0.tgz", + "integrity": "sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==", + "license": "Apache-2.0", + "optional": true, "engines": { - "node": ">= 0.8" + "node": ">=14.0.0" } }, - "node_modules/@genkit-ai/core/node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@genkit-ai/core/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "license": "Apache-2.0", + "optional": true, "engines": { - "node": ">= 0.8" + "node": ">=14" } }, - "node_modules/@genkit-ai/core/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", + "node_modules/@google-cloud/storage": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.17.3.tgz", + "integrity": "sha512-gOnCAbFgAYKRozywLsxagdevTF7Gm+2Ncz5u5CQAuOv/2VCa0rdGJWvJFDOftPx1tc+q8TXiC2pEJfFKu+yeMQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "<4.1.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "duplexify": "^4.1.3", + "fast-xml-parser": "^4.4.1", + "gaxios": "^6.0.2", + "google-auth-library": "^9.6.3", + "html-entities": "^2.5.2", + "mime": "^3.0.0", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0", + "uuid": "^8.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=14" } }, - "node_modules/@genkit-ai/firebase": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/firebase/-/firebase-1.22.0.tgz", - "integrity": "sha512-iTOVma8be8cOFzO9yaNuzBIICgFAP+N1cuB5T8K5LE5ahsSIG7sZWUE5FwMKtEDFk9D343kgLuvW9nxLkV7IzA==", - "license": "Apache-2.0", + "node_modules/@google-cloud/storage/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@gorhom/bottom-sheet": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@gorhom/bottom-sheet/-/bottom-sheet-5.2.6.tgz", + "integrity": "sha512-vmruJxdiUGDg+ZYcDmS30XDhq/h/+QkINOI5LY/uGjx8cPGwgJW0H6AB902gNTKtccbiKe/rr94EwdmIEz+LAQ==", + "license": "MIT", "dependencies": { - "@genkit-ai/google-cloud": "^1.22.0" + "@gorhom/portal": "1.0.14", + "invariant": "^2.2.4" }, "peerDependencies": { - "@google-cloud/firestore": "^7.11.0", - "firebase": ">=11.5.0", - "firebase-admin": ">=12.2", - "genkit": "^1.22.0" + "@types/react": "*", + "@types/react-native": "*", + "react": "*", + "react-native": "*", + "react-native-gesture-handler": ">=2.16.1", + "react-native-reanimated": ">=3.16.0 || >=4.0.0-" }, "peerDependenciesMeta": { - "firebase": { + "@types/react": { + "optional": true + }, + "@types/react-native": { "optional": true } } }, - "node_modules/@genkit-ai/google-cloud": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/google-cloud/-/google-cloud-1.22.0.tgz", - "integrity": "sha512-PVt7oLu3VARQ4u/R4VvG/q2lsEdTke9jxQI8sg1jxHoKV03fNUwKAyNd59ZT4igrQIUCqdJD4tH3Kzh4yd4QTw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@google-cloud/logging-winston": "^6.0.0", - "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.19.0", - "@google-cloud/opentelemetry-cloud-trace-exporter": "^2.4.1", - "@google-cloud/opentelemetry-resource-util": "^2.4.0", - "@opentelemetry/api": "^1.9.0", - "@opentelemetry/auto-instrumentations-node": "^0.49.1", - "@opentelemetry/core": "~1.25.0", - "@opentelemetry/instrumentation": "^0.52.0", - "@opentelemetry/instrumentation-pino": "^0.41.0", - "@opentelemetry/instrumentation-winston": "^0.39.0", - "@opentelemetry/resources": "~1.25.0", - "@opentelemetry/sdk-metrics": "~1.25.0", - "@opentelemetry/sdk-node": "^0.52.0", - "@opentelemetry/sdk-trace-base": "~1.25.0", - "google-auth-library": "^9.6.3", - "node-fetch": "^3.3.2", - "winston": "^3.12.0" - }, - "peerDependencies": { - "genkit": "^1.22.0" - } - }, - "node_modules/@genkit-ai/google-cloud/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "node_modules/@gorhom/portal": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@gorhom/portal/-/portal-1.0.14.tgz", + "integrity": "sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==", "license": "MIT", - "optional": true, - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/@genkit-ai/google-genai": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@genkit-ai/google-genai/-/google-genai-1.22.0.tgz", - "integrity": "sha512-Bdzjy15zWBt5GGRmzjSh2jp73fyFt3X0la9jvECmxzn1zjVl68/OU3WJAoAD+z3N4F258NmXzsMh6t5QA9INFQ==", - "license": "Apache-2.0", "dependencies": { - "google-auth-library": "^9.14.2" + "nanoid": "^3.3.1" }, "peerDependencies": { - "genkit": "^1.22.0" + "react": "*", + "react-native": "*" } }, - "node_modules/@google-cloud/common": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-5.0.2.tgz", - "integrity": "sha512-V7bmBKYQyu0eVG2BFejuUjlBt+zrya6vtsKdY+JxMM/dNntPF41vZ9+LhOshEUH01zOHEqBSvI7Dad7ZS6aUeA==", + "node_modules/@grpc/grpc-js": { + "version": "1.9.15", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", + "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", "license": "Apache-2.0", - "optional": true, "dependencies": { - "@google-cloud/projectify": "^4.0.0", - "@google-cloud/promisify": "^4.0.0", - "arrify": "^2.0.1", - "duplexify": "^4.1.1", - "extend": "^3.0.2", - "google-auth-library": "^9.0.0", - "html-entities": "^2.5.2", - "retry-request": "^7.0.0", - "teeny-request": "^9.0.0" + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" }, "engines": { - "node": ">=14.0.0" + "node": "^8.13.0 || >=10.10.0" } }, - "node_modules/@google-cloud/firestore": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.6.tgz", - "integrity": "sha512-EW/O8ktzwLfyWBOsNuhRoMi8lrC3clHM5LVFhGvO1HCsLozCOOXRAlHrYBoE6HL42Sc8yYMuCb2XqcnJ4OOEpw==", + "node_modules/@grpc/proto-loader": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", + "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { - "@opentelemetry/api": "^1.3.0", - "fast-deep-equal": "^3.1.1", - "functional-red-black-tree": "^1.0.1", - "google-gax": "^4.3.3", - "protobufjs": "^7.2.6" + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" }, "engines": { - "node": ">=14.0.0" + "node": ">=6" } }, - "node_modules/@google-cloud/logging": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.2.1.tgz", - "integrity": "sha512-2h9HBJG3OAsvzXmb81qXmaTPfXYU7KJTQUxunoOKFGnY293YQ/eCkW1Y5mHLocwpEqeqQYT/Qvl6Tk+Q7PfStw==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@google-cloud/common": "^5.0.0", - "@google-cloud/paginator": "^5.0.0", - "@google-cloud/projectify": "^4.0.0", - "@google-cloud/promisify": "4.0.0", - "@opentelemetry/api": "^1.7.0", - "arrify": "^2.0.1", - "dot-prop": "^6.0.0", - "eventid": "^2.0.0", - "extend": "^3.0.2", - "gcp-metadata": "^6.0.0", - "google-auth-library": "^9.0.0", - "google-gax": "^4.0.3", - "on-finished": "^2.3.0", - "pumpify": "^2.0.1", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" - }, "engines": { - "node": ">=14.0.0" + "node": ">=18.18.0" } }, - "node_modules/@google-cloud/logging-winston": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@google-cloud/logging-winston/-/logging-winston-6.0.1.tgz", - "integrity": "sha512-tgA/qe/aGZITMrJ/5Tuykv234pLb/Qo6iDZ8SDkjbsiIy69mLQmbphrUd/IqnE17BSDfrwDUckvWdghiy8b+Qg==", + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, "license": "Apache-2.0", - "optional": true, "dependencies": { - "@google-cloud/logging": "^11.0.0", - "google-auth-library": "^9.0.0", - "lodash.mapvalues": "^4.6.0", - "winston-transport": "^4.3.0" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "winston": ">=3.2.1" - } - }, - "node_modules/@google-cloud/logging/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" + "node": ">=18.18.0" } }, - "node_modules/@google-cloud/opentelemetry-cloud-monitoring-exporter": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@google-cloud/opentelemetry-cloud-monitoring-exporter/-/opentelemetry-cloud-monitoring-exporter-0.19.0.tgz", - "integrity": "sha512-5SOPXwC6RET4ZvXxw5D97dp8fWpqWEunHrzrUUGXhG4UAeedQe1KvYV8CK+fnaAbN2l2ha6QDYspT6z40TVY0g==", + "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", - "optional": true, - "dependencies": { - "@google-cloud/opentelemetry-resource-util": "^2.3.0", - "@google-cloud/precise-date": "^4.0.0", - "google-auth-library": "^9.0.0", - "googleapis": "^137.0.0" - }, "engines": { - "node": ">=14" + "node": ">=12.22" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.0.0", - "@opentelemetry/sdk-metrics": "^1.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@google-cloud/opentelemetry-cloud-trace-exporter/-/opentelemetry-cloud-trace-exporter-2.4.1.tgz", - "integrity": "sha512-Dq2IyAyA9PCjbjLOn86i2byjkYPC59b5ic8k/L4q5bBWH0Jro8lzMs8C0G5pJfqh2druj8HF+oAIAlSdWQ+Z9Q==", + "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", - "optional": true, - "dependencies": { - "@google-cloud/opentelemetry-resource-util": "^2.4.0", - "@grpc/grpc-js": "^1.1.8", - "@grpc/proto-loader": "^0.7.0", - "google-auth-library": "^9.0.0" - }, "engines": { - "node": ">=14" + "node": ">=18.18" }, - "peerDependencies": { - "@opentelemetry/api": "^1.0.0", - "@opentelemetry/core": "^1.0.0", - "@opentelemetry/resources": "^1.0.0", - "@opentelemetry/sdk-trace-base": "^1.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@google-cloud/opentelemetry-resource-util": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@google-cloud/opentelemetry-resource-util/-/opentelemetry-resource-util-2.4.0.tgz", - "integrity": "sha512-/7ujlMoKtDtrbQlJihCjQnm31n2s2RTlvJqcSbt2jV3OkCzPAdo3u31Q13HNugqtIRUSk7bUoLx6AzhURkhW4w==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { - "@opentelemetry/semantic-conventions": "^1.22.0", - "gcp-metadata": "^6.0.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@opentelemetry/resources": "^1.0.0" + "node": ">=12" } }, - "node_modules/@google-cloud/paginator": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", - "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", - "license": "Apache-2.0", - "optional": true, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", "dependencies": { - "arrify": "^2.0.0", - "extend": "^3.0.2" + "minipass": "^7.0.4" }, "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/precise-date": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/precise-date/-/precise-date-4.0.0.tgz", - "integrity": "sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/projectify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", - "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@google-cloud/promisify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", - "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/storage": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.17.3.tgz", - "integrity": "sha512-gOnCAbFgAYKRozywLsxagdevTF7Gm+2Ncz5u5CQAuOv/2VCa0rdGJWvJFDOftPx1tc+q8TXiC2pEJfFKu+yeMQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@google-cloud/paginator": "^5.0.0", - "@google-cloud/projectify": "^4.0.0", - "@google-cloud/promisify": "<4.1.0", - "abort-controller": "^3.0.0", - "async-retry": "^1.3.3", - "duplexify": "^4.1.3", - "fast-xml-parser": "^4.4.1", - "gaxios": "^6.0.2", - "google-auth-library": "^9.6.3", - "html-entities": "^2.5.2", - "mime": "^3.0.0", - "p-limit": "^3.0.1", - "retry-request": "^7.0.0", - "teeny-request": "^9.0.0", - "uuid": "^8.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@google-cloud/storage/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@gorhom/bottom-sheet": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/@gorhom/bottom-sheet/-/bottom-sheet-5.2.6.tgz", - "integrity": "sha512-vmruJxdiUGDg+ZYcDmS30XDhq/h/+QkINOI5LY/uGjx8cPGwgJW0H6AB902gNTKtccbiKe/rr94EwdmIEz+LAQ==", - "license": "MIT", - "dependencies": { - "@gorhom/portal": "1.0.14", - "invariant": "^2.2.4" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-native": "*", - "react": "*", - "react-native": "*", - "react-native-gesture-handler": ">=2.16.1", - "react-native-reanimated": ">=3.16.0 || >=4.0.0-" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-native": { - "optional": true - } - } - }, - "node_modules/@gorhom/portal": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@gorhom/portal/-/portal-1.0.14.tgz", - "integrity": "sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==", - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.1" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, - "node_modules/@grpc/grpc-js": { - "version": "1.9.15", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", - "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" - }, - "engines": { - "node": "^8.13.0 || >=10.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", - "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.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/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" + "node": ">=18.0.0" } }, "node_modules/@isaacs/ttlcache": { @@ -5195,6 +4901,7 @@ "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/types": "30.2.0", "@types/node": "*", @@ -5213,6 +4920,7 @@ "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/console": "30.2.0", "@jest/pattern": "30.0.1", @@ -5261,6 +4969,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -5280,6 +4989,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -5290,6 +5000,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -5304,7 +5015,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@jest/create-cache-key-function": { "version": "29.7.0", @@ -5359,6 +5071,7 @@ "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } @@ -5369,6 +5082,7 @@ "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/fake-timers": "30.2.0", "@jest/types": "30.2.0", @@ -5385,6 +5099,7 @@ "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "expect": "30.2.0", "jest-snapshot": "30.2.0" @@ -5399,6 +5114,7 @@ "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/get-type": "30.1.0" }, @@ -5412,6 +5128,7 @@ "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/types": "30.2.0", "@sinonjs/fake-timers": "^13.0.0", @@ -5430,6 +5147,7 @@ "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } @@ -5440,6 +5158,7 @@ "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/environment": "30.2.0", "@jest/expect": "30.2.0", @@ -5456,6 +5175,7 @@ "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*", "jest-regex-util": "30.0.1" @@ -5470,6 +5190,7 @@ "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "30.2.0", @@ -5513,6 +5234,7 @@ "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@sinclair/typebox": "^0.34.0" }, @@ -5526,6 +5248,7 @@ "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/types": "30.2.0", "chalk": "^4.1.2", @@ -5542,6 +5265,7 @@ "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "callsites": "^3.1.0", @@ -5557,6 +5281,7 @@ "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/console": "30.2.0", "@jest/types": "30.2.0", @@ -5573,6 +5298,7 @@ "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/test-result": "30.2.0", "graceful-fs": "^4.2.11", @@ -5589,6 +5315,7 @@ "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.27.4", "@jest/types": "30.2.0", @@ -5616,6 +5343,7 @@ "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/pattern": "30.0.1", "@jest/schemas": "30.0.5", @@ -5663,7 +5391,6 @@ "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.12.tgz", "integrity": "sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q==", "license": "MIT", - "peer": true, "dependencies": { "@jimp/core": "^0.22.12" } @@ -5910,7 +5637,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -6006,7 +5732,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.25.1.tgz", "integrity": "sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/semantic-conventions": "1.25.1" }, @@ -7194,7 +6919,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.25.1.tgz", "integrity": "sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/core": "1.25.1", "@opentelemetry/semantic-conventions": "1.25.1" @@ -7237,7 +6961,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.25.1.tgz", "integrity": "sha512-9Mb7q5ioFL4E4dDrc4wC/A3NTHDat44v4I3p2pLPSxRvqUbDIQyMVr9uK+EU69+HWhlET1VaSrRzwdckWqY15Q==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/core": "1.25.1", "@opentelemetry/resources": "1.25.1", @@ -7291,7 +7014,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz", "integrity": "sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/core": "1.25.1", "@opentelemetry/resources": "1.25.1", @@ -7375,6 +7097,7 @@ "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -7638,7 +7361,6 @@ "resolved": "https://registry.npmjs.org/@react-native-firebase/app/-/app-23.5.0.tgz", "integrity": "sha512-TOlm6V6fbILwgFP37QZM9Y0nfAW6zqNGVIWlMlepQB6b/BzzFMrCl1FiyknqD5l7i1jgdFQrqX1WH6ZO4ePa/g==", "license": "Apache-2.0", - "peer": true, "dependencies": { "firebase": "12.4.0" }, @@ -7665,6 +7387,15 @@ "@react-native-firebase/app": "23.5.0" } }, + "node_modules/@react-native-firebase/functions": { + "version": "23.5.0", + "resolved": "https://registry.npmjs.org/@react-native-firebase/functions/-/functions-23.5.0.tgz", + "integrity": "sha512-aHdn6IBYkEyJ8k8syYolvYrOzzkPJDfIlH0FiF5LtNyU6XOlc5GxflLWa0MllYB9RUpVpisLv8XAWQee3y3Jsg==", + "license": "Apache-2.0", + "peerDependencies": { + "@react-native-firebase/app": "23.5.0" + } + }, "node_modules/@react-native/assets-registry": { "version": "0.81.5", "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz", @@ -7976,7 +7707,6 @@ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.19.tgz", "integrity": "sha512-fM7q8di4Q8sp2WUhiUWOe7bEDRyRhbzsKQOd5N2k+lHeCx3UncsRYuw4Q/KN0EovM3wWKqMMmhy/YWuEO04kgw==", "license": "MIT", - "peer": true, "dependencies": { "@react-navigation/core": "^7.13.0", "escape-string-regexp": "^4.0.0", @@ -8017,446 +7747,201 @@ "nanoid": "^3.3.11" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.1.tgz", - "integrity": "sha512-bxZtughE4VNVJlL1RdoSE545kc4JxL7op57KKoi59/gwuU5rV6jLWFXXc8jwgFoT6vtj+ZjO+Z2C5nrY0Cl6wA==", - "cpu": [ - "arm" - ], + "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", - "optional": true, - "os": [ - "android" - ] + "license": "MIT" }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.1.tgz", - "integrity": "sha512-44a1hreb02cAAfAKmZfXVercPFaDjqXCK+iKeVOlJ9ltvnO6QqsBHgKVPTu+MJHSLLeMEUbeG2qiDYgbFPU48g==", - "cpu": [ - "arm64" - ], + "node_modules/@sinclair/typebox": { + "version": "0.34.41", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", + "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "peer": true }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.1.tgz", - "integrity": "sha512-usmzIgD0rf1syoOZ2WZvy8YpXK5G1V3btm3QZddoGSa6mOgfXWkkv+642bfUUldomgrbiLQGrPryb7DXLovPWQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.1.tgz", - "integrity": "sha512-is3r/k4vig2Gt8mKtTlzzyaSQ+hd87kDxiN3uDSDwggJLUV56Umli6OoL+/YZa/KvtdrdyNfMKHzL/P4siOOmg==", - "cpu": [ - "x64" - ], + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@so-ric/colorspace": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", + "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", "license": "MIT", "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "color": "^5.0.2", + "text-hex": "1.0.x" + } }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.1.tgz", - "integrity": "sha512-QJ1ksgp/bDJkZB4daldVmHaEQkG4r8PUXitCOC2WRmRaSaHx5RwPoI3DHVfXKwDkB+Sk6auFI/+JHacTekPRSw==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@so-ric/colorspace/node_modules/color": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", "license": "MIT", "optional": true, - "os": [ - "freebsd" - ] + "dependencies": { + "color-convert": "^3.1.3", + "color-string": "^2.1.3" + }, + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.1.tgz", - "integrity": "sha512-J6ma5xgAzvqsnU6a0+jgGX/gvoGokqpkx6zY4cWizRrm0ffhHDpJKQgC8dtDb3+MqfZDIqs64REbfHDMzxLMqQ==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@so-ric/colorspace/node_modules/color-convert": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", "license": "MIT", "optional": true, - "os": [ - "freebsd" - ] + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=14.6" + } }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.1.tgz", - "integrity": "sha512-JzWRR41o2U3/KMNKRuZNsDUAcAVUYhsPuMlx5RUldw0E4lvSIXFUwejtYz1HJXohUmqs/M6BBJAUBzKXZVddbg==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@so-ric/colorspace/node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", "license": "MIT", "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">=12.20" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.1.tgz", - "integrity": "sha512-L8kRIrnfMrEoHLHtHn+4uYA52fiLDEDyezgxZtGUTiII/yb04Krq+vk3P2Try+Vya9LeCE9ZHU8CXD6J9EhzHQ==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@so-ric/colorspace/node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", "license": "MIT", "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.1.tgz", - "integrity": "sha512-ysAc0MFRV+WtQ8li8hi3EoFi7us6d1UzaS/+Dp7FYZfg3NdDljGMoVyiIp6Ucz7uhlYDBZ/zt6XI0YEZbUO11Q==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@tanstack/query-core": { + "version": "5.90.7", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.7.tgz", + "integrity": "sha512-6PN65csiuTNfBMXqQUxQhCNdtm1rV+9kC9YwWAIKcaxAauq3Wu7p18j3gQY3YIBJU70jT/wzCCZ2uqto/vQgiQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.1.tgz", - "integrity": "sha512-UV6l9MJpDbDZZ/fJvqNcvO1PcivGEf1AvKuTcHoLjVZVFeAMygnamCTDikCVMRnA+qJe+B3pSbgX2+lBMqgBhA==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/@tanstack/react-query": { + "version": "5.90.7", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.7.tgz", + "integrity": "sha512-wAHc/cgKzW7LZNFloThyHnV/AX9gTg3w5yAv0gvQHPZoCnepwqCMtzbuPbb2UvfvO32XZ46e8bPOYbfZhzVnnQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@tanstack/query-core": "5.90.7" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.1.tgz", - "integrity": "sha512-UDUtelEprkA85g95Q+nj3Xf0M4hHa4DiJ+3P3h4BuGliY4NReYYqwlc0Y8ICLjN4+uIgCEvaygYlpf0hUj90Yg==", - "cpu": [ - "loong64" - ], - "dev": true, + "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/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": ">= 10" + } }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.1.tgz", - "integrity": "sha512-vrRn+BYhEtNOte/zbc2wAUQReJXxEx2URfTol6OEfY2zFEUK92pkFBSXRylDM7aHi+YqEPJt9/ABYzmcrS4SgQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "tslib": "^2.4.0" + } }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.1.tgz", - "integrity": "sha512-gto/1CxHyi4A7YqZZNznQYrVlPSaodOBPKM+6xcDSCMVZN/Fzb4K+AIkNz/1yAYz9h3Ng+e2fY9H6bgawVq17w==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/@types/aws-lambda": { + "version": "8.10.122", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.122.tgz", + "integrity": "sha512-vBkIh9AY22kVOCEKo5CJlyCgmSWvasC+SWUxL/x/vOwRobMpI/HG1xp/Ae3AqmSiZeLUbOhW0FCD3ZjqqUxmXw==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.1.tgz", - "integrity": "sha512-KZ6Vx7jAw3aLNjFR8eYVcQVdFa/cvBzDNRFM3z7XhNNunWjA03eUrEwJYPk0G8V7Gs08IThFKcAPS4WY/ybIrQ==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.1.tgz", - "integrity": "sha512-HvEixy2s/rWNgpwyKpXJcHmE7om1M89hxBTBi9Fs6zVuLU4gOrEMQNbNsN/tBVIMbLyysz/iwNiGtMOpLAOlvA==", - "cpu": [ - "s390x" - ], - "dev": true, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/types": "^7.0.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.1.tgz", - "integrity": "sha512-E/n8x2MSjAQgjj9IixO4UeEUeqXLtiA7pyoXCFYLuXpBA/t2hnbIdxHfA7kK9BFsYAoNU4st1rHYdldl8dTqGA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.1.tgz", - "integrity": "sha512-IhJ087PbLOQXCN6Ui/3FUkI9pWNZe/Z7rEIVOzMsOs1/HSAECCvSZ7PkIbkNqL/AZn6WbZvnoVZw/qwqYMo4/w==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.1.tgz", - "integrity": "sha512-0++oPNgLJHBblreu0SFM7b3mAsBJBTY0Ksrmu9N6ZVrPiTkRgda52mWR7TKhHAsUb9noCjFvAw9l6ZO1yzaVbA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.1.tgz", - "integrity": "sha512-VJXivz61c5uVdbmitLkDlbcTk9Or43YC2QVLRkqp86QoeFSqI81bNgjhttqhKNMKnQMWnecOCm7lZz4s+WLGpQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.1.tgz", - "integrity": "sha512-NmZPVTUOitCXUH6erJDzTQ/jotYw4CnkMDjCYRxNHVD9bNyfrGoIse684F9okwzKCV4AIHRbUkeTBc9F2OOH5Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.1.tgz", - "integrity": "sha512-2SNj7COIdAf6yliSpLdLG8BEsp5lgzRehgfkP0Av8zKfQFKku6JcvbobvHASPJu4f3BFxej5g+HuQPvqPhHvpQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.1.tgz", - "integrity": "sha512-rLarc1Ofcs3DHtgSzFO31pZsCh8g05R2azN1q3fF+H423Co87My0R+tazOEvYVKXSLh8C4LerMK41/K7wlklcg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "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/@sinclair/typebox": { - "version": "0.34.41", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", - "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/@tanstack/query-core": { - "version": "5.90.7", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.7.tgz", - "integrity": "sha512-6PN65csiuTNfBMXqQUxQhCNdtm1rV+9kC9YwWAIKcaxAauq3Wu7p18j3gQY3YIBJU70jT/wzCCZ2uqto/vQgiQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } - }, - "node_modules/@tanstack/react-query": { - "version": "5.90.7", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.7.tgz", - "integrity": "sha512-wAHc/cgKzW7LZNFloThyHnV/AX9gTg3w5yAv0gvQHPZoCnepwqCMtzbuPbb2UvfvO32XZ46e8bPOYbfZhzVnnQ==", - "license": "MIT", - "dependencies": { - "@tanstack/query-core": "5.90.7" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" - } - }, - "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/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/aws-lambda": { - "version": "8.10.122", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.122.tgz", - "integrity": "sha512-vBkIh9AY22kVOCEKo5CJlyCgmSWvasC+SWUxL/x/vOwRobMpI/HG1xp/Ae3AqmSiZeLUbOhW0FCD3ZjqqUxmXw==", - "license": "MIT", - "optional": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } + "dependencies": { + "@babel/types": "^7.28.2" + } }, "node_modules/@types/body-parser": { "version": "1.19.6", @@ -8555,13 +8040,6 @@ "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==", "license": "MIT" }, - "node_modules/@types/handlebars": { - "version": "4.0.40", - "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.40.tgz", - "integrity": "sha512-sGWNtsjNrLOdKha2RV1UeF8+UbQnPSG7qbe5wwbni0mw4h2gHXyPFUMOC+xwGirIiiydM/HSqjDO4rk6NFB18w==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/http-errors": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", @@ -8661,9 +8139,9 @@ } }, "node_modules/@types/node": { - "version": "24.10.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz", - "integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==", + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -8715,7 +8193,6 @@ "integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -8808,12 +8285,6 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "license": "MIT" }, - "node_modules/@types/stylis": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", - "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", - "license": "MIT" - }, "node_modules/@types/tedious": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", @@ -8898,7 +8369,6 @@ "integrity": "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.3", "@typescript-eslint/types": "8.46.3", @@ -9568,6 +9038,13 @@ "node": ">=10.0.0" } }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -9598,7 +9075,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -9987,6 +9463,13 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "license": "MIT" }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT", + "optional": true + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -10061,6 +9544,7 @@ "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/transform": "30.2.0", "@types/babel__core": "^7.20.5", @@ -10083,6 +9567,7 @@ "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "workspaces": [ "test/babel-8" ], @@ -10103,6 +9588,7 @@ "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/babel__core": "^7.20.5" }, @@ -10275,6 +9761,7 @@ "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "babel-plugin-jest-hoist": "30.2.0", "babel-preset-current-node-syntax": "^1.2.0" @@ -10387,6 +9874,60 @@ "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", "license": "MIT" }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/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/body-parser/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/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -10455,7 +9996,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", @@ -10529,22 +10069,6 @@ "node": ">= 0.10.x" } }, - "node_modules/bundle-require": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", - "integrity": "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "load-tsconfig": "^0.2.3" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "esbuild": ">=0.18" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -10554,16 +10078,6 @@ "node": ">= 0.8" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -10631,15 +10145,6 @@ "node": ">=6" } }, - "node_modules/camelize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", - "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001754", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", @@ -10682,26 +10187,11 @@ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" } }, - "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": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", @@ -10881,6 +10371,7 @@ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -10901,7 +10392,8 @@ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/color": { "version": "4.2.3", @@ -11040,12 +10532,46 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "node_modules/concurrently": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", + "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "chalk": "4.1.2", + "rxjs": "7.8.2", + "shell-quote": "1.8.3", + "supports-color": "8.1.1", + "tree-kill": "1.2.2", + "yargs": "17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } }, "node_modules/connect": { "version": "3.7.0", @@ -11077,14 +10603,16 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "dev": true, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, "engines": { - "node": "^14.18.0 || >=16.10.0" + "node": ">= 0.6" } }, "node_modules/content-type": { @@ -11102,6 +10630,21 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, "node_modules/cookiejar": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", @@ -11166,15 +10709,6 @@ "node": ">=8" } }, - "node_modules/css-color-keywords": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", - "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", - "license": "ISC", - "engines": { - "node": ">=4" - } - }, "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", @@ -11200,17 +10734,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/css-to-react-native": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", - "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", - "license": "MIT", - "dependencies": { - "camelize": "^1.0.0", - "css-color-keywords": "^1.0.0", - "postcss-value-parser": "^4.0.2" - } - }, "node_modules/css-tree": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", @@ -11224,15 +10747,6 @@ "node": ">=8.0.0" } }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/css-what": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", @@ -11249,6 +10763,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true, "license": "MIT" }, "node_modules/data-uri-to-buffer": { @@ -11346,6 +10861,7 @@ "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", "dev": true, "license": "MIT", + "peer": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, @@ -11480,6 +10996,7 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -11683,6 +11200,7 @@ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -11696,6 +11214,13 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT", + "optional": true + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -11750,6 +11275,7 @@ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -11943,7 +11469,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -12012,7 +11537,6 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -12282,7 +11806,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -12548,6 +12071,7 @@ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -12571,7 +12095,8 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/exif-parser": { "version": "0.1.12", @@ -12584,6 +12109,7 @@ "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.8.0" } @@ -12594,6 +12120,7 @@ "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/expect-utils": "30.2.0", "@jest/get-type": "30.1.0", @@ -12611,7 +12138,6 @@ "resolved": "https://registry.npmjs.org/expo/-/expo-54.0.23.tgz", "integrity": "sha512-b4uQoiRwQ6nwqsT2709RS15CWYNGF3eJtyr1KyLw9WuMAK7u4jjofkhRiO0+3o1C2NbV+WooyYTOZGubQQMBaQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "54.0.16", @@ -12679,7 +12205,6 @@ "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.10.tgz", "integrity": "sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw==", "license": "MIT", - "peer": true, "dependencies": { "@expo/config": "~12.0.10", "@expo/env": "~2.0.7" @@ -12754,7 +12279,6 @@ "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.9.tgz", "integrity": "sha512-xCoQbR/36qqB6tew/LQ6GWICpaBmHLhg/Loix5Rku/0ZtNaXMJv08M9o1AcrdiGTn/Xf/BnLu6DgS45cWQEHZg==", "license": "MIT", - "peer": true, "dependencies": { "fontfaceobserver": "^2.1.0" }, @@ -12822,7 +12346,6 @@ "resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-8.0.9.tgz", "integrity": "sha512-a0UHhlVyfwIbn8b1PSFPoFiIDJeps2iEq109hVH3CHd0CMKuRxFfNio9Axe2BjXhiJCYWR4OV1iIyzY/GjiVkQ==", "license": "MIT", - "peer": true, "dependencies": { "expo-constants": "~18.0.10", "invariant": "^2.2.4" @@ -13237,6 +12760,145 @@ "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", "license": "Apache-2.0" }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/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/express/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/express/node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/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/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/express/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express/node_modules/send/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/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -13572,8 +13234,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/firebase": { - "version": "12.4.0", + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, + "node_modules/firebase": { + "version": "12.4.0", "resolved": "https://registry.npmjs.org/firebase/-/firebase-12.4.0.tgz", "integrity": "sha512-/chNgDQ6ppPPGOQO4jctxOa/5JeQxuhaxA7Y90K0I+n/wPfoO8mRveedhVUdo7ExLcWUivnnow/ouSLYSI5Icw==", "license": "Apache-2.0", @@ -13613,7 +13285,6 @@ "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.6.0.tgz", "integrity": "sha512-GdPA/t0+Cq8p1JnjFRBmxRxAGvF/kl2yfdhALl38PrRp325YxyQ5aNaHui0XmaKcKiGRFIJ/EgBNWFoDP0onjw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@fastify/busboy": "^3.0.0", "@firebase/database-compat": "^2.0.0", @@ -13651,9 +13322,9 @@ "license": "MIT" }, "node_modules/firebase-functions": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-6.6.0.tgz", - "integrity": "sha512-wwfo6JF+N7HUExVs5gUFgkgVGHDEog9O+qtouh7IuJWk8TBQ+KwXEgRiXbatSj7EbTu3/yYnHuzh3XExbfF6wQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/firebase-functions/-/firebase-functions-7.0.0.tgz", + "integrity": "sha512-IPedw7JJ4Ok7t1Lg75RDCQkLtUhs5V1I/WzZK25iGjK9Ej7U5EWFBchiLX0uhuNlRMKixUFuiDAGj2A5ryg2bw==", "license": "MIT", "dependencies": { "@types/cors": "^2.8.5", @@ -13666,7 +13337,7 @@ "firebase-functions": "lib/bin/firebase-functions.js" }, "engines": { - "node": ">=14.10.0" + "node": ">=18.0.0" }, "peerDependencies": { "firebase-admin": "^11.10.0 || ^12.0.0 || ^13.0.0" @@ -13692,442 +13363,189 @@ "jest": ">=28.0.0" } }, - "node_modules/firebase-functions/node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "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": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=16" } }, - "node_modules/firebase-functions/node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "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/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } + "optional": true }, - "node_modules/firebase-functions/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/firebase-functions/node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "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/firebase-functions/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/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": { - "ms": "2.0.0" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/firebase-functions/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/firebase-functions/node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "license": "MIT", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 0.10.0" + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/firebase-functions/node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.8" + "node": ">= 6" } }, - "node_modules/firebase-functions/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, "engines": { - "node": ">= 0.6" + "node": ">=12.20.0" } }, - "node_modules/firebase-functions/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" } }, - "node_modules/firebase-functions/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/firebase-functions/node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "node_modules/franc-min": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/franc-min/-/franc-min-6.2.0.tgz", + "integrity": "sha512-1uDIEUSlUZgvJa2AKYR/dmJC66v/PvGQ9mWfI9nOr/kPpMFyvswK0gPXOwpYJYiYD008PpHLkGfG58SPjQJFxw==", "license": "MIT", + "dependencies": { + "trigram-utils": "^2.0.0" + }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/firebase-functions/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "node_modules/freeport-async": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz", + "integrity": "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==", "license": "MIT", - "bin": { - "mime": "cli.js" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/firebase-functions/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" + "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/firebase-functions/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", "dependencies": { - "side-channel": "^1.0.6" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/firebase-functions/node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/firebase-functions/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/firebase-functions/node_modules/send/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/firebase-functions/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/firebase-functions/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fix-dts-default-cjs-exports": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fix-dts-default-cjs-exports/-/fix-dts-default-cjs-exports-1.0.1.tgz", - "integrity": "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "magic-string": "^0.30.17", - "mlly": "^1.7.4", - "rollup": "^4.34.8" - } - }, - "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": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "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/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "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": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "license": "MIT", - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/franc-min": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/franc-min/-/franc-min-6.2.0.tgz", - "integrity": "sha512-1uDIEUSlUZgvJa2AKYR/dmJC66v/PvGQ9mWfI9nOr/kPpMFyvswK0gPXOwpYJYiYD008PpHLkGfG58SPjQJFxw==", - "license": "MIT", - "dependencies": { - "trigram-utils": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/freeport-async": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/freeport-async/-/freeport-async-2.0.0.tgz", - "integrity": "sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ==", - "license": "MIT", - "engines": { - "node": ">=8" + "node": ">=12" } }, "node_modules/fs.realpath": { @@ -14250,14 +13668,13 @@ } }, "node_modules/genkit": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.22.0.tgz", - "integrity": "sha512-GoVVO3EnNHrjkMkUPRvgx1MjBHKvOlZAu/ffMIJgLFxrH7rrUbvfHXE6Nk7uh5BNvET7+DApyhbhqz9G8sy+mQ==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/genkit/-/genkit-1.24.0.tgz", + "integrity": "sha512-9BjPrLULfWdzauibKkbZcCf2LVu0mW2EW6EXHK/cTber6QdiP/guA5mXahaaDWBo+qdIKpInXAYDEzcRUmCVSA==", "license": "Apache-2.0", - "peer": true, "dependencies": { - "@genkit-ai/ai": "1.22.0", - "@genkit-ai/core": "1.22.0", + "@genkit-ai/ai": "1.24.0", + "@genkit-ai/core": "1.24.0", "uuid": "^10.0.0" } }, @@ -14365,6 +13782,7 @@ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -14740,15 +14158,6 @@ "uglify-js": "^3.1.4" } }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -14920,7 +14329,8 @@ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/http-errors": { "version": "2.0.0", @@ -14938,15 +14348,6 @@ "node": ">= 0.8" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/http-parser-js": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", @@ -14998,6 +14399,7 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=10.17.0" } @@ -15008,9 +14410,21 @@ "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", "license": "BSD-3-Clause" }, - "node_modules/idb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", "license": "ISC" }, @@ -15108,6 +14522,7 @@ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -15219,7 +14634,8 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/is-async-function": { "version": "2.1.1", @@ -15416,6 +14832,7 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -15731,6 +15148,7 @@ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "dependencies": { "@babel/core": "^7.23.9", "@babel/parser": "^7.23.9", @@ -15748,6 +15166,7 @@ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", @@ -15763,6 +15182,7 @@ "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", @@ -15778,6 +15198,7 @@ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -15878,6 +15299,7 @@ "integrity": "sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "execa": "^5.1.1", "jest-util": "30.2.0", @@ -15893,6 +15315,7 @@ "integrity": "sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/environment": "30.2.0", "@jest/expect": "30.2.0", @@ -15925,6 +15348,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -15938,6 +15362,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -15952,7 +15377,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-cli": { "version": "30.2.0", @@ -15960,6 +15386,7 @@ "integrity": "sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "30.2.0", "@jest/test-result": "30.2.0", @@ -15993,6 +15420,7 @@ "integrity": "sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.27.4", "@jest/get-type": "30.1.0", @@ -16045,6 +15473,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16064,6 +15493,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -16074,6 +15504,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -16088,7 +15519,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-diff": { "version": "30.2.0", @@ -16096,6 +15528,7 @@ "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/diff-sequences": "30.0.1", "@jest/get-type": "30.1.0", @@ -16112,6 +15545,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16125,6 +15559,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -16139,7 +15574,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-docblock": { "version": "30.2.0", @@ -16147,6 +15583,7 @@ "integrity": "sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "detect-newline": "^3.1.0" }, @@ -16160,6 +15597,7 @@ "integrity": "sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/get-type": "30.1.0", "@jest/types": "30.2.0", @@ -16177,6 +15615,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16190,6 +15629,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -16204,7 +15644,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-environment-node": { "version": "30.2.0", @@ -16212,6 +15653,7 @@ "integrity": "sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/environment": "30.2.0", "@jest/fake-timers": "30.2.0", @@ -16240,6 +15682,7 @@ "integrity": "sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/types": "30.2.0", "@types/node": "*", @@ -16265,6 +15708,7 @@ "integrity": "sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/get-type": "30.1.0", "pretty-format": "30.2.0" @@ -16279,6 +15723,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16292,6 +15737,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -16306,7 +15752,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-matcher-utils": { "version": "30.2.0", @@ -16314,6 +15761,7 @@ "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/get-type": "30.1.0", "chalk": "^4.1.2", @@ -16330,6 +15778,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16343,6 +15792,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -16357,7 +15807,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-message-util": { "version": "30.2.0", @@ -16365,6 +15816,7 @@ "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@jest/types": "30.2.0", @@ -16386,6 +15838,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16399,6 +15852,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -16413,7 +15867,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-mock": { "version": "30.2.0", @@ -16421,6 +15876,7 @@ "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/types": "30.2.0", "@types/node": "*", @@ -16436,6 +15892,7 @@ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6" }, @@ -16454,6 +15911,7 @@ "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } @@ -16464,6 +15922,7 @@ "integrity": "sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "chalk": "^4.1.2", "graceful-fs": "^4.2.11", @@ -16484,6 +15943,7 @@ "integrity": "sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "jest-regex-util": "30.0.1", "jest-snapshot": "30.2.0" @@ -16498,6 +15958,7 @@ "integrity": "sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/console": "30.2.0", "@jest/environment": "30.2.0", @@ -16526,22 +15987,13 @@ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" } }, - "node_modules/jest-runner/node_modules/source-map": { - "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" - } - }, "node_modules/jest-runner/node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -16553,6 +16005,7 @@ "integrity": "sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/environment": "30.2.0", "@jest/fake-timers": "30.2.0", @@ -16586,7 +16039,8 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.1.tgz", "integrity": "sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-runtime/node_modules/strip-bom": { "version": "4.0.0", @@ -16594,6 +16048,7 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -16604,6 +16059,7 @@ "integrity": "sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.27.4", "@babel/generator": "^7.27.5", @@ -16637,6 +16093,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16650,6 +16107,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -16664,7 +16122,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-util": { "version": "30.2.0", @@ -16672,6 +16131,7 @@ "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/types": "30.2.0", "@types/node": "*", @@ -16696,6 +16156,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -16706,6 +16167,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -16719,6 +16181,7 @@ "integrity": "sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/get-type": "30.1.0", "@jest/types": "30.2.0", @@ -16737,6 +16200,7 @@ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16750,6 +16214,7 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10" }, @@ -16763,6 +16228,7 @@ "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/schemas": "30.0.5", "ansi-styles": "^5.2.0", @@ -16777,7 +16243,8 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/jest-watcher": { "version": "30.2.0", @@ -16785,6 +16252,7 @@ "integrity": "sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/test-result": "30.2.0", "@jest/types": "30.2.0", @@ -16805,6 +16273,7 @@ "integrity": "sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*", "@ungap/structured-clone": "^1.3.0", @@ -16822,6 +16291,7 @@ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -16847,16 +16317,6 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/jpeg-js": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", @@ -16920,7 +16380,8 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/json-schema": { "version": "0.4.0", @@ -16935,6 +16396,26 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "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", @@ -16954,6 +16435,29 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "dev": true, + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -17061,6 +16565,16 @@ "json-buffer": "3.0.1" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -17070,6 +16584,13 @@ "node": ">=6" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT", + "optional": true + }, "node_modules/lan-network": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/lan-network/-/lan-network-0.1.7.tgz", @@ -17376,19 +16897,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, "node_modules/limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", @@ -17400,16 +16908,6 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, - "node_modules/load-tsconfig": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", - "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -17667,22 +17165,13 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "semver": "^7.5.3" }, @@ -17723,12 +17212,30 @@ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", "license": "CC0-1.0" }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "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-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-options": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", @@ -18424,6 +17931,7 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -18482,19 +17990,6 @@ "node": ">=10" } }, - "node_modules/mlly": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", - "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.15.0", - "pathe": "^2.0.3", - "pkg-types": "^1.3.1", - "ufo": "^1.6.1" - } - }, "node_modules/module-details-from-path": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", @@ -18667,9 +18162,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" @@ -18756,6 +18251,7 @@ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "path-key": "^3.0.0" }, @@ -18959,12 +18455,23 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "license": "MIT", + "optional": true, + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -19215,6 +18722,7 @@ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -19255,6 +18763,46 @@ "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", "license": "MIT" }, + "node_modules/patch-package": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", + "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^10.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.2.4", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -19310,6 +18858,12 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -19320,13 +18874,6 @@ "node": ">=8" } }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/peek-readable": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", @@ -19419,6 +18966,7 @@ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "find-up": "^4.0.0" }, @@ -19432,6 +18980,7 @@ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -19446,6 +18995,7 @@ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -19459,6 +19009,7 @@ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "p-try": "^2.0.0" }, @@ -19475,6 +19026,7 @@ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -19482,22 +19034,10 @@ "node": ">=8" } }, - "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", "dev": true, "license": "MIT", "dependencies": { @@ -19577,49 +19117,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-load-config": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", - "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.1.1" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", @@ -19903,7 +19400,8 @@ "url": "https://opencollective.com/fast-check" } ], - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/qrcode-terminal": { "version": "0.11.0", @@ -19995,6 +19493,21 @@ "node": ">= 0.6" } }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -20024,7 +19537,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -20065,7 +19577,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -20103,15 +19614,6 @@ "react": ">=17.0.0" } }, - "node_modules/react-icons": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", - "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", - "license": "MIT", - "peerDependencies": { - "react": "*" - } - }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -20123,7 +19625,6 @@ "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz", "integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==", "license": "MIT", - "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.81.5", @@ -20177,1179 +19678,707 @@ } }, "node_modules/react-native-gesture-handler": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz", - "integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==", - "license": "MIT", - "peer": true, - "dependencies": { - "@egjs/hammerjs": "^2.0.17", - "hoist-non-react-statics": "^3.3.0", - "invariant": "^2.2.4" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, - "node_modules/react-native-image-colors": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/react-native-image-colors/-/react-native-image-colors-2.5.0.tgz", - "integrity": "sha512-3zSDgNj5HaZ0PDWaXkc4BpWpZRM5N4gBsoPC7DBfM/+op69Yvwbc0S1T7CnxBWbvShtOvRE+b2BUBadVn+6z/g==", - "license": "MIT", - "dependencies": { - "node-vibrant": "^4.0.3" - }, - "peerDependencies": { - "expo": "*", - "react": "*", - "react-native": "*" - } - }, - "node_modules/react-native-is-edge-to-edge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz", - "integrity": "sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==", - "license": "MIT", - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, - "node_modules/react-native-reanimated": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.3.tgz", - "integrity": "sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==", - "license": "MIT", - "peer": true, - "dependencies": { - "react-native-is-edge-to-edge": "^1.2.1", - "semver": "7.7.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0", - "react": "*", - "react-native": "*", - "react-native-worklets": ">=0.5.0" - } - }, - "node_modules/react-native-reanimated/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native-safe-area-context": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", - "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", - "license": "MIT", - "peer": true, - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, - "node_modules/react-native-screens": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz", - "integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==", - "license": "MIT", - "peer": true, - "dependencies": { - "react-freeze": "^1.0.0", - "react-native-is-edge-to-edge": "^1.2.1", - "warn-once": "^0.1.0" - }, - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, - "node_modules/react-native-svg": { - "version": "15.12.1", - "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.12.1.tgz", - "integrity": "sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g==", - "license": "MIT", - "dependencies": { - "css-select": "^5.1.0", - "css-tree": "^1.1.3", - "warn-once": "0.1.1" - }, - "peerDependencies": { - "react": "*", - "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", - "integrity": "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/runtime": "^7.18.6", - "@react-native/normalize-colors": "^0.74.1", - "fbjs": "^3.0.4", - "inline-style-prefixer": "^7.0.1", - "memoize-one": "^6.0.0", - "nullthrows": "^1.1.1", - "postcss-value-parser": "^4.2.0", - "styleq": "^0.1.3" - }, - "peerDependencies": { - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - } - }, - "node_modules/react-native-web/node_modules/@react-native/normalize-colors": { - "version": "0.74.89", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.89.tgz", - "integrity": "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==", - "license": "MIT" - }, - "node_modules/react-native-web/node_modules/memoize-one": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", - "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", - "license": "MIT" - }, - "node_modules/react-native-worklets": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.5.1.tgz", - "integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/plugin-transform-arrow-functions": "^7.0.0-0", - "@babel/plugin-transform-class-properties": "^7.0.0-0", - "@babel/plugin-transform-classes": "^7.0.0-0", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", - "@babel/plugin-transform-optional-chaining": "^7.0.0-0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", - "@babel/plugin-transform-template-literals": "^7.0.0-0", - "@babel/plugin-transform-unicode-regex": "^7.0.0-0", - "@babel/preset-typescript": "^7.16.7", - "convert-source-map": "^2.0.0", - "semver": "7.7.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0", - "react": "*", - "react-native": "*" - } - }, - "node_modules/react-native-worklets/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native/node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/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/react-native/node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/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/react-native/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "license": "MIT" - }, - "node_modules/react-native/node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/react-native/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/react-native/node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/react-native/node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native/node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "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-native/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/react-native/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native/node_modules/istanbul-lib-instrument/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/react-native/node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/react-native/node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-native/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==", + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz", + "integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==", "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" + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "react": "*", + "react-native": "*" } }, - "node_modules/react-native/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==", + "node_modules/react-native-image-colors": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/react-native-image-colors/-/react-native-image-colors-2.5.0.tgz", + "integrity": "sha512-3zSDgNj5HaZ0PDWaXkc4BpWpZRM5N4gBsoPC7DBfM/+op69Yvwbc0S1T7CnxBWbvShtOvRE+b2BUBadVn+6z/g==", "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "node-vibrant": "^4.0.3" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" } }, - "node_modules/react-native/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/react-native-is-edge-to-edge": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz", + "integrity": "sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } }, - "node_modules/react-native/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==", + "node_modules/react-native-reanimated": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.3.tgz", + "integrity": "sha512-GP8wsi1u3nqvC1fMab/m8gfFwFyldawElCcUSBJQgfrXeLmsPPUOpDw44lbLeCpcwUuLa05WTVePdTEwCLTUZg==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" + "react-native-is-edge-to-edge": "^1.2.1", + "semver": "7.7.2" }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*", + "react-native-worklets": ">=0.5.0" } }, - "node_modules/react-native/node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "node_modules/react-native-reanimated/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/react-native/node_modules/ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "license": "MIT", - "dependencies": { - "async-limiter": "~1.0.0" + "node": ">=10" } }, - "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==", + "node_modules/react-native-safe-area-context": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", + "integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==", "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "react": "*", + "react-native": "*" } }, - "node_modules/react-remove-scroll": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", - "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", + "node_modules/react-native-screens": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz", + "integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==", "license": "MIT", "dependencies": { - "react-remove-scroll-bar": "^2.3.7", - "react-style-singleton": "^2.2.3", - "tslib": "^2.1.0", - "use-callback-ref": "^1.3.3", - "use-sidecar": "^1.1.3" - }, - "engines": { - "node": ">=10" + "react-freeze": "^1.0.0", + "react-native-is-edge-to-edge": "^1.2.1", + "warn-once": "^0.1.0" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "react": "*", + "react-native": "*" } }, - "node_modules/react-remove-scroll-bar": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", - "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "node_modules/react-native-svg": { + "version": "15.12.1", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.12.1.tgz", + "integrity": "sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g==", "license": "MIT", "dependencies": { - "react-style-singleton": "^2.2.2", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" + "css-select": "^5.1.0", + "css-tree": "^1.1.3", + "warn-once": "0.1.1" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "react": "*", + "react-native": "*" } }, - "node_modules/react-simplikit": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/react-simplikit/-/react-simplikit-0.0.46.tgz", - "integrity": "sha512-HQpROB8oN3uZHQVVjTnlh8qthpzOzCNrlVvQmxM8OicvjNO8TzdROZrHRZHPhrFGjUk0gNJZkPTslQ30cVNhmA==", + "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": "*" + "react-native": "*" } }, - "node_modules/react-style-singleton": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", - "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "node_modules/react-native-web": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz", + "integrity": "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg==", "license": "MIT", "dependencies": { - "get-nonce": "^1.0.0", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=10" + "@babel/runtime": "^7.18.6", + "@react-native/normalize-colors": "^0.74.1", + "fbjs": "^3.0.4", + "inline-style-prefixer": "^7.0.1", + "memoize-one": "^6.0.0", + "nullthrows": "^1.1.1", + "postcss-value-parser": "^4.2.0", + "styleq": "^0.1.3" }, "peerDependencies": { - "@types/react": "*", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" } }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/react-native-web/node_modules/@react-native/normalize-colors": { + "version": "0.74.89", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.74.89.tgz", + "integrity": "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==", + "license": "MIT" + }, + "node_modules/react-native-web/node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/react-native-worklets": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.5.1.tgz", + "integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==", "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "@babel/plugin-transform-arrow-functions": "^7.0.0-0", + "@babel/plugin-transform-class-properties": "^7.0.0-0", + "@babel/plugin-transform-classes": "^7.0.0-0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", + "@babel/plugin-transform-optional-chaining": "^7.0.0-0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", + "@babel/plugin-transform-template-literals": "^7.0.0-0", + "@babel/plugin-transform-unicode-regex": "^7.0.0-0", + "@babel/preset-typescript": "^7.16.7", + "convert-source-map": "^2.0.0", + "semver": "7.7.2" }, - "engines": { - "node": ">= 6" + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*" } }, - "node_modules/readable-web-to-node-stream": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", - "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", - "license": "MIT", - "dependencies": { - "readable-stream": "^4.7.0" + "node_modules/react-native-worklets/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=8" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "node": ">=10" } }, - "node_modules/readable-web-to-node-stream/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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/react-native/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/readable-web-to-node-stream/node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "node_modules/react-native/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">= 0.6.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "node_modules/react-native/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": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, + "node_modules/react-native/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "license": "MIT", - "engines": { - "node": ">= 14.18.0" + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.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, + "node_modules/react-native/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": { - "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" + "@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": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.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==", + "node_modules/react-native/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "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", + "node_modules/react-native/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "license": "BSD-3-Clause", "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" + "@sinonjs/commons": "^3.0.0" } }, - "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/react-native/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/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, + "node_modules/react-native/node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "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" + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "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", + "node_modules/react-native/node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "license": "BSD-3-Clause", "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" + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "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.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", - "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", - "license": "BSD-2-Clause", + "node_modules/react-native/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "license": "MIT", "dependencies": { - "jsesc": "~3.1.0" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, - "bin": { - "regjsparser": "bin/parser" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/react-native/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.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", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "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": ">=0.10.0" + "node": ">=18" } }, - "node_modules/require-in-the-middle": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", - "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", - "license": "MIT", + "node_modules/react-native/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { - "debug": "^4.3.5", - "module-details-from-path": "^1.0.3", - "resolve": "^1.22.8" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=8.6.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/requireg": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz", - "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==", + "node_modules/react-native/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "license": "BSD-3-Clause", "dependencies": { - "nested-error-stacks": "~2.0.1", - "rc": "~1.2.7", - "resolve": "~1.7.1" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">=8" } }, - "node_modules/requireg/node_modules/resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "node_modules/react-native/node_modules/istanbul-lib-instrument/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/react-native/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "license": "MIT", "dependencies": { - "path-parse": "^1.0.5" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "node_modules/react-native/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "license": "MIT", "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, + "node_modules/react-native/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "license": "MIT", "dependencies": { - "resolve-from": "^5.0.0" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/resolve-cwd/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==", - "dev": true, + "node_modules/react-native/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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, + "node_modules/react-native/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "license": "MIT", "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "node_modules/react-native/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": { - "global-dirs": "^0.1.1" + "@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": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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, + "node_modules/react-native/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", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + "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/resolve-workspace-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.0.tgz", - "integrity": "sha512-IsaBUZETJD5WsI11Wt8PKHwaIe45or6pwNc8yflvLJ4DWtImK9kuLoH5kUva/2Mmx/RdIyr4aONNSa2v9LTJsw==", - "license": "MIT" + "node_modules/react-native/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/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "node_modules/react-native/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/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", + "node_modules/react-native/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "license": "ISC", "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, "engines": { - "node": ">=4" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/restore-cursor/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==", + "node_modules/react-native/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "async-limiter": "~1.0.0" } }, - "node_modules/restore-cursor/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==", + "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", - "dependencies": { - "mimic-fn": "^1.0.0" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/restore-cursor/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/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/react-remove-scroll": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", + "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", "license": "MIT", - "optional": true, + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, "engines": { - "node": ">= 4" + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/retry-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", - "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", "license": "MIT", "dependencies": { - "@types/request": "^2.48.8", - "extend": "^3.0.2", - "teeny-request": "^9.0.0" + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" }, "engines": { - "node": ">=14" + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, + "node_modules/react-simplikit": { + "version": "0.0.46", + "resolved": "https://registry.npmjs.org/react-simplikit/-/react-simplikit-0.0.46.tgz", + "integrity": "sha512-HQpROB8oN3uZHQVVjTnlh8qthpzOzCNrlVvQmxM8OicvjNO8TzdROZrHRZHPhrFGjUk0gNJZkPTslQ30cVNhmA==", "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "peerDependencies": { + "react": "*" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "license": "ISC", + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", "dependencies": { - "glob": "^7.1.3" + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": ">=10" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 6" } }, - "node_modules/rollup": { - "version": "4.53.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.1.tgz", - "integrity": "sha512-n2I0V0lN3E9cxxMqBCT3opWOiQBzRN7UG60z/WDKqdX2zHUS/39lezBcsckZFsV6fUTSnfqI7kHf60jDAPGKug==", - "dev": true, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz", + "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" + "readable-stream": "^4.7.0" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": ">=8" }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.1", - "@rollup/rollup-android-arm64": "4.53.1", - "@rollup/rollup-darwin-arm64": "4.53.1", - "@rollup/rollup-darwin-x64": "4.53.1", - "@rollup/rollup-freebsd-arm64": "4.53.1", - "@rollup/rollup-freebsd-x64": "4.53.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.1", - "@rollup/rollup-linux-arm-musleabihf": "4.53.1", - "@rollup/rollup-linux-arm64-gnu": "4.53.1", - "@rollup/rollup-linux-arm64-musl": "4.53.1", - "@rollup/rollup-linux-loong64-gnu": "4.53.1", - "@rollup/rollup-linux-ppc64-gnu": "4.53.1", - "@rollup/rollup-linux-riscv64-gnu": "4.53.1", - "@rollup/rollup-linux-riscv64-musl": "4.53.1", - "@rollup/rollup-linux-s390x-gnu": "4.53.1", - "@rollup/rollup-linux-x64-gnu": "4.53.1", - "@rollup/rollup-linux-x64-musl": "4.53.1", - "@rollup/rollup-openharmony-arm64": "4.53.1", - "@rollup/rollup-win32-arm64-msvc": "4.53.1", - "@rollup/rollup-win32-ia32-msvc": "4.53.1", - "@rollup/rollup-win32-x64-gnu": "4.53.1", - "@rollup/rollup-win32-x64-msvc": "4.53.1", - "fsevents": "~2.3.2" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, + "node_modules/readable-web-to-node-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { "type": "github", @@ -21366,76 +20395,95 @@ ], "license": "MIT", "dependencies": { - "queue-microtask": "^1.2.2" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "node_modules/readable-web-to-node-stream/node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.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", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" + "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" + "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", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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/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/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, + "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": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" + "regenerate": "^1.4.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "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==", + "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/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-bound": "^1.0.2", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "is-regex": "^1.2.1" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -21444,383 +20492,382 @@ "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==", + "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", - "optional": true, + "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": ">=10" + "node": ">=4" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/sax": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", - "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", - "license": "BlueOak-1.0.0" - }, - "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "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/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz", - "integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==", - "license": "MIT", + "node_modules/regjsparser": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", + "license": "BSD-2-Clause", "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.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "jsesc": "~3.1.0" }, - "engines": { - "node": ">= 0.8.0" + "bin": { + "regjsparser": "bin/parser" } }, - "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==", + "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", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=0.10.0" } }, - "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/send/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", "license": "MIT", - "bin": { - "mime": "cli.js" + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" }, "engines": { - "node": ">=4" + "node": ">=8.6.0" } }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", + "node_modules/requireg": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/requireg/-/requireg-0.2.2.tgz", + "integrity": "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg==", + "dependencies": { + "nested-error-stacks": "~2.0.1", + "rc": "~1.2.7", + "resolve": "~1.7.1" + }, "engines": { - "node": ">= 0.8" + "node": ">= 4.0.0" } }, - "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==", + "node_modules/requireg/node_modules/resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "path-parse": "^1.0.5" } }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.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.8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/serve-static/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/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "ms": "2.0.0" + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/serve-static/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/serve-static/node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "node_modules/resolve-cwd/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==", + "dev": true, "license": "MIT", + "peer": true, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/serve-static/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "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", - "bin": { - "mime": "cli.js" - }, "engines": { "node": ">=4" } }, - "node_modules/serve-static/node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "global-dirs": "^0.1.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/serve-static/node_modules/send/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/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", - "engines": { - "node": ">= 0.8" + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/serve-static/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/resolve-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.0.tgz", + "integrity": "sha512-IsaBUZETJD5WsI11Wt8PKHwaIe45or6pwNc8yflvLJ4DWtImK9kuLoH5kUva/2Mmx/RdIyr4aONNSa2v9LTJsw==", + "license": "MIT" + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/server-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", - "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, + "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": { - "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" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">=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, + "node_modules/restore-cursor/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", - "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": ">=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, + "node_modules/restore-cursor/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": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" + "mimic-fn": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "node_modules/restore-cursor/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/sf-symbols-typescript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sf-symbols-typescript/-/sf-symbols-typescript-2.1.0.tgz", - "integrity": "sha512-ezT7gu/SHTPIOEEoG6TF+O0m5eewl0ZDAO4AtdBi5HjsrUI6JdCG17+Q8+aKp0heM06wZKApRCn5olNbs0Wb/A==", + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "license": "MIT", + "optional": true, "engines": { - "node": ">=10" + "node": ">= 4" } }, - "node_modules/shallowequal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "license": "MIT" - }, - "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==", + "node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" }, "engines": { - "node": ">=8" + "node": ">=14" } }, - "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==", + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/shimmer": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", - "license": "BSD-2-Clause" - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "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": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">= 0.4" + "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==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/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": { - "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" + "isarray": "^2.0.5" }, "engines": { "node": ">= 0.4" @@ -21829,17 +20876,16 @@ "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==", + "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", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -21848,384 +20894,313 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "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/simple-plist/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==", + "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", - "dependencies": { - "big-integer": "1.6.x" - }, + "optional": true, "engines": { - "node": ">= 5.10.0" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", - "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" + "node": ">=10" } }, - "node_modules/simple-swizzle/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/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/slugify": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", - "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "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==", - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/spotify-web-api-node": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/spotify-web-api-node/-/spotify-web-api-node-5.0.2.tgz", - "integrity": "sha512-r82dRWU9PMimHvHEzL0DwEJrzFk+SMCVfq249SLt3I7EFez7R+jeoKQd+M1//QcnjqlXPs2am4DFsGk8/GCsrA==", - "license": "MIT", - "dependencies": { - "superagent": "^6.1.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause" + "node_modules/sax": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", + "license": "BlueOak-1.0.0" }, - "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, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", "license": "MIT" }, - "node_modules/stable-hash-x": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", - "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", - "dev": true, - "license": "MIT", + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=12.0.0" + "node": ">=10" } }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "node_modules/send": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.1.tgz", + "integrity": "sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==", "license": "MIT", "dependencies": { - "escape-string-regexp": "^2.0.0" + "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.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">=10" + "node": ">= 0.8.0" } }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "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", - "engines": { - "node": ">=8" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "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/stacktrace-parser": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", - "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", + "node_modules/send/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", - "dependencies": { - "type-fest": "^0.7.1" + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/stacktrace-parser/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)", + "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": ">=8" + "node": ">=0.10.0" } }, - "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, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.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", - "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", - "license": "Unlicense", - "engines": { - "node": ">= 0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/stream-events": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", - "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "node_modules/serve-static/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": { - "stubs": "^3.0.0" + "ms": "2.0.0" } }, - "node_modules/stream-shift": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "node_modules/serve-static/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/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "node_modules/serve-static/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/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/serve-static/node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "node_modules/serve-static/node_modules/send/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/server-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", + "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": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" + "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": ">=10" + "node": ">= 0.4" } }, - "node_modules/string-length/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/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": ">=8" + "node": ">= 0.4" } }, - "node_modules/string-length/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "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": { - "ansi-regex": "^5.0.1" + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==" + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sf-symbols-typescript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sf-symbols-typescript/-/sf-symbols-typescript-2.1.0.tgz", + "integrity": "sha512-ezT7gu/SHTPIOEEoG6TF+O0m5eewl0ZDAO4AtdBi5HjsrUI6JdCG17+Q8+aKp0heM06wZKApRCn5olNbs0Wb/A==", "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "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": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/string-width-cjs/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/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/string-width-cjs/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/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dev": true, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -22234,31 +21209,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.repeat": { + "node_modules/side-channel-list": { "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.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dev": true, + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" @@ -22267,17 +21225,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dev": true, + "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==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" @@ -22286,16 +21243,17 @@ "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, + "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==", "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "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" @@ -22304,626 +21262,566 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", "engines": { - "node": ">=12" + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "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": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" } }, - "node_modules/strip-ansi-cjs/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/simple-plist/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": ">=8" + "node": ">= 5.10.0" } }, - "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, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "is-arrayish": "^0.3.1" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "node_modules/simple-swizzle/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/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, + "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/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "license": "MIT", "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "optional": true - }, - "node_modules/strtok3": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", - "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "node_modules/slugify": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", "license": "MIT", - "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^4.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" + "node": ">=8.0.0" } }, - "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/stubs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", - "license": "MIT" - }, - "node_modules/styled-components": { - "version": "6.1.19", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.19.tgz", - "integrity": "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA==", - "license": "MIT", - "dependencies": { - "@emotion/is-prop-valid": "1.2.2", - "@emotion/unitless": "0.8.1", - "@types/stylis": "4.2.5", - "css-to-react-native": "3.2.0", - "csstype": "3.1.3", - "postcss": "8.4.49", - "shallowequal": "1.1.0", - "stylis": "4.3.2", - "tslib": "2.6.2" - }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", "engines": { - "node": ">= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/styled-components" - }, - "peerDependencies": { - "react": ">= 16.8.0", - "react-dom": ">= 16.8.0" + "node": ">=0.10.0" } }, - "node_modules/styled-components/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "license": "0BSD" - }, - "node_modules/styleq": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/styleq/-/styleq-0.1.3.tgz", - "integrity": "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==", - "license": "MIT" - }, - "node_modules/stylis": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", - "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", - "license": "MIT" + "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/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "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==", "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/superagent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", - "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", - "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", "license": "MIT", - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.2", - "methods": "^1.1.2", - "mime": "^2.4.6", - "qs": "^6.9.4", - "readable-stream": "^3.6.0", - "semver": "^7.3.2" - }, "engines": { - "node": ">= 7.0.0" + "node": ">=6" } }, - "node_modules/superagent/node_modules/form-data": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", - "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", + "node_modules/spotify-web-api-node": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/spotify-web-api-node/-/spotify-web-api-node-5.0.2.tgz", + "integrity": "sha512-r82dRWU9PMimHvHEzL0DwEJrzFk+SMCVfq249SLt3I7EFez7R+jeoKQd+M1//QcnjqlXPs2am4DFsGk8/GCsrA==", "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.35" - }, - "engines": { - "node": ">= 6" + "superagent": "^6.1.0" } }, - "node_modules/superagent/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "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/stable-hash-x": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", + "integrity": "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==", + "dev": true, "license": "MIT", - "bin": { - "mime": "cli.js" - }, "engines": { - "node": ">=4.0.0" + "node": ">=12.0.0" } }, - "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==", + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, + "optional": true, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" + "escape-string-regexp": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "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==", + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/syllable": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/syllable/-/syllable-5.0.1.tgz", - "integrity": "sha512-HWtNCp6v7J8H0lrT8j1HHjfOLltRoDcC7QRFVu25p4BE52JqetXG65nqC7CsatT8WQRfY4Qvh93BWJIUxbmXFg==", + "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": { - "@types/pluralize": "^0.0.29", - "normalize-strings": "^1.1.0", - "pluralize": "^8.0.0" - }, - "bin": { - "syllable": "cli.js" + "type-fest": "^0.7.1" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">=6" } }, - "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", - "dev": true, + "node_modules/stacktrace-parser/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/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.2.9" - }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/synckit" + "node": ">= 0.8" } }, - "node_modules/tar": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", - "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", - "license": "BlueOak-1.0.0", + "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": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" }, "engines": { - "node": ">=18" + "node": ">= 0.4" } }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "license": "BlueOak-1.0.0", + "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": ">=18" + "node": ">= 0.10.0" } }, - "node_modules/teeny-request": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", - "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", - "license": "Apache-2.0", + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "license": "MIT", "dependencies": { - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.9", - "stream-events": "^1.0.5", - "uuid": "^9.0.0" - }, - "engines": { - "node": ">=14" + "stubs": "^3.0.0" } }, - "node_modules/teeny-request/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/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "license": "MIT" + }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", "license": "MIT", - "dependencies": { - "debug": "4" - }, "engines": { - "node": ">= 6.0.0" + "node": ">=4" } }, - "node_modules/teeny-request/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==", + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "license": "MIT", "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" + "safe-buffer": "~5.2.0" } }, - "node_modules/teeny-request/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "peer": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "node_modules/string-length/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==", + "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } }, - "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==", + "node_modules/string-length/node_modules/strip-ansi": { + "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", + "peer": true, "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" + } + }, + "node_modules/string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", - "license": "BSD-2-Clause", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/terser/node_modules/commander": { - "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==", + "node_modules/string-width-cjs/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/string-width-cjs/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/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "license": "ISC", + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": "*" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "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": { - "any-promise": "^1.0.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" } }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, "license": "MIT", "dependencies": { - "thenify": ">= 3.1.0 < 4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/thriftrw": { - "version": "3.11.4", - "resolved": "https://registry.npmjs.org/thriftrw/-/thriftrw-3.11.4.tgz", - "integrity": "sha512-UcuBd3eanB3T10nXWRRMwfwoaC6VMk7qe3/5YIWP2Jtw+EbHqJ0p1/K3x8ixiR5dozKSSfcg1W+0e33G1Di3XA==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", "dependencies": { - "bufrw": "^1.2.1", - "error": "7.0.2", - "long": "^2.4.0" - }, - "bin": { - "thrift2json": "thrift2json.js" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 0.10.x" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/thriftrw/node_modules/long": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz", - "integrity": "sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ==", - "license": "Apache-2.0", + "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.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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/timm": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", - "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==", - "license": "MIT" - }, - "node_modules/tinycolor2": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", - "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "node": ">=8" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, + "node_modules/strip-ansi-cjs/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": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "node": ">=8" } }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "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", - "peer": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=4" } }, - "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==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, + "peer": true, "engines": { - "node": ">=8.0" + "node": ">=6" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "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": ">=0.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/token-types": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", - "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", "license": "MIT", "dependencies": { "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" + "peek-readable": "^4.1.0" }, "engines": { "node": ">=10" @@ -22933,735 +21831,686 @@ "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, + "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/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", + "license": "MIT" + }, + "node_modules/styleq": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/styleq/-/styleq-0.1.3.tgz", + "integrity": "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==", + "license": "MIT" + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, "bin": { - "tree-kill": "cli.js" + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" } }, - "node_modules/trigram-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/trigram-utils/-/trigram-utils-2.0.1.tgz", - "integrity": "sha512-nfWIXHEaB+HdyslAfMxSqWKDdmqY9I32jS7GnqpdWQnLH89r6A5sdk3fDVYqGAZ0CrT8ovAFSAo6HRiWcWNIGQ==", + "node_modules/superagent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", + "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", + "deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net", "license": "MIT", "dependencies": { - "collapse-white-space": "^2.0.0", - "n-gram": "^2.0.0" + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">= 7.0.0" } }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "node_modules/superagent/node_modules/form-data": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "license": "MIT", - "optional": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" + }, "engines": { - "node": ">= 14.0.0" + "node": ">= 6" } }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "license": "MIT", - "engines": { - "node": ">=18.12" + "bin": { + "mime": "cli.js" }, - "peerDependencies": { - "typescript": ">=4.8.4" + "engines": { + "node": ">=4.0.0" } }, - "node_modules/ts-deepmerge": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/ts-deepmerge/-/ts-deepmerge-2.0.7.tgz", - "integrity": "sha512-3phiGcxPSSR47RBubQxPoZ+pqXsEsozLo4G4AlSrsMKTFg9TA3l+3he5BqpUi9wiuDbaHWXH/amlzQ49uEdXtg==", - "dev": true, - "license": "ISC" + "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==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "license": "Apache-2.0" + "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/tsc-alias": { - "version": "1.8.16", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.16.tgz", - "integrity": "sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g==", - "dev": true, + "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/syllable": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/syllable/-/syllable-5.0.1.tgz", + "integrity": "sha512-HWtNCp6v7J8H0lrT8j1HHjfOLltRoDcC7QRFVu25p4BE52JqetXG65nqC7CsatT8WQRfY4Qvh93BWJIUxbmXFg==", "license": "MIT", "dependencies": { - "chokidar": "^3.5.3", - "commander": "^9.0.0", - "get-tsconfig": "^4.10.0", - "globby": "^11.0.4", - "mylas": "^2.1.9", - "normalize-path": "^3.0.0", - "plimit-lit": "^1.2.6" + "@types/pluralize": "^0.0.29", + "normalize-strings": "^1.1.0", + "pluralize": "^8.0.0" }, "bin": { - "tsc-alias": "dist/bin/index.js" + "syllable": "cli.js" }, - "engines": { - "node": ">=16.20.2" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/tsc-alias/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "@pkgr/core": "^0.2.9" }, "engines": { - "node": ">= 8.10.0" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "url": "https://opencollective.com/synckit" } }, - "node_modules/tsc-alias/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", + "node_modules/tar": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", + "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, "engines": { - "node": "^12.20.0 || >=14" + "node": ">=18" } }, - "node_modules/tsc-alias/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 6" + "node": ">=18" } }, - "node_modules/tsc-alias/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", + "node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "license": "Apache-2.0", "dependencies": { - "picomatch": "^2.2.1" + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=14" } }, - "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, + "node_modules/teeny-request/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": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "debug": "4" + }, + "engines": { + "node": ">= 6.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, + "node_modules/teeny-request/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": { - "minimist": "^1.2.0" + "agent-base": "6", + "debug": "4" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">= 6" } }, - "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/tsup": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.5.1.tgz", - "integrity": "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==", - "dev": true, + "node_modules/teeny-request/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", - "dependencies": { - "bundle-require": "^5.1.0", - "cac": "^6.7.14", - "chokidar": "^4.0.3", - "consola": "^3.4.0", - "debug": "^4.4.0", - "esbuild": "^0.27.0", - "fix-dts-default-cjs-exports": "^1.0.0", - "joycon": "^3.1.1", - "picocolors": "^1.1.1", - "postcss-load-config": "^6.0.1", - "resolve-from": "^5.0.0", - "rollup": "^4.34.8", - "source-map": "^0.7.6", - "sucrase": "^3.35.0", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.11", - "tree-kill": "^1.2.2" - }, "bin": { - "tsup": "dist/cli-default.js", - "tsup-node": "dist/cli-node.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@microsoft/api-extractor": "^7.36.0", - "@swc/core": "^1", - "postcss": "^8.4.12", - "typescript": ">=4.5.0" - }, - "peerDependenciesMeta": { - "@microsoft/api-extractor": { - "optional": true - }, - "@swc/core": { - "optional": true - }, - "postcss": { - "optional": true - }, - "typescript": { - "optional": true - } + "uuid": "dist/bin/uuid" } }, - "node_modules/tsup/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", - "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", - "cpu": [ - "ppc64" - ], - "dev": true, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "license": "MIT", - "optional": true, - "os": [ - "aix" - ], "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsup/node_modules/@esbuild/android-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", - "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", - "cpu": [ - "arm" - ], - "dev": true, + "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", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tsup/node_modules/@esbuild/android-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", - "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/tsup/node_modules/@esbuild/android-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", - "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "node_modules/terser/node_modules/commander": { + "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==", + "license": "MIT" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/tsup/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", - "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tsup/node_modules/@esbuild/darwin-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", - "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "optional": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" } }, - "node_modules/tsup/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", - "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, "engines": { - "node": ">=18" + "node": ">=0.8" } }, - "node_modules/tsup/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", - "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "node_modules/thriftrw": { + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/thriftrw/-/thriftrw-3.11.4.tgz", + "integrity": "sha512-UcuBd3eanB3T10nXWRRMwfwoaC6VMk7qe3/5YIWP2Jtw+EbHqJ0p1/K3x8ixiR5dozKSSfcg1W+0e33G1Di3XA==", + "dependencies": { + "bufrw": "^1.2.1", + "error": "7.0.2", + "long": "^2.4.0" + }, + "bin": { + "thrift2json": "thrift2json.js" + }, "engines": { - "node": ">=18" + "node": ">= 0.10.x" } }, - "node_modules/tsup/node_modules/@esbuild/linux-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", - "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/thriftrw/node_modules/long": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz", + "integrity": "sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ==", + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=0.6" } }, - "node_modules/tsup/node_modules/@esbuild/linux-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", - "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", - "cpu": [ - "arm64" - ], + "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/timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==", + "license": "MIT" + }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, "engines": { - "node": ">=18" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tsup/node_modules/@esbuild/linux-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", - "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", - "cpu": [ - "ia32" - ], + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/tsup/node_modules/@esbuild/linux-loong64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", - "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", - "cpu": [ - "loong64" - ], + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tsup/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", - "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", - "cpu": [ - "mips64el" - ], + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=14.14" } }, - "node_modules/tsup/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", - "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", - "cpu": [ - "ppc64" - ], - "dev": true, + "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", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "is-number": "^7.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8.0" } }, - "node_modules/tsup/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", - "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", - "cpu": [ - "riscv64" - ], - "dev": true, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=0.6" } }, - "node_modules/tsup/node_modules/@esbuild/linux-s390x": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", - "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", - "cpu": [ - "s390x" - ], - "dev": true, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" } }, - "node_modules/tsup/node_modules/@esbuild/linux-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", - "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", - "cpu": [ - "x64" - ], + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "bin": { + "tree-kill": "cli.js" } }, - "node_modules/tsup/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", - "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/trigram-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/trigram-utils/-/trigram-utils-2.0.1.tgz", + "integrity": "sha512-nfWIXHEaB+HdyslAfMxSqWKDdmqY9I32jS7GnqpdWQnLH89r6A5sdk3fDVYqGAZ0CrT8ovAFSAo6HRiWcWNIGQ==", "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "collapse-white-space": "^2.0.0", + "n-gram": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/tsup/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", - "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", "license": "MIT", "optional": true, - "os": [ - "netbsd" - ], "engines": { - "node": ">=18" + "node": ">= 14.0.0" } }, - "node_modules/tsup/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", - "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", - "cpu": [ - "arm64" - ], + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], "engines": { - "node": ">=18" + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/tsup/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", - "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", - "cpu": [ - "x64" - ], + "node_modules/ts-deepmerge": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/ts-deepmerge/-/ts-deepmerge-2.0.7.tgz", + "integrity": "sha512-3phiGcxPSSR47RBubQxPoZ+pqXsEsozLo4G4AlSrsMKTFg9TA3l+3he5BqpUi9wiuDbaHWXH/amlzQ49uEdXtg==", + "dev": true, + "license": "ISC" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" + }, + "node_modules/tsc-alias": { + "version": "1.8.16", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.16.tgz", + "integrity": "sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "get-tsconfig": "^4.10.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + }, "engines": { - "node": ">=18" + "node": ">=16.20.2" } }, - "node_modules/tsup/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", - "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", - "cpu": [ - "arm64" - ], + "node_modules/tsc-alias/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, "engines": { - "node": ">=18" + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/tsup/node_modules/@esbuild/sunos-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", - "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", - "cpu": [ - "x64" - ], + "node_modules/tsc-alias/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], "engines": { - "node": ">=18" + "node": "^12.20.0 || >=14" } }, - "node_modules/tsup/node_modules/@esbuild/win32-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", - "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", - "cpu": [ - "arm64" - ], + "node_modules/tsc-alias/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, "engines": { - "node": ">=18" + "node": ">= 6" } }, - "node_modules/tsup/node_modules/@esbuild/win32-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", - "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", - "cpu": [ - "ia32" - ], + "node_modules/tsc-alias/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "picomatch": "^2.2.1" + }, "engines": { - "node": ">=18" + "node": ">=8.10.0" } }, - "node_modules/tsup/node_modules/@esbuild/win32-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", - "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", - "cpu": [ - "x64" - ], + "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", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/tsup/node_modules/esbuild": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", - "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "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, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" + "dependencies": { + "minimist": "^1.2.0" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.0", - "@esbuild/android-arm": "0.27.0", - "@esbuild/android-arm64": "0.27.0", - "@esbuild/android-x64": "0.27.0", - "@esbuild/darwin-arm64": "0.27.0", - "@esbuild/darwin-x64": "0.27.0", - "@esbuild/freebsd-arm64": "0.27.0", - "@esbuild/freebsd-x64": "0.27.0", - "@esbuild/linux-arm": "0.27.0", - "@esbuild/linux-arm64": "0.27.0", - "@esbuild/linux-ia32": "0.27.0", - "@esbuild/linux-loong64": "0.27.0", - "@esbuild/linux-mips64el": "0.27.0", - "@esbuild/linux-ppc64": "0.27.0", - "@esbuild/linux-riscv64": "0.27.0", - "@esbuild/linux-s390x": "0.27.0", - "@esbuild/linux-x64": "0.27.0", - "@esbuild/netbsd-arm64": "0.27.0", - "@esbuild/netbsd-x64": "0.27.0", - "@esbuild/openbsd-arm64": "0.27.0", - "@esbuild/openbsd-x64": "0.27.0", - "@esbuild/openharmony-arm64": "0.27.0", - "@esbuild/sunos-x64": "0.27.0", - "@esbuild/win32-arm64": "0.27.0", - "@esbuild/win32-ia32": "0.27.0", - "@esbuild/win32-x64": "0.27.0" - } - }, - "node_modules/tsup/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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "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/tsx": { "version": "4.20.6", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.6.tgz", "integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" @@ -23710,6 +22559,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", @@ -23794,7 +22656,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -23853,13 +22714,6 @@ "node": "*" } }, - "node_modules/ufo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", - "dev": true, - "license": "MIT" - }, "node_modules/uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", @@ -23959,6 +22813,16 @@ "node": ">=8" } }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -24160,6 +23024,7 @@ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", @@ -24578,6 +23443,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/winston": { + "version": "3.18.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.18.3.tgz", + "integrity": "sha512-NoBZauFNNWENgsnC9YpgyYwOVrl2m58PpQ8lNHjV3kosGs7KJ7Npk9pCUE+WJlawVSe8mykWDKWFSVfs3QO9ww==", + "license": "MIT", + "optional": true, + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.8", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/winston-transport": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", @@ -24715,6 +23603,7 @@ "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -24924,7 +23813,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -24945,7 +23833,6 @@ "zod": "^3.25.76" }, "devDependencies": { - "tsup": "^8.5.0", "typescript": "^5.9.2" } } diff --git a/package.json b/package.json index 6256678..419791a 100644 --- a/package.json +++ b/package.json @@ -9,20 +9,22 @@ ], "scripts": { "build": "npm run build --ws --if-present", - "schemas:build": "npm run build --workspace=@lymo/schemas", - "functions:start": "npm run genkit:start --workspace=@lymo/functions", - "functions:deploy": "npm run build && firebase deploy --only functions", - "frontend:start": "npm run start --workspace=@lymo/frontend", - "lint": "eslint --fix" + "be:start": "firebase emulators:start", + "be:dev": "concurrently \"npm run build:watch --workspace=@lymo/functions\" \"firebase emulators:start --import=./dev-data --export-on-exit=./dev-data\"", + "fe:start": "npm run start --workspace=@lymo/frontend", + "lint": "eslint --fix", + "postinstall": "patch-package" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^8.46.3", "@typescript-eslint/parser": "^8.46.3", + "concurrently": "^9.2.1", "eslint": "^9.25.0", "eslint-config-expo": "~10.0.0", "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.32.0", "eslint-plugin-react": "^7.37.5", + "patch-package": "^8.0.1", "typescript-eslint": "^8.44.1" } } diff --git a/packages/schemas/package.json b/packages/schemas/package.json index 807332e..9c42849 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -1,24 +1,14 @@ { "name": "@lymo/schemas", "version": "0.0.0", - "files": [ - "./dist" - ], + "sideEffects": false, "exports": { - "./*": { - "types": "./dist/*.d.ts", - "import": "./dist/*.mjs", - "require": "./dist/*.js" - } - }, - "scripts": { - "build": "tsup" + "./*": "./src/*.ts" }, "dependencies": { "zod": "^3.25.76" }, "devDependencies": { - "tsup": "^8.5.0", "typescript": "^5.9.2" } } diff --git a/packages/schemas/src/doc.ts b/packages/schemas/src/doc.ts new file mode 100644 index 0000000..1167e24 --- /dev/null +++ b/packages/schemas/src/doc.ts @@ -0,0 +1,114 @@ +import { z } from "zod"; + +import { errorCode } from "./error"; +import { LanguageSchema, LyricSchema, LyricsProvider, LyricsProviderSchema } from "./shared"; + +// ============================== +// track 관련 스키마 +// ============================== + +// `tracks/{trackId}` 문서 스키마 +export const TrackSchema = z.object({ + title: z.string(), + artists: z.string().array(), + album: z.string().nullable(), + albumArt: z.string(), + durationInSeconds: z.number(), + publishedAt: z.string().nullable(), + lyrics: z.record(LyricsProviderSchema, LyricSchema.array().optional()), + + createdAt: z.string(), + stats: z.object({ + storyCount: z.number(), + viewCount: z.number(), + }), +}); +export type Track = Omit, "lyrics"> & { + lyrics: Partial[]>>; +}; + +// ============================== +// story 관련 스키마 +// ============================== + +// 공통 필드 +export const BaseStoryFieldsSchema = z.object({ + userId: z.string(), + userName: z.string(), + userAvatar: z.string().nullable(), + + language: LanguageSchema, + lyricsProvider: LyricsProviderSchema, + + updatedAt: z.string(), + stats: z.object({ + favoriteCount: z.number(), + viewCount: z.number(), + }), +}); +export type BaseStoryFields = z.infer; + +// track 정보 필드 +export const TrackInfoFieldsSchema = z.object({ + trackId: z.string(), + trackTitle: z.string(), + trackArtists: z.string().array(), + trackAlbum: z.string().nullable(), + trackAlbumArt: z.string(), +}); + +// AI 생성 필드 +export const GeneratedStoryFieldsSchema = z.object({ + overview: z.string(), + sectionBreaks: z.number().array(), + lyricTranslations: z.string().nullable().array(), + sectionNotes: z.string().nullable().array(), +}); +export type GeneratedStoryFields = z.infer; + +// `stories/{storyId}` 문서 스키마 +export const StorySchema = BaseStoryFieldsSchema.merge(TrackInfoFieldsSchema).merge( + GeneratedStoryFieldsSchema +); +export type Story = z.infer; + +// ============================== +// storyRequest 관련 스키마 +// ============================== + +// `storyRequests/{storyRequestId}` 문서 스키마 +export const StoryRequestSchema = z.union([ + // status가 PENDING일 경우 + z.union([ + z.object({ + status: z.literal("PENDING"), + language: LanguageSchema, + trackId: z.string(), + }), + + z.object({ + status: z.literal("PENDING"), + language: LanguageSchema, + title: z.string(), + artist: z.string(), + durationInSeconds: z.number(), + }), + ]), + + // status가 IN_PROGRESS일 경우 + BaseStoryFieldsSchema.merge(GeneratedStoryFieldsSchema.partial()).extend({ + status: z.literal("IN_PROGRESS"), + }), + + // status가 COMPLETED일 경우 + BaseStoryFieldsSchema.merge(GeneratedStoryFieldsSchema).extend({ + status: z.literal("COMPLETED"), + }), + + // status가 FAILED일 경우 + z.object({ + status: z.literal("FAILED"), + errorCode: errorCode, + }), +]); +export type StoryRequest = z.infer; diff --git a/packages/schemas/src/error.ts b/packages/schemas/src/error.ts new file mode 100644 index 0000000..b33ae42 --- /dev/null +++ b/packages/schemas/src/error.ts @@ -0,0 +1,32 @@ +import z from "zod"; + +export const errorCode = z.enum([ + // 외부 API에서 곡 정보를 검색하는 데 실패한 경우 + "EXTERNAL_TRACK_NOT_FOUND", + + // 외부 API에서 가사 정보를 검색하는 데 실패한 경우 + "EXTERNAL_LYRICS_NOT_FOUND", + + // DB에서 곡 정보를 찾을 수 없는 경우 + "TRACK_NOT_FOUND", + + // DB에서 해석 정보를 찾을 수 없는 경우 + "STORY_NOT_FOUND", + + // DB에서 가사 정보를 찾을 수 없는 경우 + "LYRICS_NOT_FOUND", + + // AI 생성이 실패한 경우 + "AI_GENERATION_FAILED", + + // 해석 정보를 DB에 저장하는 데 실패한 경우 + "STORY_SAVE_FAILED", + + // 곡 정보를 DB에 저장하는 데 실패한 경우 + "TRACK_SAVE_FAILED", + + // 잘못된 입력이 제공된 경우 + "INVALID_INPUT", +]); +export const ERROR_CODES = errorCode.enum; +export type ErrorCode = z.infer; diff --git a/packages/schemas/src/functions.ts b/packages/schemas/src/functions.ts new file mode 100644 index 0000000..37c9af5 --- /dev/null +++ b/packages/schemas/src/functions.ts @@ -0,0 +1,45 @@ +import { z } from "zod"; + +import { TrackSchema } from "./doc"; +import { errorCode } from "./error"; + +// ============================== +// 공통 스키마 +// ============================== +const CommonOutputSchema = (schema: T) => + z.union([ + z.object({ + success: z.literal(true), + data: schema, + }), + + z.object({ + success: z.literal(false), + error: errorCode, + message: z.string().optional(), + }), + ]); + +// ============================== +// retrieveTrack 관련 스키마 +// ============================== +export const RetrieveTrackInputSchema = z.union([ + z.object({ + trackId: z.string(), + }), + + z.object({ + title: z.string(), + artist: z.string(), + durationInSeconds: z.number(), + }), +]); +export type RetrieveTrackInput = z.infer; + +export const RetrieveTrackOutputSchema = CommonOutputSchema( + z.object({ + id: z.string(), + data: TrackSchema, + }) +); +export type RetrieveTrackOutput = z.infer; diff --git a/packages/schemas/src/shared.ts b/packages/schemas/src/shared.ts new file mode 100644 index 0000000..6ec3e11 --- /dev/null +++ b/packages/schemas/src/shared.ts @@ -0,0 +1,26 @@ +import { z } from "zod"; + +// 가사 문장 스키마 +export const LyricSchema = z.object({ + text: z.string(), + start: z.number(), + end: z.number(), +}); +export type Lyric = z.infer; + +// 언어 스키마 +export const LanguageSchema = z.enum(["en", "ko"]); +export type Language = z.infer; + +// 가사 제공자 스키마 +export const LyricsProviderSchema = z.enum(["lrclib", "none"]); +export type LyricsProvider = z.infer; + +// 해석 생성 상태 +export const StoryGenerationStatusSchema = z.enum([ + "PENDING", + "IN_PROGRESS", + "COMPLETED", + "FAILED", +]); +export type StoryGenerationStatus = z.infer; diff --git a/packages/schemas/src/track/doc.ts b/packages/schemas/src/track/doc.ts deleted file mode 100644 index 3b88a47..0000000 --- a/packages/schemas/src/track/doc.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { z } from "zod"; - -import { LyricsProviderSchema } from "./shared"; - -/** - * Track 문서 - * - * 문서 경로: `tracks/{trackId}` - */ -export const TrackDocSchema = z.object({ - album: z.string().nullable(), - artist: z.array(z.string()), - coverUrl: z.string(), - duration: z.number(), - publishedAt: z.string().nullable(), - title: z.string(), - createdAt: z.string(), - lyricsProviders: z.array(LyricsProviderSchema), - play: z.number(), -}); -export type TrackDoc = z.infer; - -/** - * Track 가사 문서 - * - * 문서 경로: `tracks/{trackId}/lyrics/{lyricsProvider}` - */ -export const LyricsDocSchema = z.object({ - lyrics: z.array( - z.object({ - text: z.string(), - start: z.number(), - end: z.number(), - }) - ), -}); -export type LyricsDoc = z.infer; - -/** - * 제공자 문서 - * - * 문서 경로: `tracks/{trackId}/providers/{providerId}` - */ -export const ProviderDocSchema = z.object({ - createdAt: z.string(), - updatedAt: z.string(), - providerName: z.string(), -}); -export type ProviderDoc = z.infer; - -/** - * Track 상세 문서 - * - * 문서 경로: `tracks/{trackId}/providers/{providerId}/details/{language}` - */ -export const TrackDetailDocSchema = z.object({ - summary: z.string(), - lyricsSplitIndices: z.array(z.number()), - lyricsProvider: LyricsProviderSchema, - translations: z.array(z.string().nullable()), - paragraphSummaries: z.array(z.string().nullable()), -}); -export type TrackDetailDoc = z.infer; diff --git a/packages/schemas/src/track/event.ts b/packages/schemas/src/track/event.ts deleted file mode 100644 index 51907ab..0000000 --- a/packages/schemas/src/track/event.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { z } from "zod"; - -import { LyricsProviderSchema } from "./shared"; - -/** - * 가사 제공자 설정 이벤트 - */ -export const LyricsProviderSetEventSchema = z.object({ - event: z.literal("lyrics_provider_set"), - data: z.object({ - lyricsProvider: LyricsProviderSchema, - }), -}); - -/** - * 가사 문장 번역 설정 이벤트 - */ -export const TranslationSetEventSchema = z.object({ - event: z.literal("translation_set"), - data: z.object({ - sentenceIndex: z.number(), - text: z.string().nullable(), - }), -}); -export type TranslationSetEvent = z.infer; - -/** - * 가사 문단 구분 이벤트 - */ -export const LyricsGroupEventSchema = z.object({ - event: z.literal("lyrics_group"), - data: z.array(z.number()), -}); -export type LyricsGroupEvent = z.infer; - -/** - * 곡 요약 append 이벤트 - */ -export const SummaryAppendEventSchema = z.object({ - event: z.literal("summary_append"), - data: z.object({ - summary: z.string(), - }), -}); -export type SummaryAppendEvent = z.infer; - -/** - * 문단 요약 append 이벤트 - */ -export const ParagraphSummaryAppendEventSchema = z.object({ - event: z.literal("paragraph_summary_append"), - data: z.object({ - paragraphIndex: z.number(), - summary: z.string(), - }), -}); -export type ParagraphSummaryAppendEvent = z.infer; - -/** - * 제공자 설정 이벤트 - */ -export const ProviderSetEventSchema = z.object({ - event: z.literal("provider_set"), - data: z.object({ - createdAt: z.string(), - updatedAt: z.string(), - providerName: z.string(), - providerId: z.string(), - }), -}); - -/** - * 스트리밍 완료 이벤트 - */ -export const CompleteEventSchema = z.object({ - event: z.literal("complete"), - data: z.null(), -}); diff --git a/packages/schemas/src/track/function.ts b/packages/schemas/src/track/function.ts deleted file mode 100644 index c92f2cd..0000000 --- a/packages/schemas/src/track/function.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { z } from "zod"; - -import { LyricsDocSchema, TrackDocSchema } from "./doc"; -import { - CompleteEventSchema, - LyricsGroupEventSchema, - LyricsProviderSetEventSchema, - ParagraphSummaryAppendEventSchema, - ProviderSetEventSchema, - SummaryAppendEventSchema, - TranslationSetEventSchema, -} from "./event"; -import { LanguageSchema, LLMModelSchema, LyricsProviderSchema } from "./shared"; - -/** - * addTrackFlow 입력 - */ -export const AddTrackFlowInputSchema = z.object({ - title: z.string(), - artist: z.string(), - duration: z.number().positive(), -}); -export type AddTrackFlowInput = z.infer; - -/** - * addTrackFlow 출력 - */ -export const AddTrackFlowOutputSchema = z.union([ - z.object({ - id: z.string(), - track: TrackDocSchema, - lyrics: LyricsDocSchema.shape.lyrics, - lyricsProvider: LyricsProviderSchema, - notFound: z.literal(false), - }), - - z.object({ - id: z.undefined(), - track: z.undefined(), - lyrics: z.undefined(), - lyricsProvider: z.undefined(), - notFound: z.literal(true), - }), -]); -export type AddTrackFlowOutput = z.infer; - -/** - * generateDetailFlow 입력 - */ -export const GenerateDetailFlowInputSchema = z.object({ - id: z.string(), - language: LanguageSchema, - lyricsProvider: LyricsProviderSchema.optional(), - model: LLMModelSchema.optional(), -}); -export type GenerateDetailFlowInput = z.infer; - -/** - * generateDetailFlow 스트림 - */ -export const GenerateDetailFlowStreamSchema = z.discriminatedUnion("event", [ - LyricsProviderSetEventSchema, - TranslationSetEventSchema, - LyricsGroupEventSchema, - SummaryAppendEventSchema, - ParagraphSummaryAppendEventSchema, - ProviderSetEventSchema, - CompleteEventSchema, -]); -export type GenerateDetailFlowStream = z.infer; - -/** - * generateDetailFlow 출력 - */ -export const GenerateDetailFlowOutputSchema = z.union([ - z.object({ - providerId: z.string(), - success: z.literal(true), - exists: z.literal(true), - }), - - z.object({ - providerId: z.undefined(), - success: z.literal(true), - exists: z.literal(false), - }), - - z.object({ - providerId: z.undefined(), - success: z.literal(false), - exists: z.literal(false), - }), -]); -export type GenerateDetailFlowOutput = z.infer; diff --git a/packages/schemas/src/track/shared.ts b/packages/schemas/src/track/shared.ts deleted file mode 100644 index 1a7a6ac..0000000 --- a/packages/schemas/src/track/shared.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { z } from "zod"; - -/** - * 가사 문장 - */ -export const LyricsSentenceSchema = z.object({ - text: z.string().min(1), - translation: z.string().min(1).nullable(), - start: z.number().nonnegative(), - end: z.number().nonnegative(), -}); -export type LyricsSentence = z.infer; - -/** - * 여러 가사 문장들로 구성된 문단 - */ -export const LyricsParagraphSchema = z.object({ - sentences: z.array(LyricsSentenceSchema), - summary: z.string().nullable(), -}); -export type LyricsParagraph = z.infer; - -/** - * 여러 문단으로 구성된 가사 - */ -export const LyricsSchema = z.array(LyricsParagraphSchema); -export type Lyrics = z.infer; - -/** - * 곡 정보 - */ -export const TrackSchema = z.object({ - id: z.string().min(1), - album: z.string().min(1).nullable(), - artist: z.array(z.string()), - coverUrl: z.string(), - duration: z.number().positive(), - publishedAt: z.string().nullable(), - title: z.string().min(1), - createdAt: z.string(), - providers: z.array(z.string()), -}); -export type Track = z.infer; - -/** - * 곡 상세 정보 - */ -export const TrackDetailSchema = z.object({ - lyrics: LyricsSchema, - lyricsProvider: z.string(), - summary: z.string(), -}); -export type TrackDetail = z.infer; - -/** - * 언어 - */ -export const LanguageSchema = z.enum(["en", "ko"]); -export type Language = z.infer; - -/** - * 가사 제공자 - */ -export const LyricsProviderSchema = z.enum(["lrclib", "none"]); -export type LyricsProvider = z.infer; - -/** - * AI 모델 - */ -export const LLMModelSchema = z.enum(["gemini-2.5-flash", "gemini-2.5-flash-lite"]); -export type LLMModel = z.infer; diff --git a/packages/schemas/tsup.config.ts b/packages/schemas/tsup.config.ts deleted file mode 100644 index e967ce0..0000000 --- a/packages/schemas/tsup.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from "tsup"; - -export default defineConfig({ - entry: ["src/**/*.ts"], - format: ["cjs", "esm"], - dts: true, - splitting: false, - sourcemap: true, - clean: true, -}); diff --git a/patches/@genkit-ai+ai+1.24.0.patch b/patches/@genkit-ai+ai+1.24.0.patch new file mode 100644 index 0000000..02c14c8 --- /dev/null +++ b/patches/@genkit-ai+ai+1.24.0.patch @@ -0,0 +1,15 @@ +# genkit의 generateStream stream 제네릭 타입 패치 + +diff --git a/node_modules/@genkit-ai/ai/lib/generate-CGXKfudO.d.ts b/node_modules/@genkit-ai/ai/lib/generate-CGXKfudO.d.ts +index de6b11f..2e0318c 100644 +--- a/node_modules/@genkit-ai/ai/lib/generate-CGXKfudO.d.ts ++++ b/node_modules/@genkit-ai/ai/lib/generate-CGXKfudO.d.ts +@@ -463,7 +463,7 @@ declare function generateOperation(registry: Registry, options: GenerateOptions): Promise; + type GenerateStreamOptions = Omit, 'streamingCallback'>; + interface GenerateStreamResponse { +- get stream(): AsyncIterable; ++ get stream(): AsyncIterable>; + get response(): Promise>; + } + declare function generateStream(registry: Registry, options: GenerateOptions | PromiseLike>): GenerateStreamResponse; diff --git a/scripts/postdeploy.js b/scripts/postdeploy.js deleted file mode 100644 index 6476bfd..0000000 --- a/scripts/postdeploy.js +++ /dev/null @@ -1,53 +0,0 @@ -// 🔽 모듈 import 방식을 ESM으로 변경 -import { execSync } from "child_process"; -import fs from "fs"; -import path from "path"; -import { fileURLToPath } from "url"; - -// 🔽 ESM에서 __dirname을 사용하기 위한 코드 -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -console.log("🧹 Starting postdeploy cleanup script..."); - -// --- 경로 설정 --- -const rootPath = path.resolve(__dirname, ".."); -const functionsPath = path.join(rootPath, "apps", "functions"); -const functionsPackageJsonPath = path.join(functionsPath, "package.json"); - -try { - // 1. @lymo/functions의 package.json을 원래대로 복구합니다. - const packageJson = JSON.parse( - fs.readFileSync(functionsPackageJsonPath, "utf8") - ); - - if (packageJson.originalDependencies) { - packageJson.dependencies = packageJson.originalDependencies; - delete packageJson.originalDependencies; - fs.writeFileSync( - functionsPackageJsonPath, - JSON.stringify(packageJson, null, 2) - ); - console.log(`✅ Restored dependencies in ${functionsPackageJsonPath}`); - } else { - console.log("No originalDependencies found, trying to restore with git..."); - execSync(`git restore ${functionsPackageJsonPath}`); - console.log(`✅ Restored ${functionsPackageJsonPath} using git.`); - } - - // 2. @lymo/functions 폴더에 생성되었던 .tgz 파일을 삭제합니다. - const files = fs.readdirSync(functionsPath); - const tgzFile = files.find( - (file) => file.startsWith("lymo-schemas-") && file.endsWith(".tgz") - ); - - if (tgzFile) { - fs.unlinkSync(path.join(functionsPath, tgzFile)); - console.log(`🗑️ Deleted temporary package file: ${tgzFile}`); - } - - console.log("✨ Postdeploy cleanup finished successfully!"); -} catch (error) { - console.error("🔥 An error occurred during the postdeploy script:"); - console.error(error); -} diff --git a/scripts/predeploy.js b/scripts/predeploy.js deleted file mode 100644 index ca45131..0000000 --- a/scripts/predeploy.js +++ /dev/null @@ -1,54 +0,0 @@ -// 🔽 모듈 import 방식을 ESM으로 변경 -import { execSync } from "child_process"; -import fs from "fs"; -import path from "path"; -import { fileURLToPath } from "url"; - -// 🔽 ESM에서 __dirname을 사용하기 위한 코드 -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -console.log("🚀 Starting predeploy script for Firebase Functions..."); - -// --- 경로 설정 --- -const rootPath = path.resolve(__dirname, ".."); // 이제 이 코드가 정상 동작합니다. -const schemasPath = path.join(rootPath, "packages", "schemas"); -const functionsPath = path.join(rootPath, "apps", "functions"); -const functionsPackageJsonPath = path.join(functionsPath, "package.json"); - -try { - // 1. @lymo/schemas 패키지를 .tgz 파일로 압축합니다. - console.log(`📦 Packing @lymo/schemas at ${schemasPath}...`); - const packedFileName = execSync("npm pack", { cwd: schemasPath }) - .toString() - .trim(); - const packedFilePath = path.join(schemasPath, packedFileName); - console.log(`✅ Packed successfully: ${packedFileName}`); - - // 2. 압축된 파일을 @lymo/functions 폴더로 이동합니다. - const destPath = path.join(functionsPath, packedFileName); - fs.renameSync(packedFilePath, destPath); - console.log(`🚚 Moved ${packedFileName} to ${functionsPath}`); - - // 3. @lymo/functions의 package.json을 수정합니다. - console.log(`✏️ Modifying ${functionsPackageJsonPath}...`); - const packageJson = JSON.parse( - fs.readFileSync(functionsPackageJsonPath, "utf8") - ); - - packageJson.originalDependencies = packageJson.originalDependencies || { - ...packageJson.dependencies, - }; - packageJson.dependencies["@lymo/schemas"] = `file:./${packedFileName}`; - - fs.writeFileSync( - functionsPackageJsonPath, - JSON.stringify(packageJson, null, 2) - ); - console.log("✅ package.json modified for deployment."); - console.log("✨ Predeploy script finished successfully!"); -} catch (error) { - console.error("🔥 An error occurred during the predeploy script:"); - console.error(error); - process.exit(1); -}